一起认识Spring

Spring的AOP(一)

spring中最重要的两个东西就是IOC(DI)和AOP,今天我们主要讲解有关AOP相关的知识,在了解AOP前,希望读者先了解动态代理的相关知识。

AOP我主要讲解通过注解的方式进行AOP的:

1.开启@Aspect注解,我们要让这个注解被扫描到,我们可以添加@EnableAspectJAutoProxy这个注解

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true,exposeProxy = true)
public class ApplicationConfig {
	//@EnableAspectJAutoProxy这个注解中,有proxyTargetClass和exposeProxy两个参数
    //proxyTargetClass 
   true 1、目标对象实现了接口 – 使用 CGLIB 代理机制 2、目标对象没有接口(只有实现类) – 使用 CGLIB 代理机制    false 1、目标对象实现了接口 – 使用 JDK 动态代理机制(代理所有实现了的接口) 2、目标对象没有接口(只有实现		   类) – 使用 CGLIB 代理机制
    //exposeProxy 
       该属性设置代理对象是否需要暴露,说白了就是是否需要把代理对象设置到 ThreadLocal 中
}

加入这个注解后,那些添加了@Aspect注解的类都会被扫描到,但是要注意的是,这些加了@Aspect注解的类他们也必须要加入到IOC容器中才能起作用,所以也需要添加类似于@component@service这样的注解讲该bean添加到IOC容器中,因为在扫描的时候是从容器中拿出所有的BeanDefinition来检测是否有添加@Aspect的,另外说下我们平时从IOC容器中拿到的bean其实就是这个BeanDefinition。

接下来我们进入源码看看整个流程:(本节主要讲解判断bean是否生成代理的过程)

首先是在bean实例化完成以后,会判断该bean是否生成代理,AOP的入口,是applyBeanPostProcessorsBeforeInitialization(bean, beanName);这个方法。这个方法调用前,会将bean创建出来,因为在创建代理类的时候,需要调用到原始的bean,所以必须在创建bean后才能能去创建代理类。
在这里插入图片描述接下来进入到initializeBean这个方法看看,在这个方法中就会调用到applyBeanPostProcessorsAfterInitialization这个入口方法,而在applyBeanPostProcessorsAfterInitialization中调用了postProcessorsAfterInitialization方法

在这里插入图片描述在这里插入图片描述在这里插入图片描述

那么我们就来看看getAdvicesAndAdvisorsForBean这个方法是如何拿到切面advisor的,看之前我们要了解到advisor是由advice增强和pointcut切点,这两个元素组成了一个切面,所以我去通过getAdvicesAndAdvisorsForBean方法拿到切面也就是去找到这两个元素然后组成切面的一个过程。
在这里插入图片描述

这个图中,我们可以看到有两步完成获取切面的这个任务,首先步骤一是获取到容器中所有带有@Aspect注解的类里的所有用@Before、@AfterReturning、@Around、@AfterThrowing、@After这五种注解修饰的方法作为advice增强然后加上相对应的pointcut表达式组成相对应的一个个切面,这些切面是备选切面,然后通过步骤二来完成匹配,选出pointCut表达式包含当前bean的切面,然后返回这些匹配成功的切面。
在这里插入图片描述在这里插入图片描述

下图是上图中判断是否包含Aspect注解的方法源码

在这里插入图片描述

接下来看看在getAdvisors方法中是如何创建切面的:

在这里插入图片描述

下图是上图中获取不包含pointCut注解的方法的过程源码

在这里插入图片描述

//首先还是强调一下那个概念,advisor里面最重要的是pointCut和Advice,所以我们要拿到这两东西创建切面advisor
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory 							aspectInstanceFactory, int declarationOrderInAspect, String aspectName) {
    this.validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
    //获取pointCut对象,最重要的是从注解中获取表达式
    AspectJExpressionPointcut expressionPointcut = this.getPointcut(candidateAdviceMethod, 									aspectInstanceFactory.getAspectMetadata().getAspectClass());
    //创建一个advisor切面类,这才是真正的切面类advisor,
    //其中pointCut是expressionPointcut,而Advice是candidateAdviceMethod
    return expressionPointcut == null ? null : new 														InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, 			  this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
    }

接下来看看如何获取pointCut和创建切面的。

在这里插入图片描述

下图就是上图中将注解信息封装成AspectJAnnotation对象的findAspectJAnnotationOnMethod方法源码

在这里插入图片描述

那么这个AspectJAnnotation里面的内容大概有下面这些东西

在这里插入图片描述

前三个图也就是创建了PointCut,接下来看看如何创建advisor,创建advisor是在InstantiationModelAwarePointcutAdvisorImpl这个方法里,我们进来看看这个方法:
在这里插入图片描述

可以看到创建advisor过程中会创建一个advice增强然后放到advisor中。那么接下来看看advice增强是如何创建的:

在这里插入图片描述
在这里插入图片描述

其中AspectJAroundAdvice、AspectJAfterAdvice、AspectJAfterThrowingAdvice这三个实现了MethodInterceptor接口,而AspectJMethodBeforeAdvice实现了MethodBeforeAdvice和AspectJAfterReturningAdvice实现了AfterReturningAdvice,他们两个并没有实现MethodInterceptor。这个点在后面调用代理类的时候会说到,大家需要注意到。

到这里所有候选的切面也就都拿到了,也就是完成了本文中第五个图中的第一步,下面就来看看第二步所有切面与当前bean进行匹配,然后进行排序再返回。从findAdvisorsThatCanApply这个方法开始

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

至此,本文图五中的两步完成,也就找到了所有与该bean相关的切面,如果返回的这个切面为空数组,则表示没有切面对当前并进行增强,则不生产代理对象,如果切面数组不为空,则表示有切面增强,则需要生成代理对象。下一篇文章将会带大家看看如何生成代理类,并看看代理类是如何增强调用的。

以上就是本节内容,谢谢大家的阅读,如有错漏,欢迎评论区指正提出😚!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值