我们从早期使用 AOP 的方式入手,走入 Spring AOP 源码。都说想要提升技术能力,多看看源码有利于提高自己的编码能力,事实也是如此。源码学习存在一些问题,枯燥无味还容易钻牛角尖。我们换个角度,从早期使用 Spring AOP 的方式入手,先了解 Spring AOP 的概貌。
先简单说一下常规使用到 Spring AOP 早期的使用方式,再讲解一些概念。这样从最简单最熟悉的地方入手,逐步深入学习,避免直入源码的茫然无措。
我们常规的使用 Spring AOP 都是通过注解的方式,定义切面、切点和通知。往前推一点还有 XML 配置,再往前就是通过实现接口配置切面的方式。后面主要说明最常用的注解形式,还有就是贴近源码的接口形式。
先直接上代码,从具体到抽象。定义一个目标 Bean,是我们 AOP 需要织入切面的目标。
@Component
public class TargetBean {
// 目标方法
public String message() {
return "TargetBean Message";
}
}
紧接着就定义切面,并再切面中声明通知和切点。
// 定义切面
@Aspect
@Component
public class AnnotationAop {
// 定义切点(AspectJ 表达式)
@Pointcut("execution(* com.devnolo.demo.spring.aop.target.TargetBean.message())")
public void pointCut() {
};
// 定义通知,使用切点表达式
@Before(value = "pointCut()")
public void aopBefore() {
System.out.println("AnnotationAop AopBefore");
}
}
一个切面就定义完成并且成功织入业务代码中了,到这里应该都是大家所容易理解,使用注解的方式实现 Spring AOP。
在贴上代码之前先说几个概念,然后再结合两种实现的代码就能很容易理解 Spring AOP 的基础概念了。接下来我们将认识到这几个概念:通知(Advice)、切点(Point Cut)、切面(Aspect)、顾问(Advisor)
什么是通知?通知在我的理解中是一段具体的代码,是我们所期望在业务代码前后执行的逻辑。
什么是切点?切点更多的是一段规则,我们是期望在某某方法的执行前执行我们的通知。
什么是切面?切面是一个抽象的概念,是一个完整的行为。例如我们需要在某某方法的执行前记录日志这是一个切面,这个切面包含两部分:记录日志的通知,确定执行位置的切点。
什么是顾问?顾问可以看出切面的实现,顾问通常承载了一个切面和一个切点(一段匹配规则)。所以顾问可以完成执行位置的匹配和逻辑代码的执行。
这里举一个通过实现 Spring 接口实现 AOP 的例子。
先定义一个通知(Advice)
// 实现 MethodBeforeAdvice 方法前置通知接口,并完成方法实现
public class AdviceAop implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("AopAdvice AopBefore");
}
}
在定义一个顾问(Advisor),由名字 NameMatchMethodPointcutAdvisor
可以看出这个顾问的匹配规则是通过方法名称进行匹配的,同样还有其他类型,例如正则。
@Configuration
public class AdvisorConfiguration {
@Bean
public NameMatchMethodPointcutAdvisor aspectAdvisor() {
// 顾问(Advisor、通知者):是经过包装后的细粒度控制方式(带了切点)
NameMatchMethodPointcutAdvisor advisor=new NameMatchMethodPointcutAdvisor();
// 通知(Advice) :是我们的通知类,就是一段逻辑代码
advisor.setAdvice(new AdviceAop());
// 声明切点规则(这里是匹配方法名称)
advisor.setMappedNames("message");
return advisor;
}
}
有一个稍微特殊的通知是环绕通知,它的接口定义是:MethodInterceptor
,同其他前置后置这类的命名规则有所差异。
概念其实在说接口实现 AOP 时已经说过了,我觉得在那里讲解更容易理解。在这里在做一次总结,也简单描述一下其他概念。
通知
切点
切面
顾问
连接点(JointPoint)
aMethod
前执行,那么 ClassA
的 aMethod
方法这就是一个连接点,ClassB
的 aMethod
也是一个切入点。目标(Target)
代理(Proxy)
最后贴一张图,期望帮助理解。
其实理解通过实现 Spring 接口的方式实现 AOP,以及 AOP 的相关概念的时候,已经算是理解了 Spring AOP 的基本实现,这里再做一个整合总结。
在使用 Spring AOP 的注解时,最后也会被封装成一个个的顾问(Advisor)。所以当理解接口的实现逻辑时,对于 Spring AOP 源码也有了基本认识,最近在学习 Spring 源码,有收货后再整理后续内容。