思路参考:spring源码导读 SegmentFault 思否
核心上下文依赖包
1  | <dependency>  | 
Spring内容的实现依赖于底层大量的PostProcess来对Bean的实例进行一定的修饰
IOC容器
Bean的生命周期
创建–>初始化–>销毁
创建
Bean 容器找到配置文件中 Spring Bean 的定义。
Bean 容器利用 Java Reflection API 创建一个 Bean 的实例。
如果涉及到一些属性值 利用
set()方法设置一些属性值。如果 Bean 实现了
BeanNameAware接口,调用setBeanName()方法,传入 Bean 的名字。如果 Bean 实现了
BeanClassLoaderAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例。如果 Bean 实现了
BeanFactoryAware接口,调用setBeanFactory()方法,传入BeanFactory对象的实例。与上面的类似,如果实现了其他
*.Aware接口,就调用相应的方法。如果有和加载这个 Bean 的 Spring 容器相关的
BeanPostProcessor对象,执行postProcessBeforeInitialization()方法如果 Bean 实现了
InitializingBean接口,执行afterPropertiesSet()方法。如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。
如果有和加载这个 Bean 的 Spring 容器相关的
BeanPostProcessor对象,执行postProcessAfterInitialization()方法
销毁
- 当要销毁 Bean 的时候,如果 Bean 实现了 
DisposableBean接口,执行destroy()方法。 - 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。
 
获取IOC容器底层组件
比如说容器本身
实现XXXAware接口和对应方法
1  | 
  | 
