Spring iOC主流程初始化方法org.springframework.context.support.AbstractApplicationContext#refresh方法
##### 启动测试类
@Test
public void beanTest(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Result bean = context.getBean(Result.class);
context.close();
}
}
1.ClassPathXmlApplicationContext 构造方法
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
调用了另一个构造方法
2. ClassPathXmlApplicationContext
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
/**
* 初始化父类
*/
super(parent);
/**
* 设置本地资源配置
*/
setConfigLocations(configLocations);
/**
* 完成Spring Bean的初始化
*/
if (refresh) {
/**
* 构造方法
*/
refresh();
}
}
父上下文是空
设置配置文件setLocation
public void setConfigLocations(@Nullable 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;
}
}
refresh()核心方法
public void refresh() throws BeansException, IllegalStateException {
/**
* 加锁,说明并发执行,很多地方都有调用
* registerShutdownHook 也调用了
* close()方法也调有了,
* 容器在启动时,不能调Close的方法
*/
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
/**
* 预初始化
*/
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
/**
*
* 创建BeanFactory工厂,告诉子类去刷新内部BeanFactory,
* 加载Bean信息,并封装为BeanDefinition,并注册到BeanDefinitionRegistry
* key-value key :bean的id value就是BeanDefinition
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
/**
* 准备BeanFactory,进行一些设置
* Context的类加载器
*/
prepareBeanFactory(beanFactory);
try {
/**
* BeanFactory准备完成后,后置处理器增强,空方法
*/
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
/**
* 实例化实现了BeanFactoryPostProcessor接口的类中构造方法
* 并调用用postProcessBeanFactory 方法
*
*/
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
/**
*将实现了BeanPostProcessor的构造方法
*/
registerBeanPostProcessors(beanFactory);
/**
* 初始化国际华资源MessageSource组牛
*/
// Initialize message source for this context.
initMessageSource();
/**
* 初始化事件派发器
*/
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
/**
* 空方法
* 如果子类重写了这个方法就,调用子类重写的方法tomcat jetty之类的
*/
// Initialize other special beans in specific context subclasses.
onRefresh();
/**
* 注册应用监听器就是实现了ApplicationContextListener接口Bean
*/
// Check for listener beans and register them.
registerListeners();
/**
* 执行构造方法1
* setter方法2
* 实现了BeanNameAware接口的setBeanName方法3
* 实现了BeanFactoryAware接口的 setBeanFactory(BeanFactory beanFactory)方法4
* 实现了ApplicationContextAware接口的setsetApplicationContext 方法5
* 实现了BeanPostProcessor接口的postProcessBeforeInitialization方法6 ,AOP原理
* 标有PostConstruct注解的方法 7
* 实现了InitializingBean接口的afterPropertiesSet方法8
* 调用配置了init-method方法 9
* 实现了BeanPostProcessor接口的postProcessAfterInitialization方法 10
*
*/
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
/**
* 完成刷新Context,主要调用org.springframework.context.LifecycleProcessor接口onRefresh方法,发布事件ContextRefreshedEvent事件
*/
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
/**
* 销毁Bean
*/
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
/**
* 重置Active标志为false
* this.active.set(false);
*/
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
/**
* 清空缓存
*/
resetCommonCaches();
}
}
}