IOC
Application的继承关系
-
ApplicationContext的实现类
图片来源于https://www.javadoop.com/post/spring-ioc -
ApplicationContext的父接口
图片来源于https://www.javadoop.com/post/spring-ioc
容器的启动过程
从AbstractApplicationContext抽象类的refresh方法开始。
- 准备工作
记录下容器的启动时间,标记容器开启和关闭状态位,校验配置文件 - 解析配置文件,创建BeanDefinition实例,注册进BeanFactory中
(1)将配置文件转换成一颗DOM树,从根节点开始解析文件。
(2)解析default namespace涉及到的四个标签 < import/> < alias/> < bean/>和< beans/> ;
解析其他属于custom下的标签
(3)以< bean/>标签为例,根据标签下的内容形成一个个的BeanDefiniton,然后放入注册中心中,说到底核心是一个beanName->BeanDefinition的map - 设置BeanFactory的类加载器,添加BeanPostProcessor,手动注册几个bean
- 具体的子类添加一个特殊的BeanFactoryPostProcessor 的实现类或做点什么事
- 调用上一步实现类的PostProcessorBeanFactory(factory)回调方法
- 注册BeanPostProcessor实现类,其中的两个方法会在Bean初始化之前和初始化之后得到执行
- 初始化当前ApplicationContext的MessageSource
- 初始化当前ApplicationContext的事件广播器
- 注册事件监听器
- 初始化所有的非懒加载 singleton beans
(1)预初始化:如果有Bean继承关系,合并父Bean的配置;如果bean实现了SmartInitializingSingleton 接口,进行相应的函数回调等等。
(2)正式初始化:判断bean是否已被初始化,若被初始化则直接返回,否则就进行初始化。分为三步:
第一步–创建Bean实例
如果不存在方法覆写,就利用java反射实例化,否则使用CGLB
第二步–Bean属性注入
通过名字装配、通过类型装配等
第三步–方法回调
- 如果bean实现了BeanNameAware、BeanClassLoaderAware或者BeanFactoryAware接口,调用回调方法
- 如果bean注册了BeanPostProcessor实现类,则调用postProcessBeforeInitialization 方法
- 如果bean实现了initializingBean接口,调用afterProperties()方法
调用init-method配置的方法- 如果bean注册了BeanPostProcessor实现类,则调用postProcessAfterInitialization 方法
- 广播事件
AOP
Spring对AOP的支持
Spring提供了四种类型的AOP支持,分别为:
- 基于代理的经典SpringAOP
- 纯POJO切面
- @AspectJ注解驱动的切面
- 注入式AspectJ切面(适用于Spring的各个版本)
前三种都是SpringAOP实现的变体,SpringAOP构建在动态代理基础上,因此Spring对AOP的支持局限于方法拦截。
基于xml配置的AOP模式
以DefaultAdvisorAutoProxyCreator 为例来进行追踪,可以发现它是BeanPostProcessor接口的子类。IOC容器在初始化Bean的最后一步中会调用回调方法postProcessAfterInitialization ,该方法是BeanPostProcessor的接口方法。
对于BeanPostProcessor的实现类AbstractAutoProxyCreator,它是这样实现postProcessAfterInitialization 方法的:
- 通过createProxy方法区创建ProxyFactory实例,ProxyFactory中包含了Advisor、targetSource等信息。其中的Advisor就是利用Pointcut正则表达式指定的范围匹配得来的。
- 使用createAopProxy方法返回AOPProxy实例。如果被代理的目标类实现了接口,就使用jdk动态代理;没有实现任何接口,会使用CGLIB实现代理;如果设置了proxy-target-class=“true”,那都会使用CGLIB。
当类的方法被private或者final修饰的时候,也不能够使用jdk动态代理。 - 返回AopProxy实例后继续调用getProxy(classLoder)方法,因为AopProxy实例有jdk动态代理和CGLIB两种代理方法,所以会用两种不同的方式获得代理对象。
基于注解驱动的AOP模式
Spring Aop中@Aspect的实现原理:
开启@Aspect有两种方式,一个是<aop:aspectj-autoproxy/>
,一个是@EnableAspectJAutoProxy
,它们的原理都是一样的,通过注册一个bean来实现。那这是一个怎样的Bean?
以<aop:aspectj-autoproxy/>
为例,解析这个标签会用到AopNamespaceHandler->AspectJAutoProxyBeanDefinitionParser-> …-> 注册了一个类名为AnnotationAwareAspectJAutoProxyCreator的Bean,查看继承关系,发现它也是BeanPostProcessor接口的一个实现类,所以后面同样会在IOC容器初始化Bean实例的最后调用回调方法创建Bean的代理对象。