10 Spring AOP源码解析
目录
Pt1 Spring AOP基础知识
AOP是Aspect Oriented Programming的缩写,意思是面向切面编程,通过预编译和运行时的动态代理,实现在不修改源代码的情况下给程序动态添加功能。同时AOP也为服务方和调用方实现解耦提供了很有效的方式。
在日常编码中,通常分为业务代码和非业务代码,比如事务、日志等,这些代码和业务代码混在一起。举个最常见的例子,就是JDBC的事务处理,有大量的模板代码是的事务处理代码,这些大量重复的、复制粘贴的、和业务处理无关的代码,为维护带来了风险和困难。AOP通过代理机制,可以将这些非业务代码剥离,使得他们可以独立于业务代码存在,从而降低维护的难度和风险。
所以,Spring AOP是一种编程范式,主要目的是将非功能性需求从功能型需求中分离出来,达到解耦的目标。
Pt1.1 AOP核心概念
-
Aspect(切面)
Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。
-
Jointpoint(连接点)
表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。
-
Pointcut(切点)
表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。
-
Advice(增强)
Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。
-
@Before:该注解标注的方法在业务模块代码执行之前执行,其不能阻止业务模块的执行,除非抛出异常;
-
@AfterReturning:该注解标注的方法在业务模块代码执行之后执(正常返回)行;
-
@AfterThrowing:该注解标注的方法在业务模块抛出指定异常后执行;
-
@After:该注解标注的方法在所有的Advice执行完成后执行,无论业务模块是否抛出异常,类似于finally的作用;
-
@Around:该注解功能最为强大,其所标注的方法用于编写包裹业务模块执行的代码,其可以传入一个ProceedingJoinPoint用于调用业务模块的代码,无论是调用前逻辑还是调用后逻辑,都可以在该方法中编写,甚至其可以根据一定的条件而阻断业务模块的调用;
-
@DeclareParents:其是一种Introduction类型的模型,在属性声明上使用,主要用于为指定的业务模块添加新的接口和相应的实现。
-
@Aspect:严格来说,其不属于一种Advice,该注解主要用在类声明上,指明当前类是一个组织了切面逻辑的类,并且该注解中可以指定当前类是何种实例化方式,主要有三种:singleton、perthis和pertarget,具体的使用方式后面会进行讲解。
-
-
Target(目标对象)
织入 Advice 的目标对象.。目标对象可以被一个或者多个切面织入。
-
Weaving(织入)
将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程,就是执行method同时执行advice。
-
AOP代理(AopProxy)
在Spring中有两种形式的代理:JDK动态代理和CGLib代理。后面会详细介绍。
Pt1.2 AOP切点配置规则
(1) execution
由于Spring切面粒度最小是达到方法级别,而execution表达式可以用于明确指定方法返回类型,类名,方法名和参数名等与方法相关的部件,并且在Spring中,大部分需要使用AOP的业务场景也只需要达到方法级别即可,因而execution表达式的使用是最为广泛的。
如下是execution表达式的语法:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)
这里问号表示当前项可以有也可以没有,其中各项的语义如下:
-
modifiers-pattern:方法的可见性,如public,protected;
-
ret-type-pattern:方法的返回值类型,如int,void等;
-
declaring-type-pattern:方法所在类的全路径名,如com.spring.Aspect;
-
name-pattern:方法名类型,如buisinessService();
-
param-pattern:方法的参数类型,如java.lang.String;
-
throws-pattern:方法抛出的异常类型,如java.lang.Exception;
如下是一个使用execution表达式的例子:
execution(public * com.spring.service.BusinessObject.businessService(java.lang.String,..))
上述切点表达式将会匹配使用public修饰,返回值为任意类型,并且是com.spring.BusinessObject类中名称为businessService的方法,方法可以有多个参数,但是第一个参数必须是java.lang.String类型的方法。上述示例中我们使用了..通配符,关于通配符的类型,主要有两种:
-
*通配符,该通配符主要用于匹配单个单词,或者是以某个词为前缀或后缀的单词。
如下示例表示返回值为任意类型,在com.spring.service.BusinessObject类中,并且参数个数为零的方法:
execution(* com.spring.service.BusinessObject.*())
下述示例表示返回值为任意类型,在com.spring.service包中,以Business为前缀的类,并且是类中参数个数为零方法:
execution(* com.spring.service.Business*.*())
-
..通配符,该通配符表示0个或多个项,主要用于declaring-type-pattern和param-pattern中,如果用于declaring-type-pattern中,则表示匹配当前包及其子包,如果用于param-pattern中,则表示匹配0个或多个参数。
如下示例表示匹配返回值为任意类型,并且是com.spring.service包及其子包下的任意类的名称为businessService的方法,而且该方法不能有任何参数:
execution(* com.spring.service..*.businessService())
这里需要说明的是,包路径service...businessService()中的..应该理解为延续前面的service路径,表示到service路径为止,或者继续延续service路径,从而包括其子包路径;后面的.businessService(),这里的*表示匹配一个单词,因为是在方法名前,因而表示匹配任意的类。
如下示例是使用..表示任意个数的参数的示例,需要注意,表示参数的时候可以在括号中事先指定某些类型的参数,而其余的参数则由..进行匹配:
execution(* com.spring.service.BusinessObject.businessService(java.lang.String,..))
(2) within
within表达式的粒度为类,其参数为全路径的类名(可使用通配符),表示匹配当前表达式的所有类都将被当前方法环绕。如下是within表达式的语法:
within(declaring-type-pattern)
within表达式只能指定到类级别,如下示例表示匹配com.spring.service.BusinessObject中的所有方法:
within(com.spring.service.BusinessObject)
within表达式路径和类名都可以使用通配符进行匹配,比如如下表达式将匹配com.spring.service包下的所有类,不包括子包中的类:
within(com.spring.service.*)
如下表达式表示匹配com.spring.service包及子包下的所有类:
within(com.spring.service..*)
(3) args
args表达式的作用是匹配指定参数类型和指定参数数量的方法,无论其类路径或者是方法名是什么。这里需要注意的是,args指定的参数必须是全路径的。如下是args表达式的语法:
args(param-pattern)
如下示例表示匹配所有只有一个参数,并且参数类型是java.lang.String类型的方法:
args(java.lang.String)
也可以使用通配符,但这里通配符只能使用..,而不能使用*。如下是使用通配符的实例,该切点表达式将匹配第一个参数为java.lang.String,最后一个参数为java.lang.Integer,并且中间可以有任意个数和类型参数的方法:
args(java.lang.String,..,java.lang.Integer)
Pt2 Spring AOP使用示例
Pt2.1 AOP日志(XML)
-
<?xml version="1.0" encoding="UTF-8"?>
-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
-
<modelVersion>4.0.0
</modelVersion>
-
<parent>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-parent
</artifactId>
-
<version>2.4.4
</version>
-
<relativePath/>
<!-- lookup parent from repository -->
-
</parent>
-
<groupId>com.example
</groupId>
-
<artifactId>spring-demo
</artifactId>
-
<version>0.0.1-SNAPSHOT
</version>
-
<name>spring-demo
</name>
-
<description>Demo project for Spring Boot
</description>
-
<properties>
-
<java.version>11
</java.version>
-
</properties>
-
<dependencies>
-
<dependency>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-web
</artifactId>
-
</dependency>
-
-
<dependency>
-
<groupId>org.projectlombok
</groupId>
-
<artifactId>lombok
</artifactId>
-
<optional>true
</optional>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-test
</artifactId>
-
<scope>test
</scope>
-
</dependency>
-
-
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
-
<dependency>
-
<groupId>org.aspectj
</groupId>
-
<artifactId>aspectjweaver
</artifactId>
-
<version>1.9.6
</version>
-
</dependency>
-
-
</dependencies>
-
-
<build>
-
<plugins>
-
<plugin>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-maven-plugin
</artifactId>
-
<configuration>
-
<excludes>
-
<exclude>
-
<groupId>org.projectlombok
</groupId>
-
<artifactId>lombok
</artifactId>
-
</exclude>
-
</excludes>
-
</configuration>
-
</plugin>
-
</plugins>
-
</build>
-
-
</project>
-
<?xml version="1.0" encoding="UTF-8"?>
-
<beans xmlns="http://www.springframework.org/schema/beans"
-
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
-
xmlns:context=
"http://www.springframework.org/schema/context"
-
xmlns:mvc=
"http://www.springframework.org/schema/mvc"
xmlns:aop=
"http://www.springframework.org/schema/aop"
-
xsi:schemaLocation=
"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
-
-
<!-- 自动扫描装配 -->
-
<context:component-scan base-package="com.example.springdemo"/>
-
-
<!--启用spring的一些annotation -->
-
<context:annotation-config/>
-
-
<!-- AOP配置 -->
-
<bean id="logAspect" class="com.example.springdemo.aop.log.LogAspect">
</bean>
-
-
<aop:config>
-
<aop:aspect id="log" ref="logAspect">
-
<aop:pointcut id="logPointcut" expression="execution(* com.example.springdemo.controller.LogController.LogDemo(..))"/>
-
<aop:before method="logBefore" pointcut-ref="logPointcut"/>
-
<aop:after method="logAfter" pointcut-ref="logPointcut"/>
-
</aop:aspect>
-
</aop:config>
-
</beans>
-
@Configuration
-
@ImportResource(locations = {"classpath:spring.xml"})
-
public
class ConfigClass {
-
}
-
public
class LogAspect {
-
-
public LogAspect() {
-
System.out.println(
"init");
-
}
-
-
public void logBefore() {
-
System.out.println(
"Before execution log.");
-
}
-
-
public void logAfter() {
-
System.out.println(
"After execution log.");
-
}
-
}
-
@RestController
-
public
class LogController {
-
-
@RequestMapping(value = "logAop", method = RequestMethod.GET)
-
public String LogDemo() {
-
return
"Execute Log Aop test.";
-
}
-
}
-
Before execution
log.
-
After execution
log.
Pt2.2 JDBC(Annotation)
-
<?xml version="1.0" encoding="UTF-8"?>
-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
-
<modelVersion>4.0.0
</modelVersion>
-
<parent>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-parent
</artifactId>
-
<version>2.4.4
</version>
-
<relativePath/>
<!-- lookup parent from repository -->
-
</parent>
-
<groupId>com.example
</groupId>
-
<artifactId>spring-demo
</artifactId>
-
<version>0.0.1-SNAPSHOT
</version>
-
<name>spring-demo
</name>
-
<description>Demo project for Spring Boot
</description>
-
<properties>
-
<java.version>11
</java.version>
-
</properties>
-
<dependencies>
-
<dependency>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-web
</artifactId>
-
</dependency>
-
-
<dependency>
-
<groupId>org.projectlombok
</groupId>
-
<artifactId>lombok
</artifactId>
-
<optional>true
</optional>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-test
</artifactId>
-
<scope>test
</scope>
-
</dependency>
-
-
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
-
<dependency>
-
<groupId>org.aspectj
</groupId>
-
<artifactId>aspectjweaver
</artifactId>
-
<version>1.9.6
</version>
-
</dependency>
-
-
</dependencies>
-
-
<build>
-
<plugins>
-
<plugin>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-maven-plugin
</artifactId>
-
<configuration>
-
<excludes>
-
<exclude>
-
<groupId>org.projectlombok
</groupId>
-
<artifactId>lombok
</artifactId>
-
</exclude>
-
</excludes>
-
</configuration>
-
</plugin>
-
</plugins>
-
</build>
-
-
</project>
-
@Component
-
@Aspect
-
public
class JdbcAspect {
-
-
// 定义切点
-
@Pointcut("execution(* com.example.springdemo.controller.JdbcController.jdbcDemo(..))")
-
public void jdbcPointcut() {
-
}
-
-
@Before("JdbcAspect.jdbcPointcut()")
-
public void jdbcBefore() {
-
System.out.println(
"begin transaction");
-
}
-
-
@AfterReturning("JdbcAspect.jdbcPointcut()")
-
public void jdbcAfter() {
-
System.out.println(
"commit transaction");
-
}
-
-
@AfterThrowing("JdbcAspect.jdbcPointcut()")
-
public void jdbcException() {
-
System.out.println(
"rollback transaction");
-
}
-
}
-
@RestController
-
public
class JdbcController {
-
-
@RequestMapping(value = "jdbcAop", method = RequestMethod.GET)
-
public String jdbcDemo() {
-
return
"Execute jdbc Aop test.";
-
}
-
}
-
begin transaction
-
commit transaction
Pt3 Spring AOP核心类
Pt3.1 BeanPostProcessor
BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口,它可以监听容器触发的Bean生命周期事件。向容器中注册BeanPostProcessor之后,容器中管理的Bean就具备了接受IoC容器回调事件的能力。
源码如下:
-
/**
-
* BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口,它可以监听容器触发的Bean生命周期事件。
-
* 向容器中注册BeanPostProcessor之后,容器中管理的Bean就具备了接受IoC容器回调事件的能力。
-
*
-
* 他提供的两个回调方法和容器管理的Bean生命周期事件密切相关,可以为用户提供在Spring IoC容器初始化Bean过程中,去自定义的处理操作提供钩子事件。
-
*/
-
public
interface BeanPostProcessor {
-
-
// 在Bean的初始化之前提供回调入口
-
@Nullable
-
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
-
return bean;
-
}
-
-
// 在Bean的初始化之后提供回调入口
-
@Nullable
-
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
-
return bean;
-
}
-
}
Pt3.2 TargetSource
在Spring代理目标bean的时候,其并不是直接创建一个目标bean的对象实例的,而是通过一个TargetSource类型的对象将目标bean进行封装,Spring Aop获取目标对象始终是通过TargetSource.getTarget()方法进行的。
换句话说,proxy(代理对象)代理的不是target,而是TargetSource。
通常情况下,一个proxy(代理对象)只能代理一个target,每次方法调用的目标也是唯一固定的target。但是,如果让proxy代理TargetSource,可以使得每次方法调用的target实例都不同(当然也可以相同,这取决于TargetSource实现)。这种机制使得方法调用变得灵活,可以扩展出很多高级功能,如: target pool(目标对象池)、hot swap(运行时目标对象热替换),等等。
源码实现:
-
/**
-
* 在Spring代理目标bean的时候,其并不是直接创建一个目标bean的对象实例的,而是通过一个TargetSource类型的对象将目标bean进行封装,
-
* Spring Aop获取目标对象始终是通过TargetSource.getTarget()方法进行的。
-
* 换句话说,proxy(代理对象)代理的不是target,而是TargetSource。
-
*
-
* 通常情况下,一个proxy(代理对象)只能代理一个target,每次方法调用的目标也是唯一固定的target。但是,如果让proxy代理TargetSource,
-
* 可以使得每次方法调用的target实例都不同(当然也可以相同,这取决于TargetSource实现)。
-
* 这种机制使得方法调用变得灵活,可以扩展出很多高级功能,如:target pool(目标对象池)、hot swap(运行时目标对象热替换),等等。
-
*/
-
public
interface TargetSource extends TargetClassAware {
-
-
// 本方法主要用于返回目标bean的Class类型
-
@Override
-
@Nullable
-
Class<?> getTargetClass();
-
-
// 这个方法用户返回当前bean是否为静态的,比如常见的单例bean就是静态的,而prototype就是动态的,
-
// 这里这个方法的主要作用是,对于静态的bean,spring是会对其进行缓存的,在多次使用TargetSource
-
// 获取目标bean对象的时候,其获取的总是同一个对象,通过这种方式提高效率
-
boolean isStatic();
-
-
// 获取目标bean对象,这里可以根据业务需要进行自行定制
-
@Nullable
-
Object getTarget() throws Exception;
-
-
// Spring在用完目标bean之后会调用这个方法释放目标bean对象,对于一些需要池化的对象,这个方法是必须
-
// 要实现的,这个方法默认不进行任何处理
-
void releaseTarget(Object target) throws Exception;
-
}
Pt3.3 Advice
Advice表示的是在Pointcut切点上应该执行的方法,即切面Aspect中定义的方法逻辑。
这些方法可以在目标方法之前、之后、包裹、抛出异常等等任何地方执行。
源码:
-
// 标记通知方法
-
public
interface Advice {
-
-
}
Pt3.4 Advisor
Advisor是 Pointcut 与 Advice 的组合,Advice 是执行的通知方法,而要知道方法何时执行,则 Advice 必需与 Pointcut 组合在一起,这就诞生了 Advisor 。
-
Advice表示通知的内容
-
Pointcut表示通知的时机
-
Advisor表示通知人(它知道通知的时机,且知道是通知的内容)
下图是Advisor的类图:
Advisor是顶层抽象接口,定义了操作Advice的行为:
-
// Pointcut 与 Advice 的组合
-
public
interface Advisor {
-
-
// 空的Advice通知
-
Advice EMPTY_ADVICE =
new Advice() {};
-
-
// 获取通知方法
-
Advice getAdvice();
-
-
// 判定当前Advice是否和特定目标值相关
-
boolean isPerInstance();
-
}
PointcutAdvisor继承Advisor,定义了操作Pointcut行为,此时具体了可以操作Pointcut和Advice的行为:
-
public
interface PointcutAdvisor extends Advisor {
-
-
// 获取Advisor关联的Pointcut
-
Pointcut getPointcut();
-
}
AbstractPointcutAdvisor新增了排序和序列化的能力:
-
// AbstractPointcutAdvisor是在PointcutAdvisor的基础上,增加Ordered和Serializable接口的能力。
-
// Spring就提供了Ordered这个接口,来处理相同接口实现类的优先级问题。
-
@SuppressWarnings("serial")
-
public
abstract
class AbstractPointcutAdvisor implements PointcutAdvisor, Ordered, Serializable {
-
// order用于标记执行的优先级。
-
@Nullable
-
private Integer order;
-
-
// 调用者可以手动来指定Order
-
public void setOrder(int order) {
-
this.order = order;
-
}
-
-
// 获取执行顺序
-
@Override
-
public int getOrder() {
-
if (
this.order !=
null) {
-
return
this.order;
-
}
-
-
// 若调用者没有指定Order,那就拿advice的order为准(若有),否则LOWEST_PRECEDENCE表示最后执行
-
Advice advice = getAdvice();
-
if (advice
instanceof Ordered) {
-
return ((Ordered) advice).getOrder();
-
}
-
return Ordered.LOWEST_PRECEDENCE;
-
}
-
-
// 该属性还没有被Spring使用,永远返回TURE
-
@Override
-
public boolean isPerInstance() {
-
return
true;
-
}
-
-
-
@Override
-
public boolean equals(@Nullable Object other) {
-
if (
this == other) {
-
return
true;
-
}
-
if (!(other
instanceof PointcutAdvisor)) {
-
return
false;
-
}
-
PointcutAdvisor otherAdvisor = (PointcutAdvisor) other;
-
return (ObjectUtils.nullSafeEquals(getAdvice(), otherAdvisor.getAdvice()) &&
-
ObjectUtils.nullSafeEquals(getPointcut(), otherAdvisor.getPointcut()));
-
}
-
-
@Override
-
public int hashCode() {
-
return PointcutAdvisor.class.hashCode();
-
}
-
}
AbstractGenericPointcutAdvisor保存Advice对象:
-
public
abstract
class AbstractGenericPointcutAdvisor extends AbstractPointcutAdvisor {
-
// 保存Advisor关联的Advice
-
private Advice advice = EMPTY_ADVICE;
-
-
// setter and getter
-
public void setAdvice(Advice advice) {
-
this.advice = advice;
-
}
-
@Override
-
public Advice getAdvice() {
-
return
this.advice;
-
}
-
-
@Override
-
public String toString() {
-
return getClass().getName() +
": advice [" + getAdvice() +
"]";
-
}
-
}
DefaultPointcutAdvisor是功能最强大的Advisor,保存了Advice和Pointcut对象,同时具备操作这两个对象的能力:
-
public
class DefaultPointcutAdvisor extends AbstractGenericPointcutAdvisor implements Serializable {
-
// 保存Advisor关联的Pointcut对象
-
private Pointcut pointcut = Pointcut.TRUE;
-
-
// 获取空的Advisor,在使用前必须指定Pointcut对象和Advice对象。
-
public DefaultPointcutAdvisor() {
-
}
-
-
// 根据指定Advice和默认的Pointcut生成Advisor对象,使用默认Pointcut时,Advice将匹配所有方法。
-
public DefaultPointcutAdvisor(Advice advice) {
-
this(Pointcut.TRUE, advice);
-
}
-
-
// 根据指定Pointcut和Advice生成Advisor对象
-
public DefaultPointcutAdvisor(Pointcut pointcut, Advice advice) {
-
this.pointcut = pointcut;
-
setAdvice(advice);
-
}
-
-
// setter and getter
-
public void setPointcut(@Nullable Pointcut pointcut) {
-
this.pointcut = (pointcut !=
null ? pointcut : Pointcut.TRUE);
-
}
-
@Override
-
public Pointcut getPointcut() {
-
return
this.pointcut;
-
}
-
-
@Override
-
public String toString() {
-
return getClass().getName() +
": pointcut [" + getPointcut() +
"]; advice [" + getAdvice() +
"]";
-
}
-
}
Pt3.5 Advised
Advised是对整个代理执行的抽象,创建代理的工厂ProxyFactory,Bean工厂BeanFactory都在该接口中保存。该接口维护了一些代理必要的属性,以及对 Advice,Advisor,Interceptor 的操作,任何被 Spring 代理的对象都可以强转为 Advised。
从Advised类图中可以看到,实现类ProxyFactory是创建AOP代理类的工厂。
(1) TargetClassAware
接口TargetClassAware表明代理类拥有对目标代理类的操作权限git,具体可以看Aware接口的介绍。
(2) Advised
Advised是核心接口,拥有对代理工厂、目标工厂、目标类的操作能力。
-
// Advised 接口的实现着主要是代理生成的对象与AdvisedSupport (Advised的支持器)
-
public
interface Advised extends TargetClassAware {
-
-
// 这个 frozen 决定是否 AdvisedSupport 里面配置的信息是否改变
-
boolean isFrozen();
-
-
// 是否代理指定的类, 而不是一些 Interface
-
boolean isProxyTargetClass();
-
-
// 返回代理的接口
-
Class<?>[] getProxiedInterfaces();
-
-
// 判断这个接口是否是被代理的接口
-
boolean isInterfaceProxied(Class<?> intf);
-
-
// 设置代理的目标对象
-
void setTargetSource(TargetSource targetSource);
-
-
// 获取代理的对象
-
TargetSource getTargetSource();
-
-
// 判断是否需要将 代理的对象暴露到 ThreadLocal中, 而获取对应的代理对象则通过 AopContext 获取
-
void setExposeProxy(boolean exposeProxy);
-
-
// 返回是否应该暴露 代理对象
-
boolean isExposeProxy();
-
-
// 设置 Advisor 是否已经在前面过滤过是否匹配 Pointcut (极少用到)
-
void setPreFiltered(boolean preFiltered);
-
-
// 获取 Advisor 是否已经在前面过滤过是否匹配 Pointcut (极少用到)
-
boolean isPreFiltered();
-
-
// 获取所有的 Advisor
-
Advisor[] getAdvisors();
-
-
// 增加 Advisor 到链表的最后
-
void addAdvisor(Advisor advisor) throws AopConfigException;
-
-
// 在指定位置增加 Advisor
-
void addAdvisor(int pos, Advisor advisor) throws AopConfigException;
-
-
// 删除指定的 Advisor
-
boolean removeAdvisor(Advisor advisor);
-
-
// 删除指定位置的 Advisor
-
void removeAdvisor(int index) throws AopConfigException;
-
-
// 返回 Advisor 所在位置de index
-
int indexOf(Advisor advisor);
-
-
// 将指定的两个 Advisor 进行替换
-
boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;
-
-
// 增加 Advice <- 这个Advice将会包裹成 DefaultPointcutAdvisor
-
void addAdvice(Advice advice) throws AopConfigException;
-
-
// 在指定 index 增加 Advice <- 这个Advice将会包裹成 DefaultPointcutAdvisor
-
void addAdvice(int pos, Advice advice) throws AopConfigException;
-
-
// 删除给定的 Advice
-
boolean removeAdvice(Advice advice);
-
-
// 获取 Advice 的索引位置
-
int indexOf(Advice advice);
-
-
// 将 ProxyConfig 通过 String 形式返回
-
String toProxyConfigString();
-
}
(3) ProxyConfig
保存了创建代理类的配置属性。
-
// 创建AOP代理类的配置
-
public
class ProxyConfig implements Serializable {
-
-
/** use serialVersionUID from Spring 1.2 for interoperability. */
-
private
static
final
long serialVersionUID = -
8409359707199703185L;
-
-
// 标记是否直接对目标类进行代理,而不是通过接口产生代理
-
// 或者说,标记是否使用CGLIB动态代理,true,表示使用CGLIB的方式产生代理对象,false,表示使用JDK动态代理
-
private
boolean proxyTargetClass =
false;
-
-
// 标记是否进行优化。启动优化通常意味着在代理对象被创建后,增强的修改将不会生效,因此默认值为false。
-
// 如果exposeProxy设置为true,即使optimize为true也会被忽略。
-
private
boolean optimize =
false;
-
-
// 标记是否需要阻止通过该配置创建的代理对象转换为Advised类型,默认值为false,表示代理对象可以被转换为Advised类型
-
boolean opaque =
false;
-
-
// 标记代理对象是否应该被aop框架通过AopContext以ThreadLocal的形式暴露出去。
-
// 当一个代理对象需要调用它自己的另外一个代理方法时,这个属性将非常有用。默认是是false,以避免不必要的拦截。
-
boolean exposeProxy =
false;
-
-
// 标记该配置是否需要被冻结,如果被冻结,将不可以修改增强的配置。
-
// 当我们不希望调用方修改转换成Advised对象之后的代理对象时,这个配置将非常有用。
-
private
boolean frozen =
false;
-
-
// setter and getter
-
public void setProxyTargetClass(boolean proxyTargetClass) {
-
this.proxyTargetClass = proxyTargetClass;
-
}
-
public boolean isProxyTargetClass() {
-
return
this.proxyTargetClass;
-
}
-
-
public void setOptimize(boolean optimize) {
-
this.optimize = optimize;
-
}
-
public boolean isOptimize() {
-
return
this.optimize;
-
}
-
-
public void setOpaque(boolean opaque) {
-
this.opaque = opaque;
-
}
-
public boolean isOpaque() {
-
return
this.opaque;
-
}
-
-
public void setExposeProxy(boolean exposeProxy) {
-
this.exposeProxy = exposeProxy;
-
}
-
public boolean isExposeProxy() {
-
return
this.exposeProxy;
-
}
-
-
public void setFrozen(boolean frozen) {
-
this.frozen = frozen;
-
}
-
public boolean isFrozen() {
-
return
this.frozen;
-
}
-
-
// 浅拷贝
-
public void copyFrom(ProxyConfig other) {
-
Assert.notNull(other,
"Other ProxyConfig object must not be null");
-
this.proxyTargetClass = other.proxyTargetClass;
-
this.optimize = other.optimize;
-
this.exposeProxy = other.exposeProxy;
-
this.frozen = other.frozen;
-
this.opaque = other.opaque;
-
}
-
-
@Override
-
public String toString() {
-
StringBuilder sb =
new StringBuilder();
-
sb.append(
"proxyTargetClass=").append(
this.proxyTargetClass).append(
"; ");
-
sb.append(
"optimize=").append(
this.optimize).append(
"; ");
-
sb.append(
"opaque=").append(
this.opaque).append(
"; ");
-
sb.append(
"exposeProxy=").append(
this.exposeProxy).append(
"; ");
-
sb.append(
"frozen=").append(
this.frozen);
-
return sb.toString();
-
}
-
}
(4) AdvisedSupport
AdvisedSupport是用于生成Aop代理类的辅助类,保存了目标类、Advisor和method之间的关系。
-
public
class AdvisedSupport extends ProxyConfig implements Advised {
-
-
/** use serialVersionUID from Spring 2.0 for interoperability. */
-
private
static
final
long serialVersionUID =
2651364800145442165L;
-
-
// 默认空的TargetSource
-
public
static
final TargetSource EMPTY_TARGET_SOURCE = EmptyTargetSource.INSTANCE;
-
TargetSource targetSource = EMPTY_TARGET_SOURCE;
-
-
/** Whether the Advisors are already filtered for the specific target class. */
-
// 当前Advisor是否已经过滤了目标类
-
private
boolean preFiltered =
false;
-
-
/** The AdvisorChainFactory to use. */
-
AdvisorChainFactory advisorChainFactory =
new DefaultAdvisorChainFactory();
-
-
/** Cache with Method as key and advisor chain List as value. */
-
// 缓存method和Advisor之间关系
-
private
transient Map<MethodCacheKey, List<Object>> methodCache;
-
-
// 目标代理类继承的接口
-
private List<Class<?>> interfaces =
new ArrayList<>();
-
-
// 关联的Advisor
-
private List<Advisor> advisors =
new ArrayList<>();
-
private Advisor[] advisorArray =
new Advisor[
0];
-
-
// 方法基本都是对于属性的操作
-
// ......
-
}
(5) ProxyCreatorSupport
生成代理类的辅助类ProxyCreatorSupport。
-
public
class ProxyCreatorSupport extends AdvisedSupport {
-
-
// AOP代理类生成工厂,用于创建代理类。
-
private AopProxyFactory aopProxyFactory;
-
-
// 监听Advisor的变化
-
private
final List<AdvisedSupportListener> listeners =
new ArrayList<>();
-
-
// 第一个AopProxyu对象生成时置为True
-
private
boolean active =
false;
-
-
public ProxyCreatorSupport() {
-
this.aopProxyFactory =
new DefaultAopProxyFactory();
-
}
-
public ProxyCreatorSupport(AopProxyFactory aopProxyFactory) {
-
Assert.notNull(aopProxyFactory,
"AopProxyFactory must not be null");
-
this.aopProxyFactory = aopProxyFactory;
-
}
-
-
// aopProxyFactory的setter/getter
-
public void setAopProxyFactory(AopProxyFactory aopProxyFactory) {
-
Assert.notNull(aopProxyFactory,
"AopProxyFactory must not be null");
-
this.aopProxyFactory = aopProxyFactory;
-
}
-
public AopProxyFactory getAopProxyFactory() {
-
return
this.aopProxyFactory;
-
}
-
-
// 操作AdvisedSupportListener
-
public void addListener(AdvisedSupportListener listener) {
-
Assert.notNull(listener,
"AdvisedSupportListener must not be null");
-
this.listeners.add(listener);
-
}
-
public void removeListener(AdvisedSupportListener listener) {
-
Assert.notNull(listener,
"AdvisedSupportListener must not be null");
-
this.listeners.remove(listener);
-
}
-
-
-
// 获取AopProxy,用于生成Bean的代理类
-
protected final synchronized AopProxy createAopProxy() {
-
// 第一个AopProxy被创建时,执行以下激活操作。
-
if (!
this.active) {
-
activate();
-
}
-
-
// 获取AopProxy,用于生成Bean的代理类
-
return getAopProxyFactory().createAopProxy(
this);
-
}
-
-
// 激活AopProxy配置。
-
private void activate() {
-
this.active =
true;
-
for (AdvisedSupportListener listener :
this.listeners) {
-
listener.activated(
this);
-
}
-
}
-
-
// 监听advice变更事件
-
@Override
-
protected void adviceChanged() {
-
super.adviceChanged();
-
synchronized (
this) {
-
if (
this.active) {
-
for (AdvisedSupportListener listener :
this.listeners) {
-
listener.adviceChanged(
this);
-
}
-
}
-
}
-
}
-
-
protected final synchronized boolean isActive() {
-
return
this.active;
-
}
-
}
(6) ProxyFactory
ProxyFactory是生成目标AOP代理类的工厂类。
-
public
class ProxyFactory extends ProxyCreatorSupport {
-
-
public ProxyFactory() {
-
}
-
-
// 根据目标类生成代理类
-
public ProxyFactory(Object target) {
-
setTarget(target);
-
setInterfaces(ClassUtils.getAllInterfaces(target));
-
}
-
-
// 根据目标接口生成代理类
-
public ProxyFactory(Class<?>... proxyInterfaces) {
-
setInterfaces(proxyInterfaces);
-
}
-
-
public ProxyFactory(Class<?> proxyInterface, Interceptor interceptor) {
-
addInterface(proxyInterface);
-
addAdvice(interceptor);
-
}
-
-
public ProxyFactory(Class<?> proxyInterface, TargetSource targetSource) {
-
addInterface(proxyInterface);
-
setTargetSource(targetSource);
-
}
-
-
// 生成代理类
-
public Object getProxy() {
-
return createAopProxy().getProxy();
-
}
-
-
// 基于指定的ClassLoader和Factory设置,创建AOP代理类。
-
public Object getProxy(@Nullable ClassLoader classLoader) {
-
// createAopProxy():获取AOP代理类,有JdkDynamicAopProxy和CglibAopProxy两种。
-
// getProxy:使用AOP代理类,生成目标Bean的代理类。
-
// 这里假定使用JdkDynamicAopProxy的方式执行getProxy方法
-
return createAopProxy().getProxy(classLoader);
-
}
-
-
// 生成代理类
-
public
static <T>
T getProxy(Class<T> proxyInterface, Interceptor interceptor) {
-
return (T)
new ProxyFactory(proxyInterface, interceptor).getProxy();
-
}
-
-
// 生成代理类
-
@SuppressWarnings("unchecked")
-
public
static <T>
T getProxy(Class<T> proxyInterface, TargetSource targetSource) {
-
return (T)
new ProxyFactory(proxyInterface, targetSource).getProxy();
-
}
-
-
// 生成代理类
-
public static Object getProxy(TargetSource targetSource) {
-
if (targetSource.getTargetClass() ==
null) {
-
throw
new IllegalArgumentException(
"Cannot create class proxy for TargetSource with null target class");
-
}
-
ProxyFactory proxyFactory =
new ProxyFactory();
-
proxyFactory.setTargetSource(targetSource);
-
proxyFactory.setProxyTargetClass(
true);
-
return proxyFactory.getProxy();
-
}
-
}
Pt3.6 Pointcut
Pointcut是AOP中非常重要的一个类,它定义了AOP切点逻辑,约定了Advice通知的时机。
我们先来看看其中一个实现类AspectJExpressionPointcut类的相关类图。
从类图上可以看出,AspectJExpressionPointcut主要有4个顶层接口:
-
Pointcut:定义和切点相关的能力。
-
Aware:标记当前类具备某种行为的感知能力。
-
MethodMatcher:用来匹配mehtod是否匹配切点的规则,从而决定是否需要通知Advice。
-
ClassFilter:用来匹配Class是否匹配切点规则。
ClassFilter限定在类级别上,MethodMatcher限定在方法级别上。
首先来看Pointcut顶层接口的能力:
-
// 切点的顶层抽象接口
-
public
interface Pointcut {
-
-
// 返回当前Pointcut的ClassFilter,用于匹配Class是否符合切点逻辑。
-
ClassFilter getClassFilter();
-
-
// 返回当前Pointcut的MethodMatcher对象,用于匹配method规则。
-
MethodMatcher getMethodMatcher();
-
-
// 默认值,如果返回此结果表明所有method都会被匹配成功。
-
Pointcut TRUE = TruePointcut.INSTANCE;
-
}
-
// 匹配规则使用String表达式的Pointcut
-
public
interface ExpressionPointcut extends Pointcut {
-
-
// 返回切点规则表达式
-
@Nullable
-
String getExpression();
-
}
-
public
abstract
class AbstractExpressionPointcut implements ExpressionPointcut, Serializable {
-
-
// 切点位置
-
@Nullable
-
private String location;
-
-
// 切点匹配规则表达式
-
@Nullable
-
private String expression;
-
-
-
// setter and getter
-
public void setLocation(@Nullable String location) {
-
this.location = location;
-
}
-
@Nullable
-
public String getLocation() {
-
return
this.location;
-
}
-
-
public void setExpression(@Nullable String expression) {
-
this.expression = expression;
-
try {
-
onSetExpression(expression);
-
}
-
catch (IllegalArgumentException ex) {
-
// Fill in location information if possible.
-
if (
this.location !=
null) {
-
throw
new IllegalArgumentException(
"Invalid expression at location [" +
this.location +
"]: " + ex);
-
}
-
else {
-
throw ex;
-
}
-
}
-
}
-
protected void onSetExpression(@Nullable String expression) throws IllegalArgumentException {
-
}
-
@Override
-
@Nullable
-
public String getExpression() {
-
return
this.expression;
-
}
-
}
最终实现类是AspectJExpressionPointcut类:
-
// Pointcut实现类。
-
@SuppressWarnings("serial")
-
public
class AspectJExpressionPointcut extends AbstractExpressionPointcut
-
implements
ClassFilter,
IntroductionAwareMethodMatcher,
BeanFactoryAware {
-
-
private
static
final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES =
new HashSet<>();
-
-
......
-
-
}
Pt3.7 ClassFilter
比较简单,直接看源码:
-
// ClassFilter限定在类级别上,判断是否符合Pointcut规则。
-
@FunctionalInterface
-
public
interface ClassFilter {
-
-
// true表示能够匹配。那就会进行织入的操作
-
boolean matches(Class<?> clazz);
-
-
// 默认值。会匹配所有的类,TrueClassFilter不是public得class,所以只是Spring内部自己使用的。
-
ClassFilter TRUE = TrueClassFilter.INSTANCE;
-
}
Pt3.8 MethodMatcher
MethodMatcher用于定义Pointcut匹配method的逻辑:
-
// Pointcut匹配逻辑:判断方法是否符合Pointcut规则,执行Advice通知。
-
public
interface MethodMatcher {
-
-
// 这个称为静态匹配:在匹配条件不是太严格时使用,可以满足大部分场景的使用
-
boolean matches(Method method, Class<?> targetClass);
-
-
// 这个称为动态匹配(运行时匹配): 它是严格的匹配。在运行时动态的对参数的类型进行匹配
-
boolean matches(Method method, Class<?> targetClass, Object... args);
-
-
// 两个方法的分界线就是boolean isRuntime()方法,步骤如下
-
// 1、先调用静态匹配,若返回true。此时就会继续去检查isRuntime()的返回值
-
// 2、若isRuntime()还返回true,那就继续调用动态匹配
-
// (若静态匹配都匹配上,动态匹配那铁定更匹配不上得~~~~)
-
boolean isRuntime();
-
-
// 默认值
-
MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;
-
}
实现接口:
-
// 校验方法是否匹配Pointcut规则
-
public
interface IntroductionAwareMethodMatcher extends MethodMatcher {
-
boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions);
-
}
Pt3.9 Aware
我们在介绍下Aware接口。
打开Aware接口可以看到,他是一个空接口,没有任何实现。他标识的其实是一种能力,Spring容器中的Bean能够具备感知某一对象的能力。
-
// Aware是顶层超类,用于标识是否具备一种能力。
-
public
interface Aware {
-
-
}
比如,BeanFactoryAware是继承了Aware的接口,它就代表Bean对归属Spring IoC容器的感知能力。
-
// 实现了BeanFactoryAware接口的类,能够感知到他所属的BeanFactory。直白点,就是Bean能够获得他所属的BeanFactory对象。
-
// 这就是Aware接口的能力,他使得继承类能够具备某一种感知的能力。
-
public
interface BeanFactoryAware extends Aware {
-
-
// 设置当前Bean所属的BeanFactory实例
-
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
-
}
还有TargetClassAware接口:
-
// 该接口使得,对应的代理类拥有感知TargetClass的能力,就是能够操作目标代理类。
-
public
interface TargetClassAware {
-
// 获得目标代理类。
-
@Nullable
-
Class<?> getTargetClass();
-
}
Pt4 Spring AOP初始化剖析
Pt4.1 寻找入口
在AOP基础部分中,介绍过AOP的原理是生成原始Bean对象的代理类,从而在执行过程中通过动态代理完成逻辑横切。
所以AOP的初始化是在Bean初始化完成之后发生的。在DI部分,通过调用BeanFactory.getBean()触发Bean的初始化和依赖注入,当整个Bean初始化逻辑之心完成后,会继续执行AOP初始化处理,为Bean创建AOP代理类。
DI操作是通过调用#getBean()触发的,其核心逻辑是在AbstractAutowireCapableBeanFactory#doCreateBean()执行。我们跳过IoC、DI和MVC部分的详细逻辑介绍,直接从doCreateBean()来找AOP的入口。
先来看#doCreateBean()实例化逻辑:
-
// org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
-
protected <T>
T doGetBean(
-
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
-
throws BeansException {
-
-
// ......
-
-
// 跳过DI前后其他逻辑,这部分在DI部分已经详细介绍过。
-
// 不管Bean的Scope是那种,最终都是通过#createBean()·。
-
return createBean(beanName, mbd, args);
-
-
// ......
-
}
还没到AOP的地方,继续往下:
-
// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
-
// 真正完成指定Bean对象创建的方法
-
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
-
throws BeanCreationException {
-
-
// ......
-
-
// 跳过DI前后其他逻辑,这部分在DI部分已经详细介绍过。
-
// Bean的处理只要分为三个步骤:
-
// 1. 实例化,执行构造器;
-
// 2. 依赖注入;
-
// 3. 调用init-method;
-
// 到这里,DI已经完成Bean的实例化操作,这是第一步,我们继续往下看。
-
-
// 2、对Bean进行依赖注入
-
populateBean(beanName, mbd, instanceWrapper);
-
-
// 3、Bean实例对象依赖注入完成后,开始对Bean实例对象进行初始化,为Bean实例对象应用BeanPostProcessor后置回调处理
-
// AOP的逻辑在这里执行
-
exposedObject = initializeBean(beanName, exposedObject, mbd);
-
-
// ......
-
}
找到#initializeBean,这里才是真正开始的地方:
-
// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
-
// 初始化容器创建的Bean实例对象,为其添加BeanPostProcessor后置处理器
-
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
-
// JDK安全机制验证权限
-
if (System.getSecurityManager() !=
null) {
-
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
-
invokeAwareMethods(beanName, bean);
-
return
null;
-
}, getAccessControlContext());
-
}
-
else {
-
// 为Bean实例对象包装相关属性:类名称、类加载器、所属容器等。
-
invokeAwareMethods(beanName, bean);
-
}
-
-
Object wrappedBean = bean;
-
if (mbd ==
null || !mbd.isSynthetic()) {
-
// 1、调用BeanPostProcessor的回调方法,执行Bean初始化之前的操作。
-
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
-
}
-
-
try {
-
// 2、调用Bean的Init-Method方法,完成Bean的初始化操作。
-
// 这个Bean的初始化方法是在Spring Bean定义配置文件中通过init-method属性指定的。
-
// 这里不是新建Bean的实例操作,此时的Bean已经完成实例化处理,生成了Bean的实例对象,也完成了属性的设置。
-
// 如果Bean定义中配置了init-method,这里将执行该方法完成Bean配置中所有init动作。
-
invokeInitMethods(beanName, wrappedBean, mbd);
-
// 到此为止,Bean实例的初始化操作已经完成,创建了Bean对象,完成了属性的依赖注入,执行了自定义的init-method方法。
-
}
-
catch (Throwable ex) {
-
throw
new BeanCreationException(
-
(mbd !=
null ? mbd.getResourceDescription() :
null),
-
beanName,
"Invocation of init method failed", ex);
-
}
-
if (mbd ==
null || !mbd.isSynthetic()) {
-
// 3、调用BeanPostProcessor的回调方法,执行Bean初始化之后的操作。
-
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
-
}
-
-
return wrappedBean;
-
}
代码里分为三步:
-
调用BeanPostProcessor的回调方法,执行Bean初始化之前的操作。
-
调用Bean的Init-Method方法,完成Bean的初始化操作。
-
调用BeanPostProcessor的回调方法,执行Bean初始化之后的操作。
AOP是在Bean完成初始化之后触发的,前两部Bean还没有完成初始化,所以真正跟AOP相关的操作,是在第3步开始的:
-
// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
-
// 调用BeanPostProcessor的回调方法,执行Bean初始化之后的操作。
-
@Override
-
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
-
throws BeansException {
-
-
Object result = existingBean;
-
// 遍历容器为所创建的Bean添加的所有BeanPostProcessor后置处理器。
-
for (BeanPostProcessor processor : getBeanPostProcessors()) {
-
// 调用Bean实例所有定义的BeanPostProcessor初始化之后回调操作,完成初始化后的自定义操作。
-
Object current = processor.postProcessAfterInitialization(result, beanName);
-
if (current ==
null) {
-
return result;
-
}
-
result = current;
-
}
-
return result;
-
}
Pt4.2 选择代理策略
执行BeanPostProcessor的后置回调方法,AOP的BeanPostProcessor实现类很多,其中AbstractAutoProxyCreator是非常重要的一个。
-
// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
-
@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;
-
}
wrapIfNecessary()是非常核心的方法,负责处理AOP代理。
-
// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
-
/**
-
* 如果给定的Bean符合AOP条件,则生成代理类。
-
*
-
* @param bean 原始Bean实例对象
-
* @param beanName Bean的名称
-
* @param cacheKey 从Bean信息得到的唯一缓存Key
-
*/
-
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
-
if (StringUtils.hasLength(beanName) &&
this.targetSourcedBeans.contains(beanName)) {
-
return bean;
-
}
-
-
// 判断是否应该代理这个Bean
-
if (Boolean.FALSE.equals(
this.advisedBeans.get(cacheKey))) {
-
return bean;
-
}
-
// 判断是否是一些InfrastructureClass或者是否应该跳过这些类。
-
// InfrastructureClass 指Advice、PointCut、Advisor等接口的实现类。
-
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
-
// 记录Bean不需要AOP代理的类
-
this.advisedBeans.put(cacheKey, Boolean.FALSE);
-
return bean;
-
}
-
-
// 获取Bean相关的所有AOP通知
-
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName,
null);
-
if (specificInterceptors != DO_NOT_PROXY) {
-
// 记录Bean需要AOP代理的类
-
this.advisedBeans.put(cacheKey, Boolean.TRUE);
-
// 创建AOP代理类
-
Object proxy = createProxy(
-
bean.getClass(), beanName, specificInterceptors,
new SingletonTargetSource(bean));
-
this.proxyTypes.put(cacheKey, proxy.getClass());
-
return proxy;
-
}
-
-
this.advisedBeans.put(cacheKey, Boolean.FALSE);
-
return bean;
-
}
getAdvicesAndAdvisorsForBean()用于获取和当前Bean相关的Advice和Advisor信息:
-
// org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean
-
// 获取Bean定义的所有AOP通知
-
@Override
-
@Nullable
-
protected Object[] getAdvicesAndAdvisorsForBean(
-
Class<?> beanClass, String beanName,
@Nullable TargetSource targetSource) {
-
-
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
-
if (advisors.isEmpty()) {
-
return DO_NOT_PROXY;
-
}
-
return advisors.toArray();
-
}
createProxy()用于创建AOP代理类,这是核心逻辑。
Pt4.3 生成AOP代理类
Spring初始化阶段,通过动态字节码生成AOP代理类,其核心逻辑如下:
-
// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy
-
/**
-
* 为Bean生成AOP代理类。
-
*
-
* @param beanClass Bean的Class类型
-
* @param beanName Bean的名称
-
* @param specificInterceptors Bean定义的AOP通知
-
* @param targetSource 代理的目标源
-
* @return AOP代理类
-
*/
-
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
-
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
-
-
if (
this.beanFactory
instanceof ConfigurableListableBeanFactory) {
-
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)
this.beanFactory, beanName, beanClass);
-
}
-
-
// AOP代理类生成的工厂类
-
ProxyFactory proxyFactory =
new ProxyFactory();
-
proxyFactory.copyFrom(
this);
-
-
// ProxyTargetClass用于标记是代理目标类,还是目标类的接口,继而决定了代理模式,这点后面会说。
-
if (!proxyFactory.isProxyTargetClass()) {
-
if (shouldProxyTargetClass(beanClass, beanName)) {
-
proxyFactory.setProxyTargetClass(
true);
-
}
-
else {
-
evaluateProxyInterfaces(beanClass, proxyFactory);
-
}
-
}
-
-
// 初始化ProxyFactory
-
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
-
proxyFactory.addAdvisors(advisors);
-
proxyFactory.setTargetSource(targetSource);
-
customizeProxyFactory(proxyFactory);
-
-
proxyFactory.setFrozen(
this.freezeProxy);
-
if (advisorsPreFiltered()) {
-
proxyFactory.setPreFiltered(
true);
-
}
-
-
// 基于代理类的类加载器生成代理类对象
-
return proxyFactory.getProxy(getProxyClassLoader());
-
}
-
// org.springframework.aop.framework.ProxyFactory#getProxy(java.lang.ClassLoader)
-
// 基于指定的ClassLoader和Factory设置,创建AOP代理类。
-
public Object getProxy(@Nullable ClassLoader classLoader) {
-
// createAopProxy():获取AOP代理类,有JdkDynamicAopProxy和CglibAopProxy两种。
-
// getProxy:使用AOP代理类,生成目标Bean的代理类。
-
// 这里假定使用JdkDynamicAopProxy的方式执行getProxy方法
-
return createAopProxy().getProxy(classLoader);
-
}
createAopProxy()获取AOP代理对象,该对象用于生成目标类的代理类:
-
// org.springframework.aop.framework.ProxyCreatorSupport#createAopProxy
-
// 获取AopProxy,用于生成Bean的代理类
-
protected final synchronized AopProxy createAopProxy() {
-
// 第一个AopProxy被创建时,执行以下激活操作。
-
if (!
this.active) {
-
activate();
-
}
-
-
// 获取AopProxy,用于生成Bean的代理类
-
return getAopProxyFactory().createAopProxy(
this);
-
}
Spring AOP有两种模式实现动态代理,JdkDynamicProxy和CGLibProxy。判断逻辑很简单,如果目标代理类有接口则使用JDK动态代理,否则直接通过CGLib代理目标类。核心创建逻辑是在DefaultAopProxyFactory中实现,这里的核心是判断使用那种模式来实现代理:
-
// org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy
-
// 创建指定Bean的AOP代理类
-
@Override
-
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
-
// 判断选择创建代理对象的方式。
-
// config.isOptimize() 是否对代理类的生成使用策略优化,其作用是和isProxyTargetClass是一样的,默认为false。
-
// config.isProxyTargetClass() 是否使用Cglib的方式创建代理对象,默认为false。
-
// hasNoUserSuppliedProxyInterfaces 目标类是否有接口存在,且只有一个接口的时候接口类型不是SpringProxy类型。
-
if (!IN_NATIVE_IMAGE &&
-
(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
-
// 从AdvisedSupport中获取目标类对象
-
Class<?> targetClass = config.getTargetClass();
-
if (targetClass ==
null) {
-
throw
new AopConfigException(
"TargetSource cannot determine target class: " +
-
"Either an interface or a target is required for proxy creation.");
-
}
-
-
// 如果目标类对象是接口类型,则使用JdkDynamicAopProxy
-
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
-
// 获取代理类要实现的接口,除了Advised对象中配置的接口信息外,还会加上SpringProxy、Advised(opaque=false)
-
// 检查得到的接口中有没有定义equals或者hashcode的接口
-
return
new JdkDynamicAopProxy(config);
-
}
-
-
// 否则使用CglibAopProxy
-
return
new ObjenesisCglibAopProxy(config);
-
}
-
else {
-
// 上面的三个方法没有一个为true 那使用JDK的提供的代理方式生成代理对象
-
return
new JdkDynamicAopProxy(config);
-
}
-
}
获得了AopProxy之后,就是使用他来生成目标类的动态代理类,回到刚才createAopProxy().getProxy(classLoader),我们看getProxy()是怎么完成代理类创建的。
因为JDK动态代理比较常见,这里我们研究JDK动态代理的分支逻辑。
-
// org.springframework.aop.framework.JdkDynamicAopProxy#JdkDynamicAopProxy
-
// 获取代理类要实现的接口,除了Advised对象中配置的接口信息外,还会加上SpringProxy、Advised(opaque=false)
-
// 检查得到的接口中有没有定义equals或者hashcode的接口
-
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
-
// 生成Bean的代理类的前提是有AOP通知信息的配置
-
Assert.notNull(config,
"AdvisedSupport must not be null");
-
if (config.getAdvisors().length ==
0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
-
throw
new AopConfigException(
"No advisors and no TargetSource specified");
-
}
-
-
// AOP配置信息
-
this.advised = config;
-
-
// 获取生成的代理类要实现接口
-
this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(
this.advised,
true);
-
-
// 检查得到的接口中有没有定义equals或者hashcode的接口
-
findDefinedEqualsAndHashCodeMethods(
this.proxiedInterfaces);
-
}
创建和配置好Proxy策略后,就是执行代理类的生成操作:
-
// org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)
-
// 生成代理对象
-
@Override
-
public Object getProxy(@Nullable ClassLoader classLoader) {
-
if (logger.isTraceEnabled()) {
-
logger.trace(
"Creating JDK dynamic proxy: " +
this.advised.getTargetSource());
-
}
-
// 基于Java动态代理生成目标对象的代理类(反射)。
-
// JdkDynamicAopProxy本身实现了InvocationHandler接口,实现了invoke()。
-
// JdkDynamicAopProxy的本质:基于被代理类的接口,生成相同接口的实现类,但包含了InvocationHandler对象。当方法执行时,实际上
-
// 是执行代理类的同名方法,该方法的逻辑就是执行InvocationHandler对象的invoke()来完成被代理类同名方法的执行逻辑。
-
return Proxy.newProxyInstance(classLoader,
this.proxiedInterfaces,
this);
-
}
这里实际上就是,基于JDK动态代理来实现,就不具体介绍了。
可以说,到这里AOP初始化动作已经完成了。但是,AOP的核心逻辑实际上是在方法触发的时候,通过动态代理来完成调用,所以我们继续研究一下运行时,AOP动态代理是如何工作的。
Pt4.4 执行代理方法
既然是通过动态代理,那么一定是通过InvocationHandler完成目标方法的执行,所以找到InvocationHandler逻辑就比较清晰了。
JdkDynamicAopProxy恰好继承了InvocationHandler,所以动态代理执行的核心逻辑是在JdkDynamicAopProxy#invoke()中,继续分析源码:
-
// org.springframework.aop.framework.JdkDynamicAopProxy#invoke
-
// InvocationHandler接口定义的方法的具体实现,负责执行代理类的方法。
-
// 它是JDK动态代理的核心,invoke()负责执行被代理类方法,同时完成advice织入。
-
@Override
-
@Nullable
-
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-
// 旧的代理对象
-
Object oldProxy =
null;
-
// 用来标记是否需要将代理对象暴露在ThreadLocal中
-
boolean setProxyContext =
false;
-
-
// 获取被代理的目标类
-
TargetSource targetSource =
this.advised.targetSource;
-
// 目标对象
-
Object target =
null;
-
-
try {
-
// 代理类未实现equal(),且要执行的代理方法是equals()
-
if (!
this.equalsDefined && AopUtils.isEqualsMethod(method)) {
-
// 因为目标类没有自己实现equals(),所以执行当前类的equals方法。
-
return equals(args[
0]);
-
}
-
// 代理类未实现hashCode(),且要执行的代理方法是hashCode()
-
else
if (!
this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
-
// 因为目标类没有自己实现hashCode(),所以执行当前类的hashCode方法。
-
return hashCode();
-
}
-
// DecoratingProxy接口中定义了一个方法,用来获取原始的被代理的目标类,主要是用在嵌套代理的情况下
-
// 所谓嵌套代理:代理对象又被作为目标对象进行了代理
-
else
if (method.getDeclaringClass() == DecoratingProxy.class) {
-
// 调用AopProxyUtils工具类的方法,内部通过循环遍历的方式,找到最原始的被代理的目标类
-
return AopProxyUtils.ultimateTargetClass(
this.advised);
-
}
-
// 方法来源于 Advised 接口,代理对象默认情况下会实现 Advised 接口,可以通过代理对象来动态向代理对象中添加通知等
-
else
if (!
this.advised.opaque && method.getDeclaringClass().isInterface() &&
-
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
-
//
this.advised是AdvisedSupport类型的,AdvisedSupport实现了Advised接口中的所有方法
-
// 所以最终通过通过反射方式交给
this.advised来响应当前调用
-
return AopUtils.invokeJoinpointUsingReflection(
this.advised, method, args);
-
}
-
-
Object retVal;
-
-
//是否需要在threadLocal中暴露代理对象
-
if (
this.advised.exposeProxy) {
-
// 将代理对象暴露在上线文中,即暴露在threadLocal中,那么在当前线程中可以通过静态方法
-
// AopContext#currentProxy获取当前被暴露的代理对象。
-
oldProxy = AopContext.setCurrentProxy(proxy);
-
// 将setProxyContext标记为true
-
setProxyContext =
true;
-
}
-
-
// 获取目标Bean的Class类型
-
target = targetSource.getTarget();
-
Class<?> targetClass = (target !=
null ? target.getClass() :
null);
-
-
// 获取当前方法的拦截器链,即Advice通知
-
List<Object> chain =
this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
-
-
// 拦截器链为空的情况下,表示这个方法上面没有找到任何增强的通知,那么会直接通过反射直接调用目标对象
-
if (chain.isEmpty()) {
-
// 获取方法请求的参数(有时候方法中有可变参数,所谓可变参数就是带有省略号(...)这种格式的参数,
-
// 传入的参数类型和这种类型不一样的时候,会通过下面的adaptArgumentsIfNecessary方法进行转换)
-
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
-
// 通过反射直接调用目标方法
-
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
-
}
-
else {
-
// 创建一个方法调用器(包含了代理对象、目标对象、调用的方法、参数、目标类型、方法拦截器链)
-
MethodInvocation invocation =
-
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
-
// 通过拦截器链一个个调用最终到目标方法的调用
-
retVal = invocation.proceed();
-
}
-
-
// 下面会根据方法返回值的类型,做一些处理,比如方法返回的类型为自己,则最后需要将返回值置为代理对象
-
Class<?> returnType = method.getReturnType();
-
if (retVal !=
null && retVal == target &&
-
returnType != Object.class && returnType.isInstance(proxy) &&
-
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
-
// Special
case: it returned "
this" and the
return type of the method
-
// is type-compatible. Note that we can't help if the target sets
-
// a reference to itself in another returned object.
-
retVal = proxy;
-
}
-
// 方法的返回值类型returnType为原始类型(即int、byte、double等这种类型的) && retVal为null,
-
// 此时如果将null转换为原始类型会报错,所以此处直接抛出异常
-
else
if (retVal ==
null && returnType != Void.TYPE && returnType.isPrimitive()) {
-
throw
new AopInvocationException(
-
"Null return value from advice does not match primitive return type for: " + method);
-
}
-
return retVal;
-
}
-
finally {
-
// 目标对象不为null && 目标源不是静态的:所谓静态的,你可以理解为是否是单例的
-
// isStatic为true,表示目标对象是单例的,同一个代理对象中所有方法共享一个目标对象
-
// isStatic为false的时候,通常每次调用代理的方法,target对象是不一样的,所以方法调用万之后需要进行释放,可能有些资源清理,连接的关闭等操作
-
if (target !=
null && !targetSource.isStatic()) {
-
// Must have come from TargetSource.
-
targetSource.releaseTarget(target);
-
}
-
if (setProxyContext) {
-
// Restore old proxy.
-
AopContext.setCurrentProxy(oldProxy);
-
}
-
}
-
}
执行的思路非常简单:先获取应用到此方法上的拦截器链。如果有拦截器,则应用拦截器,并执行连接点(目标方法);如果没有拦截器,则直接通过反射执行连接点。
this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
获取拦截器链的逻辑如下:
-
// org.springframework.aop.framework.AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice
-
// 目标目标类的方法,定义的所有拦截器,即Advice通知
-
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
-
// 是否可以从缓存中获取,如果已经被执行过,则可以直接从缓存中获取。
-
MethodCacheKey cacheKey =
new MethodCacheKey(method);
-
List<Object> cached =
this.methodCache.get(cacheKey);
-
if (cached ==
null) {
-
cached =
this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
-
this, method, targetClass);
-
this.methodCache.put(cacheKey, cached);
-
}
-
return cached;
-
}
遍历和Bean相关的所有Advisor,获取跟当前Method相关的内容:
-
// org.springframework.aop.framework.DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice
-
/**
-
* 获取方法匹配的拦截器链列表
-
*
-
* @param config:代理配置信息,里面包含了创建代理的所有信息,如:Advisor列表,此方法会从Advisor列表中找到和method匹配的
-
* @param targetClass:目标类
-
*/
-
@Override
-
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
-
Advised config, Method method, @Nullable Class<?> targetClass) {
-
-
// 获取Advisor适配器注册器,所有的Advisor最终都会转换为MethodInterceptor类型的,然后注册方法调用链去执行,
-
// AdvisorAdapterRegistry就是搞这个事情的,其内部会将非MethodInterceptor类型通知通过适配器转换为MethodInterceptor类型
-
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
-
-
// 获取配置中的Advisor列表
-
Advisor[] advisors = config.getAdvisors();
-
List<Object> interceptorList =
new ArrayList<>(advisors.length);
-
-
// 获取被调用方法所在类实际的类型
-
Class<?> actualClass = (targetClass !=
null ? targetClass : method.getDeclaringClass());
-
Boolean hasIntroductions =
null;
-
-
// 遍历Advisor列表,找到和actualClass和方法匹配的所有方法拦截器(MethodInterceptor)链列表
-
for (Advisor advisor : advisors) {
-
// 判断是否是PointcutAdvisor类型的,这种类型的匹配分为2个阶段,先看类是否匹配,然后再看方法是否匹配
-
if (advisor
instanceof PointcutAdvisor) {
-
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
-
// 在ProxyConfig中介绍过,如果isPreFiltered为ture,表示类已经匹配成功,不需要看类是否匹配。
-
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
-
// MethodMatcher用来匹配method是否符合Pointcut逻辑
-
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
-
boolean match;
-
if (mm
instanceof IntroductionAwareMethodMatcher) {
-
if (hasIntroductions ==
null) {
-
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
-
}
-
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
-
}
-
else {
-
// 判断方法是否匹配Pointcut规则
-
match = mm.matches(method, actualClass);
-
}
-
-
// 方法匹配的话,说明当前Advisor要加入到方法执行的拦截器链中。
-
if (match) {
-
// 通过AdvisorAdapterRegistry的getInterceptors将advisor转换为MethodInterceptor列表
-
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
-
// 方法是否动态匹配,动态匹配的逻辑在MethodMatcher中介绍过。
-
// 1、先调用静态匹配,若返回true。此时就会继续去检查isRuntime()的返回值
-
// 2、若isRuntime()还返回true,那就继续调用动态匹配
-
if (mm.isRuntime()) {
-
// 轮询连接器,将其包装为InterceptorAndDynamicMethodMatcher对象,后续方法调用的时候可以做动态匹配
-
for (MethodInterceptor interceptor : interceptors) {
-
interceptorList.add(
new InterceptorAndDynamicMethodMatcher(interceptor, mm));
-
}
-
}
-
else {
-
interceptorList.addAll(Arrays.asList(interceptors));
-
}
-
}
-
}
-
}
-
else
if (advisor
instanceof IntroductionAdvisor) {
-
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
-
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
-
Interceptor[] interceptors = registry.getInterceptors(advisor);
-
interceptorList.addAll(Arrays.asList(interceptors));
-
}
-
}
-
else {
-
Interceptor[] interceptors = registry.getInterceptors(advisor);
-
interceptorList.addAll(Arrays.asList(interceptors));
-
}
-
}
-
-
return interceptorList;
-
}
这里通过GlobalAdvisorAdapterRegistry将Advisor转换为MethodInterceptor,从而组装成拦截器链进行执行,这里后面我们会详细介绍。
retVal = invocation.proceed();
获取拦截器链之后,就是执行拦截器链:
-
public
class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
-
// 生成的代理对象
-
protected
final Object proxy;
-
-
// 被代理的目标对象
-
@Nullable
-
protected
final Object target;
-
-
// 被调用的方法
-
protected
final Method method;
-
-
// 调用方法传入参数
-
protected Object[] arguments;
-
-
// 目标对象类型
-
@Nullable
-
private
final Class<?> targetClass;
-
-
/**
-
* Lazily initialized map of user-specific attributes for this invocation.
-
*/
-
@Nullable
-
private Map<String, Object> userAttributes;
-
-
/**
-
* 当期被调用的方法上匹配的 MethodInterceptor and InterceptorAndDynamicMethodMatcher 列表
-
* 即方法调用链列表
-
*/
-
protected
final List<?> interceptorsAndDynamicMethodMatchers;
-
-
/**
-
* Index from 0 of the current interceptor we're invoking.
-
* -1 until we invoke: then the current interceptor.
-
*/
-
private
int currentInterceptorIndex = -
1;
-
-
// 这里是重点,用来处理被调用的方法,会递归进行调用,所有的拦截器都执行完毕之后,会通过反射调用目标方法
-
@Override
-
@Nullable
-
public Object proceed() throws Throwable {
-
// 拦截器都执行完毕之后,通过反射调用目标对象中的方法
-
if (
this.currentInterceptorIndex ==
this.interceptorsAndDynamicMethodMatchers.size() -
1) {
-
return invokeJoinpoint();
-
}
-
-
//获取++this.currentInterceptorIndex指定的拦截器
-
Object interceptorOrInterceptionAdvice =
-
this.interceptorsAndDynamicMethodMatchers.get(++
this.currentInterceptorIndex);
-
-
// 判断拦截器是否是InterceptorAndDynamicMethodMatcher,这种表示是动态拦截器,
-
// 所谓动态拦截器就是要根据方法的参数的值来判断拦截器是否需要执行
-
if (interceptorOrInterceptionAdvice
instanceof InterceptorAndDynamicMethodMatcher) {
-
// Evaluate dynamic method matcher here: static part will already have
-
// been evaluated and found to match.
-
InterceptorAndDynamicMethodMatcher dm =
-
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
-
Class<?> targetClass = (
this.targetClass !=
null ?
this.targetClass :
this.method.getDeclaringClass());
-
-
// 判断动态拦截器是否需要执行
-
if (dm.methodMatcher.matches(
this.method, targetClass,
this.arguments)) {
-
//执行当前拦截器的调用
-
return dm.interceptor.invoke(
this);
-
}
-
else {
-
//如果不匹配,直接递归进入下一个拦截器的调用
-
return proceed();
-
}
-
}
-
else {
-
//执行拦截器的调用
-
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(
this);
-
}
-
}
-
-
// 使用反射执行被代理类方法
-
@Nullable
-
protected Object invokeJoinpoint() throws Throwable {
-
return AopUtils.invokeJoinpointUsingReflection(
this.target,
this.method,
this.arguments);
-
}
-
-
// ......
-
}
-
// org.springframework.aop.support.AopUtils#invokeJoinpointUsingReflection
-
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
-
throws Throwable {
-
-
// Use reflection to invoke the method.
-
try {
-
ReflectionUtils.makeAccessible(method);
-
return method.invoke(target, args);
-
}
-
catch (InvocationTargetException ex) {
-
// Invoked method threw a checked exception.
-
// We must rethrow it. The client won't see the interceptor.
-
throw ex.getTargetException();
-
}
-
catch (IllegalArgumentException ex) {
-
throw
new AopInvocationException(
"AOP configuration seems to be invalid: tried calling method [" +
-
method +
"] on target [" + target +
"]", ex);
-
}
-
catch (IllegalAccessException ex) {
-
throw
new AopInvocationException(
"Could not access method [" + method +
"]", ex);
-
}
-
}
到这里,AOP的执行过程就已经结束了。
在初始化过程中,将目标类、代理类、通知列表建立关系,从而在触发执行时,生成方法调用关系,最终通过代理和反射,完成Advice和目标方法的执行。
Pt4.5 触发AOP通知
在上面获取拦截器的过程中,使用了AdvisorAdapterRegistry作为适配器注册器,他负责将Advisor转换为拦截器,我们看具体实现。
GlobalAdvisorAdapterRegistry是单例模式,用于获取生成拦截器链的工厂类DefaultAdvisorAdapterRegistry:
-
// GlobalAdvisorAdapterRegistry类负责拦截器的适配和注册过程。
-
// 他是单例模式的实现,保存的是DefaultAdvisorAdapterRegistry的实例。
-
public
final
class GlobalAdvisorAdapterRegistry {
-
// 构造器私有化,单例模式
-
private GlobalAdvisorAdapterRegistry() {
-
}
-
// 恶汉模式的单例
-
private
static AdvisorAdapterRegistry instance =
new DefaultAdvisorAdapterRegistry();
-
-
public static AdvisorAdapterRegistry getInstance() {
-
return instance;
-
}
-
-
static void reset() {
-
instance =
new DefaultAdvisorAdapterRegistry();
-
}
-
}
DefaultAdvisorAdapterRegistry是核心类:
-
// DefaultAdvisorAdapterRegistry主要是将负责将前置通知,异常通知,后置通知转换为MethodInterceptor类型的
-
@SuppressWarnings("serial")
-
public
class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
-
-
// AdvisorAdapter是转换器列表,AdvisorAdapter负责将Advisor中的Advice转换为MethodInterceptor类型的。
-
private
final List<AdvisorAdapter> adapters =
new ArrayList<>(
3);
-
-
// 默认会注册3个AdvisorAdapter,这3个负责将前置通知,异常通知,后置通知转换为MethodInterceptor类型的
-
public DefaultAdvisorAdapterRegistry() {
-
registerAdvisorAdapter(
new MethodBeforeAdviceAdapter());
-
registerAdvisorAdapter(
new AfterReturningAdviceAdapter());
-
registerAdvisorAdapter(
new ThrowsAdviceAdapter());
-
}
-
-
-
@Override
-
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
-
if (adviceObject
instanceof Advisor) {
-
return (Advisor) adviceObject;
-
}
-
if (!(adviceObject
instanceof Advice)) {
-
throw
new UnknownAdviceTypeException(adviceObject);
-
}
-
Advice advice = (Advice) adviceObject;
-
if (advice
instanceof MethodInterceptor) {
-
// So well-known it doesn't even need an adapter.
-
return
new DefaultPointcutAdvisor(advice);
-
}
-
for (AdvisorAdapter adapter :
this.adapters) {
-
// Check that it is supported.
-
if (adapter.supportsAdvice(advice)) {
-
return
new DefaultPointcutAdvisor(advice);
-
}
-
}
-
throw
new UnknownAdviceTypeException(advice);
-
}
-
-
@Override
-
public MethodInterceptor[] getInterceptors(Advisor advisor)
throws UnknownAdviceTypeException {
-
List<MethodInterceptor> interceptors =
new ArrayList<>(
3);
-
Advice advice = advisor.getAdvice();
-
if (advice
instanceof MethodInterceptor) {
-
interceptors.add((MethodInterceptor) advice);
-
}
-
for (AdvisorAdapter adapter :
this.adapters) {
-
if (adapter.supportsAdvice(advice)) {
-
interceptors.add(adapter.getInterceptor(advisor));
-
}
-
}
-
if (interceptors.isEmpty()) {
-
throw
new UnknownAdviceTypeException(advisor.getAdvice());
-
}
-
return interceptors.toArray(
new MethodInterceptor[
0]);
-
}
-
-
// 注册AdvisorAdapter
-
@Override
-
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
-
this.adapters.add(adapter);
-
}
-
}
DefaultAdvisorAdapterRegistry构造器默认会添加before/after和exception3个拦截器。
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
-
// 适配MethodBeforeAdvice前置通知,负责将MethodBeforeAdvice类型的通知转换为MethodBeforeAdviceInterceptor类型
-
@SuppressWarnings("serial")
-
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
-
-
@Override
-
public boolean supportsAdvice(Advice advice) {
-
return (advice
instanceof MethodBeforeAdvice);
-
}
-
-
@Override
-
public MethodInterceptor getInterceptor(Advisor advisor) {
-
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
-
return
new MethodBeforeAdviceInterceptor(advice);
-
}
-
}
-
public
class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
-
-
private
final MethodBeforeAdvice advice;
-
-
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
-
Assert.notNull(advice,
"Advice must not be null");
-
this.advice = advice;
-
}
-
-
// 执行MethodBeforeAdvice
-
@Override
-
@Nullable
-
public Object invoke(MethodInvocation mi) throws Throwable {
-
// 触发before方法
-
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
-
// 触发目标方法
-
return mi.proceed();
-
}
-
}
需要说明的是,mi.proceed();并不会直接触发目标方法的执行,而是回到代理方法执行的proceed()递归调用链中,直到所有拦截器被执行,才会执行目标方法,最后完成方法栈中所有方法的执行。
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
-
class AfterReturningAdviceAdapter implements AdvisorAdapter, Serializable {
-
-
@Override
-
public boolean supportsAdvice(Advice advice) {
-
return (advice
instanceof AfterReturningAdvice);
-
}
-
-
@Override
-
public MethodInterceptor getInterceptor(Advisor advisor) {
-
AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice();
-
return
new AfterReturningAdviceInterceptor(advice);
-
}
-
-
}
-
@SuppressWarnings("serial")
-
public
class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
-
-
private
final AfterReturningAdvice advice;
-
-
public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
-
Assert.notNull(advice,
"Advice must not be null");
-
this.advice = advice;
-
}
-
-
@Override
-
@Nullable
-
public Object invoke(MethodInvocation mi) throws Throwable {
-
// 先触发目标方法
-
Object retVal = mi.proceed();
-
// 在执行after advice方法
-
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
-
return retVal;
-
}
-
}
registerAdvisorAdapter(new ThrowsAdviceAdapter());
-
class ThrowsAdviceAdapter implements AdvisorAdapter, Serializable {
-
-
@Override
-
public boolean supportsAdvice(Advice advice) {
-
return (advice
instanceof ThrowsAdvice);
-
}
-
-
@Override
-
public MethodInterceptor getInterceptor(Advisor advisor) {
-
return
new ThrowsAdviceInterceptor(advisor.getAdvice());
-
}
-
}
-
public
class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice {
-
-
private
static
final String AFTER_THROWING =
"afterThrowing";
-
-
private
static
final Log logger = LogFactory.getLog(ThrowsAdviceInterceptor.class);
-
-
-
private
final Object throwsAdvice;
-
-
/** Methods on
throws advice, keyed by exception class. */
-
private
final Map<Class<?>, Method> exceptionHandlerMap =
new HashMap<>();
-
-
-
/**
-
* Create a new ThrowsAdviceInterceptor for the given ThrowsAdvice.
-
* @param throwsAdvice the advice object that defines the exception handler methods
-
* (usually a {@link org.springframework.aop.ThrowsAdvice} implementation)
-
*/
-
public ThrowsAdviceInterceptor(Object throwsAdvice) {
-
Assert.notNull(throwsAdvice,
"Advice must not be null");
-
this.throwsAdvice = throwsAdvice;
-
-
Method[] methods = throwsAdvice.getClass().getMethods();
-
for (Method method : methods) {
-
if (method.getName().equals(AFTER_THROWING) &&
-
(method.getParameterCount() ==
1 || method.getParameterCount() ==
4)) {
-
Class<?> throwableParam = method.getParameterTypes()[method.getParameterCount() -
1];
-
if (Throwable.class.isAssignableFrom(throwableParam)) {
-
// An exception handler to register...
-
this.exceptionHandlerMap.put(throwableParam, method);
-
if (logger.isDebugEnabled()) {
-
logger.debug("Found exception handler method on
throws advice: " + method);
-
}
-
}
-
}
-
}
-
-
if (
this.exceptionHandlerMap.isEmpty()) {
-
throw
new IllegalArgumentException(
-
"At least one handler method must be found in class [" + throwsAdvice.getClass() +
"]");
-
}
-
}
-
-
/**
-
* Return the number of handler methods in this advice.
-
*/
-
public int getHandlerMethodCount() {
-
return
this.exceptionHandlerMap.size();
-
}
-
-
@Override
-
@Nullable
-
public Object invoke(MethodInvocation mi) throws Throwable {
-
try {
-
// 先触发目标方法执行
-
return mi.proceed();
-
}
-
catch (Throwable ex) {
-
Method handlerMethod = getExceptionHandler(ex);
-
if (handlerMethod !=
null) {
-
// 发生异常时,执行exception advice
-
invokeHandlerMethod(mi, ex, handlerMethod);
-
}
-
throw ex;
-
}
-
}
-
-
/**
-
* Determine the exception handle method for the given exception.
-
* @param exception the exception thrown
-
* @return a handler for the given exception type, or {@code null} if none found
-
*/
-
@Nullable
-
private Method getExceptionHandler(Throwable exception) {
-
Class<?> exceptionClass = exception.getClass();
-
if (logger.isTraceEnabled()) {
-
logger.trace(
"Trying to find handler for exception of type [" + exceptionClass.getName() +
"]");
-
}
-
Method handler =
this.exceptionHandlerMap.get(exceptionClass);
-
while (handler ==
null && exceptionClass != Throwable.class) {
-
exceptionClass = exceptionClass.getSuperclass();
-
handler =
this.exceptionHandlerMap.get(exceptionClass);
-
}
-
if (handler !=
null && logger.isTraceEnabled()) {
-
logger.trace("Found handler
for exception of type [" + exceptionClass.getName() + "]: " + handler);
-
}
-
return handler;
-
}
-
-
private void invokeHandlerMethod(MethodInvocation mi, Throwable ex, Method method) throws Throwable {
-
Object[] handlerArgs;
-
if (method.getParameterCount() ==
1) {
-
handlerArgs =
new Object[] {ex};
-
}
-
else {
-
handlerArgs =
new Object[] {mi.getMethod(), mi.getArguments(), mi.getThis(), ex};
-
}
-
try {
-
method.invoke(
this.throwsAdvice, handlerArgs);
-
}
-
catch (InvocationTargetException targetEx) {
-
throw targetEx.getTargetException();
-
}
-
}
-
-
}
以上就是获取AOP拦截器链的过程。
Pt4.6 流程图
参考资料
参考学习资料和相关文章列表,请参照如下链接:
https://blog.csdn.net/moonlight821/article/details/116463513
转载:https://blog.csdn.net/cmm13655612162/article/details/116571530