前言
一般来说,spring启动,就是构造ApplicationContext对象以及调用refresh()方法的过程
spring的启动主要做了这么几件事情:
- 构造一个
BeanFactory
对象 - 解析配置类,得到BeanDefinition,并注册到BeanFactory中
- 解析
@ComponentScan
,此时就会完成扫描 - 解析
@Import
- 解析
@Bean
- ...
- 解析
- 因为
ApplicationContext
还支持国际化,所以还需要初始化MessageSource
对象 - 因为
ApplicationContext
还支持事件机制,所以还需要初始化ApplicationEventMulticaster
对象 - 把用户定义的
ApplicationListener
对象添加到ApplicationContext
中,等Spring启动完了就要发布事件了 - 创建非懒加载的单例Bean对象,并存在BeanFactory的单例池中。
- 调用
Lifecycle Bean
的start()方法 - 发布
ContextRefreshedEvent
事件
由于Spring启动过程中要创建非懒加载的单例Bean对象,那么就需要用到BeanPostProcessor
,所 以Spring在启动过程中就需要做两件事:
- 生成默认的
BeanPostProcessor
对象,并添加到BeanFactory中AutowiredAnnotationBeanPostProcessor
:处理@Autowired、@ValueCommonAnnotationBeanPostProcessor
:处理@Resource、@PostConstruct、 @PreDestroyApplicationContextAwareProcessor
:处理ApplicationContextAware
等回调
- 找到外部用户所定义的
BeanPostProcessor
对象(类型为BeanPostProcessor
的Bean对象), 并添加到BeanFactory中
BeanFactoryPostProcessor
Bean的后置处理器,是用来对Bean进行加工的,类似的, BeanFactoryPostProcessor
理解为BeanFactory的后置处理器,用来用对BeanFactory进行加工的。
Spring支持用户定义BeanFactoryPostProcessor
的实现类Bean,来对BeanFactory进行加工,比 如:
@Component
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");
beanDefinition.setAutowireCandidate(false);
}
}
以上代码,就利用了BeanFactoryPostProcessor
来拿到BeanFactory,然后获取BeanFactory内的某 个BeanDefinition对象并进行修改,注意这一步是发生在Spring启动时,创建单例Bean之前的,所 以此时对BeanDefinition就行修改是会生效的。
注意:在ApplicationContext内部有一个核心的DefaultListableBeanFactory
,它实现了 ConfigurableListableBeanFactory
和BeanDefinitionRegistry
接口,所以ApplicationContext和 DefaultListableBeanFactory
是可以注册BeanDefinition的,但是 ConfigurableListableBeanFactory
是不能注册BeanDefinition的,只能获取BeanDefinition,然后 做修改。 所以Spring还提供了一个BeanFactoryPostProcessor
的子接口: BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor{
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
BeanDefinitionRegistryPostProcessor
继承了BeanFactoryPostProcessor
接口,并新 增了一个方法,注意方法的参数为BeanDefinitionRegistry
,所以如果我们提供一个类来实现 BeanDefinitionRegistryPostProcessor
,那么在postProcessBeanDefinitionRegistry()
方法中就可 以注册BeanDefinition了。
public static void main(String[] args) {
@Component
public class ZhouyuBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition()
.getBeanDefinition();
beanDefinition.setBeanClass(User.class);
registry.registerBeanDefinition("user", beanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");
beanDefinition.setAutowireCandidate(false);
}
}
}
如何理解refresh()?
取自源码注释翻译:
加载或刷新持久化的配置,可能是XML文件、属性文件或关系数据库中存储的。由于这是一个启动方法,如果失败,它应该销毁已经创建的单例,以避免暂用资源。换句话说,在调用该方法之后,应该实例化所有的单例, 或者根本不实例化单例 。
ApplicationContext关闭之后不代表JVM也关闭了,ApplicationContext是 属于JVM的,说白了ApplicationContext也是JVM中的一个对象。
在Spring的设计中,也提供可以刷新的ApplicationContext和不可以刷新的ApplicationContext。
// 可以刷新
AbstractRefreshableApplicationContext extends AbstractApplicationContext
// 不可以刷新
GenericApplicationContext extends AbstractApplicationContext
AnnotationConfigApplicationContext
继承的是GenericApplicationContext
,所以它是不能刷新 的。 AnnotationConfigWebApplicationContext
继承的是 AbstractRefreshableWebApplicationContext
,所以它是可以刷的。 上面说的不能刷新是指不能重复刷新,只能调用一次refresh方法,第二次时会报错。
refresh()底层原理流程
面以AnnotationConfigApplicationContext
为例子,来介绍refresh的底层原理。
- 在调用
AnnotationConfigApplicationContext
的构造方法之前,会调用父类GenericApplicationContext
的无参构造方法,会构造一个BeanFactory,为DefaultListableBeanFactory
。 - 构造
AnnotatedBeanDefinitionReader
(主要作用添加一些基础的PostProcessor,同时可以通过reader进行BeanDefinition的注册),同时对BeanFactory进行设置和添加 PostProcessor(后置处理器)- 设置dependencyComparator:AnnotationAwareOrderComparator,它是一个 Comparator,是用来进行排序的,会获取某个对象上的Order注解或者通过实现Ordered 接口所定义的值进行排序,在日常开发中可以利用这个类来进行排序。
- 设置autowireCandidateResolver:ContextAnnotationAutowireCandidateResolver, 用来解析某个Bean能不能进行自动注入,比如某个Bean的autowireCandidate属性是否等 于true
- 向BeanFactory中添加
ConfigurationClassPostProcessor
对应的BeanDefinition,它是 一个BeanDefinitionRegistryPostProcessor,并且实现了PriorityOrdered接口 i - 向BeanFactory中添加
AutowiredAnnotationBeanPostProcessor
对应的 BeanDefinition,它是一个InstantiationAwareBeanPostProcessorAdapter, MergedBeanDefinitionPostProcessor - 向BeanFactory中添加CommonAnnotationBeanPostProcessor对应的BeanDefinition, 它是一个InstantiationAwareBeanPostProcessor, InitDestroyAnnotationBeanPostProcessor
- 向BeanFactory中添加EventListenerMethodProcessor对应的BeanDefinition,它是一个 BeanFactoryPostProcessor,SmartInitializingSingleton
- 向BeanFactory中添加DefaultEventListenerFactory对应的BeanDefinition,它是一个 EventListenerFactory