你的位置:首页 > 软件开发 > Java > 白话文剖析[spring4.2.1.RELEASE] IOC核心架构

白话文剖析[spring4.2.1.RELEASE] IOC核心架构

发布时间:2015-12-05 16:00:07
在这篇文章中,我将用第一人称的方式向你阐述spring4.2.1.RELEASE IOC部分的基本架构,你可以用如下的简单demo开启源码debug之旅demo包含三个文件User.javapublic class User { @Override public String ...

白话文剖析[spring4.2.1.RELEASE] IOC核心架构

在这篇文章中,我将用第一人称的方式向你阐述spring4.2.1.RELEASE IOC部分的基本架构,你可以用如下的简单demo开启源码debug之旅

demo包含三个文件


User.java

public class User {  @Override  public String toString() {    return hi, I am a user!;  }}

user.

  

UserTest.java

public class UserTest {  public static void main(String[] args) {    ApplicationContext context = new ClassPath

UserTest.java 中通过ClassPath 创建了一个上下文,getBean 的方式可以拿到该bean

我们直接进到new ClassPath 看看我到底做了什么事情~_~

ClassPath

public ClassPath

调用

public ClassPath

上面的函数先调用super(parent) 层层往上调用,最终发现做了这么一件事情

AbstractApplicationContext.java

public AbstractApplicationContext() {    this.resourcePatternResolver = getResourcePatternResolver();}

resourcePatternResolver 这从字面上就可以知道这家伙是做资源解析的用的呢,查看一下ResourcePatternResolver 的定义,发现重点只有这么一行

ResourcePatternResolver.java

  Resource[] getResources(String locationPattern) throws IOException;

这里的 locationPattern 代表实际的资源路径(基本上就等同于Resource, 好了,初次看spring源码了解到这里就够了,关于 Resource的深入里面后面会后专题分析!

继续下面一行

setConfigLocations(configLocations);

public void setConfigLocations(String... locations) {    if (locations != null) {      Assert.noNullElements(locations, Config locations must not be null);      this.configLocations = new String[locations.length];      for (int i = 0; i < locations.length; i++) {        this.configLocations[i] = resolvePath(locations[i]).trim();      }    }    else {      this.configLocations = null;    }}

这一句的作用就是将创建ApplicationContext传入进来的ch0/user. 转换为合法的location,将location里面类似${key} 的placeHolder 转换为实际的值

protected String resolvePath(String path) {    return getEnvironment().resolveRequiredPlaceholders(path);}

而转换过程中会通过getEnviroment()拿到ConfigurableEnvironment对象来进行占位符${}的替换,标准的Enviroment对象为

StandardEnvironment.java

public class StandardEnvironment extends AbstractEnvironment {  public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = systemEnvironment;  public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = systemProperties;  @Override  protected void customizePropertySources(MutablePropertySources propertySources) {    propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));    propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));  }}

可以看到在设置替换placeHolder的源的时候,最终会通过getProperties(),和System.getenv()来获取启动jvm的时候的环境变量和系统环境变量,也就是说,如果你传入的location里面有个${key} 占位,而jvm参数或者系统环境变量里面刚好有个变量叫做key 那么spring在解析该location的时候,会将该占位解析为对应的value


接下来,到了

if (refresh) {  refresh();}

这一行可是我的重头戏啊,我的核心功能都在这个refresh() 方法里面搞定哦我又可以发布事件ApplicationEventPublisher, 又可以通过文件路径解析资源ResourcePatternResolver, 还可以处理国际化MessageSource, 还可以创建bean,获取beanListableBeanFactory,并且我可以告诉你我的父工厂是谁HierarchicalBeanFactory, 甚至可以告诉你我现在处在什么环境中 EnvironmentCapable,好啦,我是不是很牛逼,算了,低调,低调,哈哈哈

可以看到,我内部的对象管理也是通过注册bean来实现的哦,和你定义的bean没啥本质区别啦

晕啊晕,赶紧回忆一下我们到讲到哪一行了,快看,还是在refresh方法里面没出来啊==<喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" >vcD4NCjxoMiBpZD0="postprocessbeanfactorybeanfactory">postProcessBeanFactory(beanFactory);

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {}

是的,你没看错,这行里面啥都没,但是,仔细看哦,这个是protected方法,你懂的,我可以留给我的子类来扩展这个方法做一些更牛逼的事情

转啊转,转到下面这一行,这一行告诉你,我的工厂中制作bean的原料(BeanDefinition)准备好了, 准备好之后,我可以给你一个机会更改这些原料,你通过向我注册BeanFactoryPostProcessor就可以达到你不可告人的秘密, 在这里,你可以做任何事情,甚至将我的工厂炸毁掉也行啊(搞坏所有的原料)

void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

好了,还是看看我是怎么调用你给我注册的这些后置处理器的吧

invokeBeanFactoryPostProcessors(beanFactory);

调用

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());}

继续转啊转转到这个类

PostProcessorRegistrationDelegate.java

这个类是在2013-8-28,Juergen Hoeller 这家伙重构过的, since spring 4.0,主要处理一些后置处理器相关的复杂的操作,由于函数体过于庞大,这里我就带你深入到内部去剖析,带你装逼带你飞

首先,我简要的告诉你这段代码做了什么事情,看到传入的beanFactoryPostProcessors参数没有,所有的beanFactoryPostProcessor中,他们是最先被执行的哦,他们是通过调用

AbstractApplicationContext

public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor beanFactoryPostProcessor) {    this.beanFactoryPostProcessors.add(beanFactoryPostProcessor);}

加入到成员变量 beanFactoryPostProcessors, 然后通过

public List getBeanFactoryPostProcessors() {    return this.beanFactoryPostProcessors;}

传到这里来的

这里的 BeanFactoryPostProcessors 可以分为两种,一种是非常普通的,一种是BeanDefinitionRegistryPostProcessor, 字面上意思也可以看的出来,这玩意功能更多呀,

原标题:白话文剖析[spring4.2.1.RELEASE] IOC核心架构

关键词:Spring

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。

可能感兴趣文章

我的浏览记录