Spring启动流程
启动容器的第一步 执行构造方法GenericApplicationContext
会初始化一个 beanFactory 是 DefaultListableBeanFactory
在DefaultListableBeanFactory的构造方法中
会往 ignoredDependencyInterfaces 中 加入回调类 BeanNameAware BeanFactoryAware BeanClassLoaderAware
第二部 会往application中加入两个东西
AnnotatedBeanDefinitionReader
在这个类的构造方法中会有一些,非常重要的东西
这些都是 设置到 了 beanFactory
直接new出来 并设置到属性中
AnnotationAwareOrderComparator(比较器)
ContextAnnotationAutowireCandidateResolver(依赖注入的 条件类 )–责任链
向BDMap中添加一些东西
ConfigurationClassPostProcessor(配置类的) – internalConfigurationAnnotationProcessor
AutowiredAnnotationBeanPostProcessor(@Autowired)-- internalAutowiredAnnotationProcessor
CommonAnnotationBeanPostProcessor(@Resource) – internalCommonAnnotationProcessor
EventListenerMethodProcessor(事件监听)-- internalEventListenerProcessor
功能 解析 EventListener 注解的
(这是一个BeanFactoryProcess 和 *SmartInitializingSingleton*)
SmartInitializingSingleton提供的一个方法 afterSingletonsInstantiated(所有单例bean都创建后才会执行 的一个方法 , 这里大概就会 所有单例bean都创建后,会遍历 , 看看哪些bean实现 SmartInitializingSingleton,就会调用afterSingletonsInstantiated)
EventListenerMethodProcessor的 afterSingletonsInstantiated方法中 会获得所有BD定义的对象
然后会遍历这些 对象 中的方法 看看有没有哪个方法上面加了 @EventListener 然后将这些方法放到一个
annotatedMethods中
然后对这个 集合 中的每一个方法 都会 封装成一个监听器 然后放到事件发布器中
DefaultEventListenerFactory(事件监听) – internalEventListenerFactory
ClassPathBeanDefinitionScanner
这个类的构造方法
主要就是向 includeFilters 中 添加一个 Component注解
执行register方法
会将我们传的类 KangConfiger的类 进行注册
用这个AnnotatedBeanDefinitionReader 将这个类 转为 BD
生成默认的beanName
并 解析 @Scope @Lazy @Primary @DependsOn @Role @Description
将这个 类 放到 BDMap中
refresh(最复杂的方法)
这个方法 用到了 模板的设计模式
这个方法是 AbstractApplicationContext 中定义了一个模板
这个模板
prepareRefresh(); 为刷新做准备
initPropertySources();
这个方法 AbstractApplicationContext 没有没有实现 ,
但 如果子类 调用了 refresh方法,如果实现了这个方法就会去调用这个方法
这就是模板设计的精髓
举一个 实际的例子
AnnotationConfigWebApplicationContext的父类
AbstractRefreshableWebApplicationContext的这个initPropertySources方法会将web.xml的文档转换为key-value的格式,并设置到环境变量中
getEnvironment().validateRequiredProperties();
进行环境变量的校验
我们可以再 刷新前 指定一个环境变量的key的
annotationConfigApplicationContext.getEnvironment().setRequiredProperties(“132”);
会将这个 “123” 转换为一个 requiredProperties 的集合
如果再这一步,去遍历requiredProperties 集合,然后去环境变量里找,如果有一个没有找到,就会抛异常
一个小机制
obtainFreshBeanFactory 也是一个模板方法
这个重复刷新有关系
还有一个就是 获得beanFactory
如果不是web容器 AnnotationConfigApplicationContext 就会 禁止重复刷新,如果重复就会报错
是web容器 , 就允许重复刷新
重复刷新 : 会销毁所有的bean ,在这之前会执行bean的销毁方法(有就执行),然会清空beanFactory
相当于重启了
prepareBeanFactory(beanFactory)
对beanFactory 再次进行加工
给 beanFactory 添加一个 类加载器
开启beanFactorySpel**功能
添加一些 类型 转化器(String 转化 为 spring默认支持的类型)
向beanFactory中的beanPostProcessList中添加一个 ApplicationContextAwareProcessor 对象
处理一些 aware的回调
注册一些接口
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.ignoreDependencyInterface(ApplicationStartupAware.class);
ignoreDependencyInterface这个集合到底有什么用(不是很重要)
和依赖注入有关系
当我们通过xml注入bean的时候,如果设置是根据类型/名字注入,就会遍历所有set方法,但是真正被作为pvs的前提是,就是这个bean实现的接口不在这个ignoreDependencyInterface集合中,因为这个集合中放的都是一些回调函数,会在初始化前调用这个方法,就是解决了,回调函数和依赖注入(不要重复调用这个set方法)
但是@Autowired并没有这个前提判断,如果将@Autowired加到回调方法上,就会调用两次这个方法
// 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);
这段代码 会往 resolvableDependencies 这个map《class,object》中添加
resolvableDependencies 这个是在 依赖注入 的findAutowireCandidates中
会根据类型 找到这个集合中的对象 并根据一些spring特殊规则(不是正常规则)生成一个beanname
然后放到 result 中
这也是为啥 我们可以通过这种方式 获得 applicationContext
@Autowired
ApplicationContext applicationContext;
// Register early post-processor for detecting inner beans as ApplicationListeners.
// ApplicationListenerDetector负责把ApplicantsListener类型的Bean注册到ApplicationContext中
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
向beanPostProcessList中添加一个ApplicationListenerDetector对象(事件监听)
// Register default environment beans.
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());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
向单例池里面添加一些 有关 environment 的单例bean
postProcessBeanFactory(和web有关)
invokeBeanFactoryPostProcessors(很重要)
功能如其名 执行 beanFactoryPostProcess (操作BD 但是不能增加BD)和 它的子类 BeanDefinitionRegistryPostProcessor 可以增加BD
registerBeanPostProcessors(很重要)
initMessageSource(和国际化有关)
initApplicationEventMulticaster(和事件广播器有关)
会判断BD内有没有applicationEventMulticaster这个bean
如果有就拿到这个bean 赋值给 applicationEventMulticaster这个属性
如果没有 就会默认 给一个SimpleApplicationEventMulticaster,并将这个对象赋给applicationEventMulticaster属性,并将这个bean放到单例池里面
registerListeners();和事件监听器有关
需要程序员自己去 写事件监听器
这个算是 娄底的 如果一个类上面标了 @Lazy 注解 是不会通过 后置处理器的,但是这个类的信息会放到BD里
这个方法会获得 所有的事件监听器(根据类型ApplicationListener,在BD里面获取),然后会将这写事件监听器的beanname放到 SimpleApplicationEventMulticaster这个事件广播器一个属性中(applicationListenerBeans),在事件发布时,就会去getBean方法
问题来了
怎么判断一个bean是不是 事件监听器
通过BeanPostProcess来完成 之前我们也刚好 放了一个ApplicationListenerDetector这个对象 在prepareBeanFactory这个方法里放的
ApplicationListenerDetector就会在 初始化后 判断一个bean是不是一个监听器,然后放到事件广播器的一个属性中
我们事件发布都是通过 事件广播器完成的、
事件发布 默认是 广播的
所有的listen都会执行(串行的)
finishBeanFactoryInitialization(beanFactory);
执行到这里,已经完成了bean的扫描,会对我们设置的一些bean,和一些规则,提前搞定,为了实例化单例bena做准备
设置一些类型转换器conversionService
设置 设置默认的占位符解析器 ${xxx} —key
这里设置的就是Lambda表达式 是根据environment来解决的 xxx本来就是 环境变量 的key
最后 创建非懒加载的单例bean
finishRefresh();不太重要
和Spring生命周期有关
会发布一个事件
解析配置类
ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry 方法
获得所有的BD 遍历
得到这些BD中的配置类
配置类的判断
先分析获得这个类 标注的所有注解(注解读取器)
AnnotationMetadata metadata
下来获得 Configuration注解的 key和value
Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName())
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
// 存在@Configuration,并且proxyBeanMethods为false时,是lite配置类
// 或者不存在@Configuration,但是只要存在@Component、@ComponentScan、@Import、@ImportResource四个中的一个,就是lite配置类
// 或者不存在@Configuration,只要存在@Bean注解了的方法,就是lite配置类
else if (config != null || isConfigurationCandidate(metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
}
// It's a full or lite configuration candidate... Let's determine the order value, if any.
Integer order = getOrder(metadata);
if (order != null) {
beanDef.setAttribute(ORDER_ATTRIBUTE, order);
}
return true;