前言
我们将通过Spring(具体版本为:4.3.9.RELEASE)注解的方式来分析IOC容器的创建过程,主要通过AnnotationConfigApplicationContext
类。入口程序如下
@Test
public void test(){
AnnotationConfigApplicationContext applicationContext = new
AnnotationConfigApplicationContext(MainConfig.class);
System.out.println("IOC容器创建完毕");
Object person = applicationContext.getBean("person");
Person person1 = applicationContext.getBean(Person.class);
System.out.println(person == person1);
}
其中MainConfig
是Spring的注解配置类,其代码如下
@Configuration
public class MainConfig {
/**
* @Bean注解的value属性用来定义注册到IOC容器中的bean name
* 如果不指定value属性,则用方法名作为bean name
* @return
*/
@Bean(value = "person")
public Person getPerson(){
Person person = new Person();
person.setName("Jerry");
person.setAge(18);
person.setNickName("J");
return person;
}
}
AnnotationConfigApplicationContext的继承体系
AnnotationConfigApplicationContext继承体系图由上图可知,
AnnotationConfigApplicationContext
是ApplicationContext
接口某个具体实现类,而ApplicationContext
是BeanFactory
的子接口。所以我们可以将AnnotationConfigApplicationContext
看成是一种BeanFactory
,他们的本质都是一样的。
ApplicationContext和BeanFactory都是用于加载Bean的,这两个类都可以看成是Spring IOC容器,但是ApplicationContext比BeanFactory提供了更多的扩展功能。
常见的ApplicationContext
上图中用红框框起来的是一些常见的
ApplicationContext
,它们用于各种不同的场景。在这些类实例化的过程中,都会直接或间接的调用AbstractApplicationContext.refresh()
方法。而AbstractApplicationContext.refresh()
方法的执行过程就是IOC容器的创建过程。下面来分析一下refresh()方法的执行过程。
refresh()执行流程
refresh()
方法很重要,它是各种IOC容器初始化的入口。首先需要知道的是refresh()
方法运用了“模板方法”的设计模式,后面会出个专栏分析Spring中运用的设计模式。先来看看refresh()
的源码
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 准备上下文信息
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 2. 初始化BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 对BeanFactory进行功能填充
prepareBeanFactory(beanFactory);
try {
// 4. 子类覆盖的方法,用于做特殊的处理,这是个钩子方法
postProcessBeanFactory(beanFactory);
// 5. 激活各种BeanFactoryPostProcessor处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册各种Bean的后置处理器,后置处理器的调用发生在getBean
registerBeanPostProcessors(beanFactory);
// 7. 国际化处理
initMessageSource();
// 8. 在容器中初始化消息广播器
initApplicationEventMulticaster();
// 9. 子类覆盖的方法,各⼦类来初始化其他的bean,钩子方法
onRefresh();
// 10. 注册Listener到消息广播器中
registerListeners();
// 11. 初始化剩余的所有非懒加载的单实例bean
finishBeanFactoryInitialization(beanFactory);
// 12. 发送ContextRefreshEvent广播,完成刷新过程
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// 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...
// 13. 清除缓存
resetCommonCaches();
}
}
}
refresh()
正常执行完毕,即表明创建好IOC容器。分析源码可以知道refresh()
方法做了13件事。
- 准备上下文信息;
- 创建BeanFactory;
- 对BeanFactory进行功能填充;
- 子类覆盖的方法,用于做特殊的处理,这是个钩子方法;
- 激活各种BeanFactoryPostProcessor处理器;
- 注册各种Bean的后置处理器,后置处理器的调用发生在getBean;
- 国际化处理;
- 在容器中初始化消息广播器;
- 子类覆盖的方法,各⼦类来初始化其他的bean,钩子方法;
- 注册Listener到消息广播器中;
- 初始化剩余的所有非懒加载的单实例bean;
- 发送ContextRefreshEvent广播,完成刷新过程;
- 清除缓存。
1. 准备上下文信息
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// 初始化property资源,扩展点,留给子类实现
initPropertySources();
// 验证需要的配置文件是否加载到环境中
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
2. 创建BeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
这个方法执行完毕之后,ApplicationContext
就拥有了BeanFactory
的功能。这段代码做了两件事:2.1 初始化BeanFactory;2.2 获取BeanFactory。
2.1 初始化BeanFactory
refreshBeanFactory();
用来初始化BeanFactory
,它最终调用的是GenericApplicationContext.refreshBeanFactory()
方法,代码如下:
protected final void refreshBeanFactory() throws IllegalStateException {
if (!this.refreshed.compareAndSet(false, true)) {
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
this.beanFactory.setSerializationId(getId());
}
主要是通过getId()方法给BeanFactory设置serializationId的属性值,此处设置的值为:"org.springframework.context.annotation.AnnotationConfigApplicationContext@6cc7b4de"
2.2 获取BeanFactory
public final ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
}
此处返回的是DefaultListableBeanFactory
3. 对BeanFactory进行功能填充
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 增加对AspectJ的支持
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// 添加默认的系统环境Bean
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
此方法是对BeanFactory
进行一些设置。关于这一块的解说可以参考容器的功能扩展(二)功能扩展
4. postProcessBeanFactory
postProcessBeanFactory
方法是一个扩展点,在AbstractApplicationContext
中是一个空方法,它主要是让子类可以重写以实现它们自己的特殊逻辑。而AnnotationConfigApplicationContext
并没有对该类进行重写。
5.激活各种BeanFactoryPostProcessor处理器
BeanFactoryPostProcessor
和BeanPostProcessor
都是Spring提供的扩展点,可以通过它们对bean的定义修改。
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
激活BeanFactoryPostProcessor
的工作会委托给PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()
进行处理。
6. 注册各种Bean的后置处理器
Bean的后置处理器的方法也是委托给PostProcessorRegistrationDelegate
处理,具体方法为:registerBeanPostProcessors()
。这⾥只是注册,真正的调⽤是在getBean的时候
待续
网友评论