Spring的IOC底层原理
基于注解的IOC容器流程
Spring基于注解的开发方式,获取IOC容器。
AnnotationConfigApplicationContext是一个用来管理注解bean的容器,继承GenericApplicationContext这个通用应用上下文。
接下来我们就看看 AnnotationConfigApplicationContext 是怎么实现Bean的创建-初始化等一系列工作。
我们进入 AnnotationConfigApplicationContext 的源码:
Spring 容器中的refresh()方法,主要通过这个方法对IOC容器进行创建和刷新。
1. refresh中的 prepareRefresh() 方法进行刷新前的预处理工作。
1)initPropertySources() 初始化一些属性设置,子类实现这个方法自定义个性化的属性设置。
2)getEnvironment().validateRequiredProperties() 检验属性的合法
3)earlyApplicationEvents= new LinkedHashSet<ApplicationEvent>() 保存容器中的一些早期的事件
2. refresh中的 obtainFreshBeanFactory(),此方法获取BeanFactory对象
1)refreshBeanFactory() 创建 BeanFactory
在 GenericApplicationContext 类中通过构造方法创建BeanFactory对象。
2)getBeanFactory() 返回刚才GenericApplicationContext创建的BeanFactory对象;
3)最终将创建的 BeanFactory 对象返回
3. prepareBeanFactory(beanFactory) 对BeanFactory进行一些设置
1)设置BeanFactory 的类加载器
2)添加部分BeanPostProcessor【ApplicationContextAwareProcessor】 判断是否实现了ApplicationContext接口
3)设置忽略的自动装配的接口 EnvironmentAware、EmbeddedValueResolverAware
4)注册可以解析的自动装配,我们能直接在任何组件中自动注入:
BeanFactory、ResourceLoader、ApplicationEventPublisher(事件派发器)、ApplicationContext
5)添加BeanPostProcessor【ApplicationListenerDetector】监听器
6)添加编译时的AspectJ支持
7)给BeanFactory中注册一些能用的组件
4. postProcessBeanFactory(beanFactory) 对BeanFactory进行后置处理工作
子类通过重写这个方法来在 BeanFactory创建 并预准备完成以后做进一步的设置。
5. invokeBeanFactoryPostProcessors(beanFactory) 执行BeanFactoryPostProcessor的方法。
BeanFactoryPostProcessor:BeanFactory的后置处理器。在BeanFactory标准初始化之后执行。
1)执行BeanFactoryPostProcessor
先执行BeanDefinitionRegistryPostProcessor
获取所有的BeanDefinitionRegistryPostProcessor,按照优先级顺序,先执行实现了PriorityOrdered优先级接口的,再执行实现了Ordered顺序接口的,最后执行没有实现任何优先级或者是顺序接口的BeanDefinitionRegistryPostProcessors。
再执行BeanFactoryPostProcessor
同样按照BeanDefinitionRegistryPostProcessor流程进行执行。
6. registerBeanPostProcessors(beanFactory) 注册BeanPostProcessor(Bean的后置处理器)【拦截bean的创建过程】
不同接口类型的BeanPostProcessor,在Bean创建前后的执行时机不一样。
BeanPostProcessor、
DestructionAwareBeanPostProcessor、
InstantiationAwareBeanPostProcessor、
SmartInstantiationAwareBeanPostProcessor、
MergedBeanDefinitionPostProcessor
1)获取所有的 BeanPostProcessor 后置处理器默认都可以通过PriorityOrdered、Ordered接口来执行优先级
2)先注册PriorityOrdered优先级接口的BeanPostProcessor。
把每一个BeanPostProcessor;添加到BeanFactory中
beanFactory.addBeanPostProcessor(postProcessor);
3)再注册Ordered接口的
4)最后注册没有实现任何优先级接口的
5)最终注册MergedBeanDefinitionPostProcessor;
6)注册一个ApplicationListenerDetector;来在Bean创建完成后检查是否是ApplicationListener,如果是
调用 applicationContext.addApplicationListener((ApplicationListener<?>) bean) 注册进监听器列表。
7. initMessageSource() 初始化MessageSource组件(做国际化功能;消息绑定,消息解析)。
1)获取BeanFactory
2)看容器中是否有id为messageSource的,类型是MessageSource的组件,如果有赋值给messageSource,如果没有自己创建一个DelegatingMessageSource。
MessageSource:取出国际化配置文件中的某个key的值;能按照区域信息获取。
3)把创建好的MessageSource注册在容器中,以后获取国际化配置文件的值的时候,可以自动注入MessageSource。
8. initApplicationEventMulticaster() 初始化事件派发器
1)获取BeanFactory
2)从BeanFactory中获取applicationEventMulticaster的ApplicationEventMulticaster
3)如果上一步没有配置;创建一个SimpleApplicationEventMulticaster
4)将创建的ApplicationEventMulticaster添加到BeanFactory中,以后其他组件直接自动注入
9. onRefresh() 留给子容器(子类)
子类重写这个方法,在容器刷新的时候可以自定义逻辑。
10. registerListeners() 将所有ApplicationListener注册进容器
1)从容器中拿到所有的 ApplicationListener
2)将每个监听器添加到事件派发器中
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
3)派发之前产生的事件。
11. finishBeanFactoryInitialization(beanFactory) 初始化所有剩下的单实例bean
11.1)beanFactory.preInstantiateSingletons() 初始化后剩下的单实例bean
1)获取容器中的所有bean,依次进行初始化和创建对象
2)获取bean的定义信息,RootBeanDefinition
3)判断 bean是否满足:不是抽象的,是单实例的,不是懒加载的
3.1)判断是否是FactoryBean(实现了FactoryBean的bean),工厂bean调用工厂bean的逻辑创建对象
3.2)不是工厂bean,利用getBean(beanName) 创建对象
1. ioc.getBean(beanName),ioc为创建的容器。
2. getBean中调用doGetBean() 方法
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
//1. 获取容器中的所有bean,依次进行初始化和创建对象
for (String beanName : beanNames) {
//2. 拿到bean的定义信息
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//3. 判断bean 不是抽象的,是单实例的,不是懒加载(用到的时候才创建对象)
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//3.1 判断是否FactoryBean,是否是实现FactoryBean接口的,如果是工厂bean按照工厂方法创建对象
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) () ->
((SmartFactoryBean<?>) factory).isEagerInit(),
getAccessControlContext());
} else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
} else {
//3.2 不是工厂bean,调用getBean
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
} else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
3. 先获取缓存中保存的单实例bean,如果能获取到说明创建过(创建过的单实例bean都会被缓存起来)
缓存在 singletonObjects 中
4. 缓存中拿不到,开始Bean的创建对象流程:
5. markBeanAsCreated(beanName),标记当前bean已经创建了,防止多线程重复创建
获取bean的定义信息
6. 获取当前bean的其他bean依赖,如果有通过getBean()把依赖的bean先创建出来。
7. 启动单实例bean的创建流程:
7.1)调用 createBean()创建bean
7.2)让BeanPostProcessor 先拦截返回代理对象
【InstantiationAwareBeanPostProcessor】:进行拦截
先触发:postProcessBeforeInstantiation();
如果有返回值:触发postProcessAfterInitialization();
7.3)前面的InstantiationAwareBeanPostProcessor没有返回代理对象
7.4)调用 doCreateBean(beanName, mbdToUse, args) 创建Bean
7.4.1)【创建Bean实例】;createBeanInstance(beanName, mbd, args)
利用工厂方法或者对象的构造器创建出Bean实例。
7.4.2)【Bean属性赋值】populateBean(beanName, mbd, instanceWrapper)
7.4.3)【进行Bean属性赋值】为属性利用setter方法等进行赋值
applyPropertyValues(beanName, mbd, bw, pvs);
7.4.4)【Bean初始化】initializeBean(beanName, exposedObject, mbd)
1)【 执行Aware接口方法】invokeAwareMethods(beanName, bean)
2)【执行后置处理器初始化之前的方法】
BeanPostProcessor.postProcessBeforeInitialization();
3)【执行初始化方法】invokeInitMethods(beanName, wrappedBean, mbd)
4)【执行后置处理器初始化之后】BeanPostProcessor.postProcessAfterInitialization()
7.4.5) 注册bean的销毁方法
7.5)将创建的Bean添加到缓存中singletonObjects中
ioc容器就是singletonObjects 这些map,保存了很多的单实例bean,环境信息。
12. finishRefresh() 完成BeanFactory的初始化创建工作,IOC容器就创建完成。
initLifecycleProcessor() 初始化和生命周期有关的后置处理器
publishEvent(new ContextRefreshedEvent(this)) 发布容器刷新完成事件
至此IOC容器创建完成。
总结:
1. Spring 容器在启动时,首先会保存所有注册进来的Bean的定义信息,
1)基于xml的方式:<bean>
2)基于注解的方式:@Service、@Component、@Bean、@Controller等
2. Spring 容器会在合适的时机创建这些bean
1)用到某个bean的时候,利用getBean创建bean,创建好保存在容器中。
2)统一创建剩下所有的bean的时候 调用:finishBeanFactoryInitialization() 上面的第11点。
3. 后置处理器:BeanPostProcessor
每一个bean创建、初始化前后都会使用各种后置处理器进行处理,来增强bean的功能。
4. 事件驱动模型:
ApplicationListener;事件监听;
ApplicationEventMulticaster;事件派发:
ApplicationContext中Bean的生命周期
首先:InstantiationAwareBeanPostProcessor 是 BeanPostProcessor的子接口,主要作用是目标对象的实例化过程中需要处理的事情,包括实例化对象的前后过程以及实例的属性设置。
1. 启动容器,调用BeanFactoryPostProcessor的postProcessBeanFactory()对工厂定义信息进行后处理。
2.通过getBean()调用某一个bean。
3. 调用 InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation(),该方法在bean实例化之前进行后置处理工作。如果返回为null,调用doCreateBean(),创建bean。返回不为null,表示生成了代理对象,则执行初始化之后的postProcessAfterInitialization,跳过实例化之后的postProcessAfterInstantiation()和初始化之前的postProcessBeforeInitialization。
4. bean进行实例化
5. 调用 InstantiationAwareBeanPostProcessor 的 postProcessAfterInstantiation(),在实例化之后进行后置工作。
6. 调用 InstantiationAwareBeanPostProcessor 的 postProcessPropertyValues() 方法进行属性值的修改。
7. 调用 BeanNameAware 接口的 setBeanName()方法,将名称设置到bean中。
8. 调用 BeanFactoryAware 接口的 setBeanFactory() 方法,将BeanFactory容器的实例设置到bean中。
9. 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法,进行初始化前的后置处理工作。
10. 调用 InInitializingBean 接口 afterPropertiesSet()方法。
11. 通过 init-method 属性配置的初始化方法,执行初始化逻辑。
12. 调用 BeanPostProcessor 的 postProcessAfterInitialization()方法,进行初始化后的后置处理工作。
13. 如果是单实例bean,则将bean放进IOC容器缓存池,将bean的引用返回,如果是多实例bean,将该bean返回给调用者。
14. 如果是单实例bean,实现了 DisposableBean 接口,当容器关闭的时候调用 destory 方法,然后调用 destory-method 属性指定的销毁方法。
上一篇: Spring5.X 事务相关类介绍
下一篇: 天气+记事+闹钟——android程序
推荐阅读
-
spring5 源码深度解析----- 被面试官给虐懵了,竟然是因为我不懂@Configuration配置类及@Bean的原理
-
struts2、hibernate、spring的工作原理[简明易懂]
-
Spring源码剖析2:Spring IOC容器的加载过程
-
利用递归,反射,注解等,手写Spring Ioc和Di 底层(分分钟喷倒面试官)了解一下
-
Python字典的核心底层原理讲解
-
02Spring基于xml的IOC配置--实例化Bean的三种方式
-
Spring事务的开启原理详解
-
从原理层面掌握@SessionAttribute的使用【一起学Spring MVC】
-
Spring的IOC注解开发入门1
-
原理解密 → Spring AOP 实现动态数据源(读写分离),底层原理是什么