本章节采用的是全注解开发模式
一.AOP的概述
> AOP是Aspect Oriented Programming(面向切面编程),以解耦合的方式对service层的业务方法的功能增强
> AOP本身是一种思想,但是Spring框架实现了这种思想
> AOP的执行原理:利用动态代理创建代理对象,并将通知方法织入到切入点当中
二.AOP定义阶段的源码分析
(1)全注解状态下配置打开AOP的自动代理功能,会涉及到一个注解@EnableAspectJAutoProxy注解,功能是开启AOP的自动代理
@EnableAspectJAutoProxy //开始aop自动代理
@Configuration
public class AOPOpenConfig {
}
(2)@EnableAspectJAutoProxy的源代码
> 使用@Import注解导入了一个叫做AspectJAutoProxyRegistry类
> 观察继承树体系发现其本身是一个BeanDefinitionRegistryPostProcessors增强器
@Import(AspectJAutoProxyRegistrar.class) // 导入类
public @interface EnableAspectJAutoProxy {
(3)debug AspectJAutoProxyRegistry
> 该类调用时机是在invokeBeanDefinitionRegistryPostProcessors(),调用bean实例定义信息处理器进行后置处理(容器刷新十二大步的invokeBeanFactoryPostProcessor())
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
> 执行postProcessBeanDefinitionRegistry()方法进行后置增强
postProcessor.postProcessBeanDefinitionRegistry(registry);
> 内部调用了processConfigBeanDefinition()方法来处理配置bean实例的定义信息
processConfigBeanDefinitions(registry); // 处理配置bean实例的定义信息
> this.reader.loadBeanDefinition() 【reader是配置类定义信息的读取器,加载bean实例信息】
this.reader.loadBeanDefinitions(configClasses);
> 调用 AspectJAutoProxyRegistry 注册AopConfig类的定义信息
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
> 总结:AspectJAutoProxyRegistry是负责注册AnnotationAwareAspectJAutoProxyCreator
(4)AnnotationAwareAspectJAutoProxyCreator
> 观察继承树结构可以得知:该类是一个BeanPostProcessor(bean实例的后置处理器)
> 对该类的实例方法进行debug调试,观察其执行时机
> 第一次执行的方法是initBeanFactory()方法
[ 1 ] initBeanFactory()
> 执行时机:registerBeanPostProcessor():容器刷新十二大步的注册bean实例后置处理器
> 作用:传入beanFactory实例工厂,并设置一些关于AOP操作的属性
> 设置的属性:reflectiveAspectJAdvisiorFactory:准备创建增强器的工厂
aspectJAdvisiorsBuilder:准备建造者
if (this.aspectJAdvisorFactory == null) {
this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
// 准备一个ReflectiveAspectJAdvisorFactory作为切面增强器工厂
}
this.aspectJAdvisorsBuilder =
new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory); //准备建造者
[ 2 ] isInfrastructureClass()
> 执行时机:在注册后置处理器,完成beanFactory初始化完毕的时候会调用该方法
> 作用:判断当前类是否为切面类,获取当前类上是否有配置切面注解的类
> 原因:AnnotationAwareAspectJAutoProxyCreator 实现的接口有InstantiationAwareBeanPostProcessor
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
Object result = bp.postProcessBeforeInstantiation(beanClass, beanName); // bean实例实例化之前进行后置增强
if (result != null) {
return result;
}
}
[ 3 ] findCandidateAdvisiors()下的buildAspectAdvisiors()
> 执行时机:在bean实例或后置处理器初始化之后调用creator的后置处理方法时调用
> 作用:根据 aspectBeanNames集合来获取到第一次获取到的切面类名字,获取到标注 > 切面注解的通知方法,也就是增强器
> 操作范围:1、可以对单例对象操作 2、可以对原型对象(多例对象)操作
> 执行流程:1、第一次执行该方法的时候,会获取容器中所有bean实例,遍历获取增强器,将其放到了缓存当中
> 执行次数:每一个bean实例初始化的时候都会执行该方法
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
2、第二次或多次获取的时候,遍历切面类名集合,将名字作为key值获取增强器,放入到advisior()集合当中
if (cachedAdvisors != null) { // 表示切面类是单例对象
advisors.addAll(cachedAdvisors); // 缓存的增强器添加到增强器集合当中
}
三、AOP在其他环节的准备操作
> 执行例子:debug 需要功能增强的业务类的业务方法】
ApplicationContext context = new AnnotationConfigApplicationContext(Config1.class);
HelloService bean = context.getBean(HelloService.class);
bean.sayHello();
(1)首先,创建HelloService类,调用getBean()方法的时候
(2)bean实例创建之前,被resolveBeforeInstantiation()方法拦截,该方法是给用户一个机会返回一个bean实例的代理对象,Spring就不需要进行创建了
涉及后置处理器类型:InstantiationAwareBeanPostProcessor
关于AOP的后置处理器:creator本身也是一个 InstantiationAwareBeanPostProcessor
执行流程:调用postProcessBeforeInstantiation()方法对bean实例后置增强
功能:判断当前bean实例是否为切面类,获取到所有切面的增强器方法,观察是否有特殊的类
总结:该后置增强方法并没有真正执行关于AOP的操作
(3)bean实例创建过程中,被 applyMergedBeanDefinitionPostProcessors()方法拦截
> 涉及后置处理器类型: MergedBeanDefinitionPostProcessor
> 关于AOP的后置处理器:creator不是一个 MergedBeanDefinitionPostProcessor
> 总结:并没有真正任何关于AOP的操作
(4)bean实例属性赋值的时候,被 InstantiationAwareBeanPostProcessor处理器拦截
> 关于AOP的后置处理器:creator本身是一个InstantiationAwareBeanPostProcessor
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
return pvs; // skip postProcessPropertyValues 返回bean实例的原生对象,可以说明并没有AOP并没有起作用
}
> postProcessProperties()方法本身只返回一个原生对象,所以也没有处理AOP流程
(5)至此,bean实例的自动装配环节到此结束
> 说明:AOP的执行是在bean实例执行@Autowired注解自动装配环节之后的
(6)初始化bean实例的时候,被前置拦截
> 涉及后置处理器类型:BeanPostProcessor
> 关于AOP的后置处理器:creator本身是一个 BeanPostProcessor
> 执行方法:beanPostProcessor.postProcessBeforeInitialization()
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
> 返回了bean实例原生对象,可以说明并没有真正执行AOP的操作
(7)bean实例初始化后,被后置拦截
> 涉及后置处理器类型:BeanPostProcessor
> 关于AOP的后置处理器:creator本身是一个BeanPostProcessor
> 执行方法:beanPostProcessor.postProcessAfterInitialization()
> 以下可知:可以得知开始执行AOP的准备阶段了 ,重点分析
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
(8)获取cacheKey值,并且执行wrapIfNecessary()方法
> 根据bean实例的class信息和beanName获取对该类切入点增强的增强器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
> 寻找合法的增强器,并且进行条件判断(在getAdvicesAndAdvisiorsForBean())
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); // 找到合法的增强方法
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
> 调用creator的findCandidateAdvisiors()获取候选的增强器,并且判断是否可以切入
> 返回的增强器是六个,Spring内部注入了一个ExposeInvocationInterceptor()
List<Advisor> candidateAdvisors = findCandidateAdvisors(); // 从缓存拿到所有切面的增强器
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); // 看增强器能不能引用到这个实例上
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors); // 对增强器的执行顺序进行一个排序
}
return eligibleAdvisors;
> 执行上述两个方法之后,重点操作
> 由于特定拦截器不为空,所以为其创建代理对象
> 执行操作:获取增强器,获取代理工厂,为代理工厂设置一系列的属性
> 最终,返回结果的时候使用代理工厂创建代理对象
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE); // 将bean实例添加到已经增强的bean实例当中
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); // 创建代理
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return proxyFactory.getProxy(classLoader);
> 观察getProxy方法的时候,发现创建方式是cglib动态代理模式
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
> 执行完上述方法,创建代理对象的操作结束
(9)至此,创建完带有增强器方法的代理对象,AOP的准备阶段就已经结束了
四.AOP的运行流程
(1)调用IOC容器的getBean获取到代理对象,具体的获取步骤就不展示了
(2)执行切入点方法sayHello()方法
(3)由于HelloService对象是cglib代理对象,执行interceptor()回调方法
(4)执行方法的重点步骤proceed()
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); // proceed才是真正执行的关键
(5)调用父类的模板方法proceed()
return super.proceed(); // 调用父类的模板方法
(6)观察可知:proceed()执行的时候采用的是递归调用的方式,由于该步骤较为长,因此对此使用流程图的方式来
> 建议:一边跟着流程图,一边可以比对所给的流程图,您会发现新世界
链接:https://pan.baidu.com/s/1e1oZ8zxjCPG-7G4LN2hLeA
提取码:obr6
--来自百度网盘超级会员V3的分享
(7)至此,AOP的操作就到此结束了
五.总结
1、源码分析流程是我个人花费一个星期去一个一个分析出来,如果有不足的话,请大佬们指出
2、也希望你们能仔细看一下