spring IOC源码解读

本文从直接调用的ClassPathXmlApplicationContext开始说起,看看spring是怎么实现IOC/DI

1.spring应用代码

其中singer.xml是自定义的

DIMp3类是自定义的。

public static void main(String[] args) {
//spring通过应用上下文装载bean的定义并组装
//使用spring实现的ClassPathXmlApplicationContext加载配置文件
@SuppressWarnings("resource")
ApplicationContext context = new ClassPathXmlApplicationContext("singer.xml");

//从应用上下文中获取bean
DIMp3 mp3 = (DIMp3) context.getBean("mp3");

mp3.play();
}


2.ClassPathXmlApplicationContext:获取容器

ClassPathXmlApplicationContext("singer.xml"); 实际调用的是

/**

* 使用configLocations指定配置文件去构造一个spring容器

* refresh是否刷新容器,默认true(具体的刷新后面讲解)

* parent: 当前容器父级容器

*/

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}

2.1 super(parent):给定parent创建父级容器

实际调用的是
public AbstractApplicationContext(ApplicationContext parent) {
this.resourcePatternResolver = getResourcePatternResolver();//返回一个PathMatchingResourcePatternResolver对象
this.parent = parent;
if (parent != null) {
Environment parentEnvironment = parent.getEnvironment();
if (parentEnvironment instanceof ConfigurableEnvironment) {
getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
}
}//将父级容器运行时环境合并到当前容器运行时环境。
}

2.2 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;
}
}

2.3 refresh():这一步是真正的创建容器加载bean

public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//这步无关紧要,就是设置一下开始刷新时间,开始记录日志,检查是否运行时环境变量是完整的
// Prepare this context for refreshing.
prepareRefresh();


// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
1.beanFactory是否存在,存在就销毁:destroyBeans();
2.根据父级beanFactory创建一个新的beanFactory:createBeanFactory();
3.定制当前的beanFactory(主要是设置对注解的支持):customizeBeanFactory(beanFactory);
4.加载XmlBeanDefinitionReader:loadBeanDefinitions(beanFactory);


// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
1.为beanFactory加载一个ContextClassLoader:beanFactory.setBeanClassLoader(getClassLoader());
2.加载一个BeanExpressionResolver去解析spring的el表达式例如#{}:beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
3.加载一个资源加载器ResourceLoader加载classpath以及一些file资源,加载一个PropertyResolver,去获取一些属性文件信 息:beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
4.加载一个BeanPostProcessor,这个处理器提供两个回调方法给spring创建bean的过程中回调。书面上交spring扩展 点:beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
5.最后是注册一些环境变量。


try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
在ApplicationContext初始化后,修改context的 beanFactory



// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
在单例应用bean之前实例化所有的 BeanFactoryPostProcessor并调用


// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
在实例化应用bean之前实例化所有的 BeanFactoryPostProcessor并调用


// Initialize message source for this context.
initMessageSource();
使用父级messageSource初始化本context国际化组件,如果父级没有,创建一个新的 beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);


// Initialize event multicaster for this context.
initApplicationEventMulticaster();
使用实例化一个在context自定义的时间广播器,如果没有自定义的用默认的SimpleApplicationEventMulticaster


// Initialize other special beans in specific context subclasses.
onRefresh();


// Check for listener beans and register them.
registerListeners();


// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);


// Last step: publish corresponding event.
finishRefresh();
}


catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
destroyBeans();


// Reset 'active' flag.
cancelRefresh(ex);


// Propagate exception to caller.
throw ex;
}
}
}

3.IOC相关类说明

至此,bean已经实例化完毕。更多细节参考:
http://www.iteye.com/topic/1122859

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值