在这篇文章中,我将用第一人称的方式向你阐述spring4.2.1.RELEASE IOC部分的基本架构,你可以用如下的简单demo开启源码debug之旅demo包含三个文件User.javapublic class User { @Override public String ...
在这篇文章中,我将用第一人称的方式向你阐述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
(#换成@)。