XXXAware接口会由XXXAwareProcessor进行处理,这些Processor都是实现了BeanPostProcessor的后置处理器
如ApplicationContextAwareProcessor通过调用invokeAwareInterfaces方法来匹配Aware的对应类型并传入上下文
1  | private void invokeAwareInterfaces(Object bean) {  | 
IOC容器创建过程
进入refresh()方法:
1  | public void refresh() throws BeansException, IllegalStateException {  | 
prepareRefresh()
- 记录启动时间,设置容器的active和close状态。
 - initPropertySources():提供给子容器类,子容器类可覆盖该方法进行一些自定义的属性设置。
 - getEnvironment().validateRequiredProperties():检验属性的合法性
 - this.earlyApplicationEvents = new LinkedHashSet
() :保存容器中的一些早期的事件,待事件多播器创建后执行。  
obtainFreshBeanFactory()
将Bean的配置信息添加到注册中心
- refreshBeanFactory:如果当前容器已经有了BeanFactory就销毁原来的BeanFactory。然后创建一个DefaultListableBeanFactory();
- 对BeanFactory并进行配置,主要配置是否允许BeanDefinition覆盖,是否允许Bean间的循环引用。
 - 加载BeanDefinition,解析XML文件和配置文件,将其转换为BeanDefinition,然后保存到DefaultListableBeanFactory的beanDefinitionMap字段中。
 
 - getBeanFactory() 简单的返回beanFactory,即DefaultListableBeanFactory。
 
- refreshBeanFactory:如果当前容器已经有了BeanFactory就销毁原来的BeanFactory。然后创建一个DefaultListableBeanFactory();
 prepareBeanFactory()
- 设置BeanFactory的类加载器、设置支持SPEL表达式的解析器。
 - 添加ApplicationContextAwareProcessor用于处理XXXAware接口的回调。
 - 设置忽略一些接口。并注册一些类,这些类可以在bean里直接进行自动装配。
 - 添加ApplicationListenerDetector用于识别并保存ApplicationListener的子类。
 
postProcessBeanFactory()
提供给子容器类,子容器类可以覆盖该方法在BeanFactory准备工作完成后处理一些工作。
invokeBeanFactoryPostProcessors()
执行BeanFactoryPostProcessors类型的后置处理器的监听方法
- BeanFactoryPostProcessor是beanFactory后置处理器,在整个BeanFactory标准初始化完成后进行拦截调用,
 - BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor,在beanFactory解析完所有的BeanDefinition后拦截调用。
 - BeanFactoryPostProcessor来源
- 通过ApplicationContent的addBeanFactoryPostProcessor()方法手动添加自己的拦截器
 - 系统默认了一些BeanFactoryPostProcessor。例如:ConfigurationClassPostProcessor用来处理@Configuration标注的Spring配置类。
 
 - 调用顺序 
- 先调用BeanDefinitionRegistryPostProcessor类型的拦截器,
 - 然后再依次调用实现了PriorityOrdered,Ordered接口的BeanFactoryPostProcessor
 - 最后调用普通的BeanFactoryPostProcessor
 
 
registerBeanPostProcessors()
注册Bean的后置处理器
- 从beanFactory里获取所有BeanPostProcessor类型的Bean的名称。
 - 调用beanFactory的getBean方法并传入每一个BeanPostProcesso类型的Bean名称,从容器中获取该Bean的实例。
 - 第一步向beanFactory注册实现了PriorityOrdered的BeanPostProcessor类型的Bean实例。
 - 第二步向beanFactory注册实现了Ordered的BeanPostProcessor类型的Bean实例。
 - 第三步向beanFactory注册普通的BeanPostProcessor类型的Bean实例。
 - 最后一步向beanFactory重新注册实现了MergedBeanDefinitionPostProcessor的BeanPostProcessor类型的Bean实例
 
- 向beanFactory注册BeanPostProcessor的过程就是简单的将实例保存到beanFactory的beanPostProcessors属性中。
 
initMessageSource()
初始化国际化相关功能
- 看容器中是否有id为messageSource的,类型是MessageSource的Bean实例。如果有赋值给messageSource,如果没有自己创建一个DelegatingMessageSource。
 - 把创建好的MessageSource注册在容器中,以后获取国际化配置文件的值的时候,可以自动注入MessageSource。
 
initApplicationEventMulticaster()
初始化事件派发器,用于给监听器传递消息
- 看容中是否有名称为applicationEventMulticaster的,类型是ApplicationEventMulticaster的Bean实例。如果没有就创建一个SimpleApplicationEventMulticaster。
 - 把创建好的ApplicationEventMulticaster添加到BeanFactory中。
 
onRefresh()
提供给子容器类,供子容器去实例化其他的特殊的Bean
registerListeners()
处理容器中已有的ApplicationListener
- 从容器中获得所有的ApplicationListener
 - 将每个监听器添加到事件派发器(ApplicationEventMulticaster)中;
 - 处理之前步骤产生的事件;
 
finishBeanFactoryInitialization()
初始化容器中剩余的单实例bean:拿到剩余的所有的BeanDefinition,依次调用getBean方法
finishRefresh()
- 初始化和生命周期有关的后置处理器;LifecycleProcessor,如果容器中没有指定处理就创建一个DefaultLifecycleProcessor加入到容器。
 - 获取容器中所有的LifecycleProcessor回调onRefresh()方法。
 - 发布容器刷新完成事件ContextRefreshedEvent。
 
AOP
1  | <dependency>  | 
在程序运行期间,动态的将某段代码切入到指定位置的编程方式
底层:动态代理
@EnableAspectJAutoProxy的作用
@EnableAspectJAutoProxy
- @EnableAspectJAutoProxy 通过@Import(AspectJAutoProxyRegistrar.class)给spring容器中导入了一个AnnotationAwareAspectJAutoProxyCreator。
 - AnnotationAwareAspectJAutoProxyCreator实现了InstantiationAwareBeanPostProcessor,InstantiationAwareBeanPostProcessor是一个BeanPostProcessor。它可以拦截spring的Bean初始化(Initialization)前后和实例化(Initialization)前后。
 
总结
@EnableAspectJAutoProxy
向容器中注册组件AnnotationAwareAspectJAutoProxyCreator后置处理器
容器创建流程:
registerBeanPostProcessors()注册后置处理器,创建AnnotationAwareAspectJAutoProxyCreator对象
finishBeanFactoryInitialization()初始化剩下的单实例Bean
创建业务逻辑组件和切面组件
AnnotationAwareAspectJAutoProxyCreator会拦截组建的创建过程
组件创建完后,判断组件是否需要增强
如果是,将切面的通知方法包装秤增强器,给业务逻辑组件创建一个代理对象
执行目标方法:
代理对象执行目标方法
CglibAopProxy.intercept()
得到目标方法的拦截器链(将增强器包装成MethodInterceptor)
利用拦截器的链式机制,依次进入每个拦截器进行执行
由于每个拦截器会先放行执行它的下一个拦截器,因此排在最后的前置通知拦截器会最先执行
执行顺序:
- 正常执行:前置通知-目标方法->后置通知->返回通知
 - 出现异常:前置通知-目标方法->后置通知->异常通知
 
声明式事务原理
注解使用方式
配置数据源DataSource
主类上添加
@EnableTransactionManagement需要转为事务操作的方法上添加
@Transactional配置事务管理器来管理事务
1
2
3
4
5
public PlatformTransactionManager transactionManager(){
//这里传入配置好的数据源
return new DataSourceTransactionManager(datasource());
}
运行过程:
- @EnableTransactionManagement利用TransactionManagementConfigurationSelector给spring容器中导入两个组件:AutoProxyRegistrar和ProxyTransactionManagementConfiguration
 - AutoProxyRegistrar给spring容器中注册一个InfrastructureAdvisorAutoProxyCreator,InfrastructureAdvisorAutoProxyCreator实现了InstantiationAwareBeanPostProcessor,InstantiationAwareBeanPostProcessor是一个BeanPostProcessor。它可以拦截spring的Bean初始化(Initialization)前后和实例化(Initialization)前后。利用后置处理器机制在被拦截的bean创建以后包装该bean并返回一个代理对象代理对象执行方法利用拦截器链进行调用(同springAop的原理)
 - ProxyTransactionManagementConfiguration:是一个spring的配置类,它为spring容器注册了一个BeanFactoryTransactionAttributeSourceAdvisor,是一个事务事务增强器。它有两个重要的字段:AnnotationTransactionAttributeSource和TransactionInterceptor。
- AnnotationTransactionAttributeSource:用于解析事务注解的相关信息
 - TransactionInterceptor:事务拦截器,在事务方法执行时,都会调用TransactionInterceptor的invoke->invokeWithinTransaction方法,这里面通过配置的PlatformTransactionManager控制着事务的提交和回滚。
 
 
扩展原理
- BeanFactoryPostProcessor:beanFactory后置处理器,的拦截时机:所有Bean的定义信息已经加载到容器,但还没有被实例化。可以对beanFactory进行一些操作。
 - BeanPostProcessor:bean后置处理器,拦截时机:bean创建对象初始化前后进行拦截工作。可以对每一个Bean进行一些操作。
 - BeanDefinitionRegistryPostProcessor:是BeanFactoryPostProcessor的子接口,拦截时机:所有Bean的定义信息已经加载到容器,但还没有被实例化,可以对每一个Bean的BeanDefinition进行一些操作。
 - 监听器原理:EventListenerMethodProcessor是一个SmartInitializingSingleton,当所有的单例bean都初始化完以后, 容器会回调该接口的方法afterSingletonsInstantiated(),该方法里会遍历容器中所有的bean,并判断每一个bean里是否带有@EventListener注解的Method,然后创建ApplicationListenerMethodAdapter存储并包装该Method,最后将ApplicationListenerMethodAdapter添加到spring容器中。
 - 事件派发器ApplicationEventMulticaster给EventListener传递消息
 
使用监听器
监听对象
实现并注册ApplicationListener接口
1
2
3
4
5
6
public class MyListener implements ApplicationListener<ApplicationEvent> {
public void onApplicationEvent(ApplicationEvent applicationEvent) {
System.out.println("监听到了事件:" + applicationEvent);
}
}或者直接使用
@EventListener()接口来为普通的方法指定监听对象
可以自己发布事件
1
applicationContext.publishEvent(new ApplicationEvent(new String("我发布的事件")){});
bean的循环依赖问题
A 依赖 B B 依赖 A 产生闭环,称为循环依赖
·Spring 默认允许单例对象的属性注入 所产生的循环依赖
单例对象的循环依赖 Spring通过3级缓存来解决
比如一个类A中有一个属性是B类,B类中有一个属性是A类,这时看Spring是怎么解决他们的相互依赖的。Spring注入一个类的大体步骤分为两部分,一是先完成对类的构造工作,二是会对类的属性进行设置和填充。首先Spring构造A类,通过AbstractAutowireCapableBeanFactory的doCreateBean方法中调用addSingletonFactory方法将A类曝光到singletonFactories中。这时完成A的构造后,需要填充B属性,继续第二步,发现B还没有构造,于是开始B流程的构造过程,构造的时候发现需要填充A,从第三层缓存singletonFactories中找到A(此时的A还没有完全构造完成,但是可以拿到A的一个引用),B拿到A的引用后,完成B自己的填充属性工作,完成初始化工作,把自己放到第一层缓存singletonObjects中。这时回到A的这边,在拿到B对象后,完成自己的填充属性工作。
| 源码 | 级别 | 描述 | 
|---|---|---|
| singletonObjects | 一级缓存 | 用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用 | 
| earlySingletonObjects | 二级缓存 | 存放原始的 bean 对象(尚未填充属性),用于解决循环依赖 | 
| singletonFactories | 三级缓存 | 存放 bean 工厂对象,用于解决循环依赖 | 
二级缓存就能解决缓存依赖,三级缓存解决的是AOP代理问题