Spring AOP 从入门到源码解析

先学会如何使用

Spring-boot 或 Spring-cloud 中使用AOP

在Spring-boot 工程中使用AOP功能,先引入相关的依赖。

pom.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <version>1.18.22</version>
</dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
  <exclusions>
    <exclusion>
      <groupId>org.junit.vintage</groupId>
      <artifactId>junit-vintage-engine</artifactId>
    </exclusion>
  </exclusions>
</dependency>

测试业务接口 UserService.java

1
2
3
public interface UserService {
    void test();
}

测试业务接口实现类 UserServiceImp.java

1
2
3
4
5
6
7
8
@Slf4j
@Service
public class UserServiceImpl implements UserService {
    @Override
    public void test() {
        log.info("执行业务方法test...");
    }
}

切面类 LogAspect.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
@Slf4j
@Aspect
@Component
public class LogAspect {

    @Pointcut("execution(public * com.example.service.impl.*.*(..))")
    public void pointcut() {
    }

    @Before("pointcut()")
    public void before() {
        log.info("Before通知 -> 业务方法执行前调用...");
    }

    @After("pointcut()")
    public void after() {
        log.info("After通知 -> 业务方法执行后调用...");
    }

}

启动类 Application.java

1
2
3
4
5
6
7
8
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

执行测试类 UserServiceTest.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16

@SpringBootTest
public class SpringTests {

}

class UserServiceTest extends SpringTests {

    @Autowired
    private UserService userService;
    @Test
    void test() {
        userService.test();
    }

}
1
2
3
INFO 53837 --- [           main] com.example.aspect.LogAspect             : Before通知 -> 业务方法执行前调用...
INFO 53837 --- [           main] c.example.service.impl.UserServiceImpl   : 执行业务方法test...
INFO 53837 --- [           main] com.example.aspect.LogAspect             : After通知 -> 业务方法执行后调用...

可以看到,在springboot项目中只要引入 spring-boot-starter-aop 包,默认会自动开启AOP功能。

这是因为SpringBoot自动配置的特性,如下是AOP的配置类,默认是开启。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {
  //
  @Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(Advice.class)
	static class AspectJAutoProxyingConfiguration {

		@Configuration(proxyBeanMethods = false)
		@EnableAspectJAutoProxy(proxyTargetClass = false)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",
				matchIfMissing = false)
		static class JdkDynamicAutoProxyConfiguration {

		}

		@Configuration(proxyBeanMethods = false)
		@EnableAspectJAutoProxy(proxyTargetClass = true)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
				matchIfMissing = true)
		static class CglibAutoProxyConfiguration {

		}

	}
}
  • 根据ConditionalOnProperty条件注解,当前环境中存在 spring.aop.auto,且值为true会启用该配置类, 而matchIfMissing的值为 true, 表明当没有手动配置 spring.aop.auto 时其默认值为true, 即默认开启AOP自动配置。

  • havingValue 表示手动配置的值和havingValue的值相等时才生效。

  • 通过 AspectJAutoProxyingConfiguration 内部类注入 JdkDynamicAutoProxyConfiguration 和 CglibAutoProxyConfiguration 配置类型,到底哪一个会生效呢 ?

  • CglibAutoProxyConfiguration会生效,因为没有配置spring.aop.proxy-target-class时CglibAutoProxyConfiguration上的默认值为true, 所以CglibAutoProxyConfiguration配置生效。

  • matchIfMissing 表示没有手动配置时 spring.aop.proxy-target-class 配置的默认值。

  • 通过 @EnableAspectJAutoProxy(proxyTargetClass = true) 开启AOP功能,这是实现AOP的关键。

原理分析

Spring-AOP 的原理可以划分为三个步骤,总共做了三件事,分别是解析切面、创建动态代理、调用代理方法。

image-20211208172327744

解析切面:

在Spring容器启动的过程中会扫描所有的切面类,即标注@Aspect的bean,解析该类中的所有通知方法,生成Advisor,每个含有 @Before、@After… 的类都是一个通知,都会生成一个Advisor,最后将所有解析好的Advisor保存在缓存中。

创建代理对象:

根据切点表达式匹配所有bean和方法,如果匹配成功,实现了接口的bean使用JDK动态代理,没有实现接口使用Cglib动态代理。

调用代理方法:

当调用被代理的类的方法是,AOP会在执行目标方法前后执行被植入的切面逻辑。

解析切面

从入口 @EnableAspectJAutoProxy 开始。

导入了另一个类 AspectJAutoProxyRegistrar,@Import注解可以将一个普通类注入到spring容器,注册成bean。

1
2
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

   @Override
   public void registerBeanDefinitions(
         AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

      // 注入AOP核心类型
      AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

     // 获取 EnableAspectJAutoProxy 注解中的 proxyTargetClass 和  exposeProxy 执行。
     // proxyTargetClass = true 表示都使用cglib代理。
     // exposeProxy = true 暴露代理对象到AOP的上下文,可以通过AopContext获取。
      AnnotationAttributes enableAspectJAutoProxy =
            AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
      if (enableAspectJAutoProxy != null) {
         if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
         }
         if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
         }
      }
   }
}

这里导入的是 ImportBeanDefinitionRegistrar 类型的bean, 通过实现 registerBeanDefinitions 方法可以注入其他任何类型的bean。

关于ImportBeanDefinitionRegistrar 的用法参考另一篇文章:https://juejin.cn/post/7039308644768284679

关键是注册了另一个bean,AnnotationAwareAspectJAutoProxyCreator 。

image-20211208170900734

AnnotationAwareAspectJAutoProxyCreator 实现了 BeenPostProcessor接口 , 是bean的后置处理器。

BeenPostProcessor 中有两个重要方法如下,他们分别在bean初始化前后执行。

1
2
3
4
5
6
7
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  return bean;
}

default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  return bean;
}
  • postProcessBeforeInitialization 在bean 初始化前执行。
  • postProcessAfterInitialization 在 bean 初始化后执行。

另外还实现了 InstantiationAwareBeanPostProcessor接口,该类也有两个方法,分别在bean实例化前后执行。

1
2
3
4
5
6
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
  return null;
}
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
  return true;
}
  • postProcessBeforeInstantiation 在bean实例化前执行。
  • postProcessAfterInstantiation 在bean实例化后执行。

以上四个方法是AOP解析切面、创建代理的关键,在抽象类AbstractAutoProxyCreator中分别实现了这四个方法。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
   Object cacheKey = getCacheKey(beanClass, beanName);

   if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
      if (this.advisedBeans.containsKey(cacheKey)) {
         return null;
      }
      // 解析切面
      if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
         this.advisedBeans.put(cacheKey, Boolean.FALSE);
         return null;
      }
   }
   TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
   if (targetSource != null) {
      if (StringUtils.hasLength(beanName)) {
         this.targetSourcedBeans.add(beanName);
      }
      Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
      Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
      this.proxyTypes.put(cacheKey, proxy.getClass());
      return proxy;
   }

   return null;
}

@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) {
   return true;
}

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
   return bean;
}

@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;
}

在 postProcessBeforeInstantiation 方法中实现了切面解析的逻辑,会在第一个bean实例化前执行。

在 postProcessAfterInitialization 方法中实现创建代理,在bean初始化后执行。

切面解析入口方法 postProcessBeforeInstantiation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// 切面bean缓存
private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
  Object cacheKey = getCacheKey(beanClass, beanName);

  if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
    // 如果已经解析返回
    if (this.advisedBeans.containsKey(cacheKey)) {
      return null;
    }
		// 解析切面
    if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
      this.advisedBeans.put(cacheKey, Boolean.FALSE);
      return null;
    }
  }
  return null;
}

postProcessBeforeInstantiation 在bean实例化前执行。

shouldSkip 方法中实现注解方式AOP的解析过程。

解析过的切面会把beanName存入 advisedBeans 缓存中, 不再重复解析。

解析切面核心方法 shouldSkip

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
  // TODO: Consider optimization by caching the list of the aspect names
  List<Advisor> candidateAdvisors = findCandidateAdvisors();
  for (Advisor advisor : candidateAdvisors) {
    if (advisor instanceof AspectJPointcutAdvisor &&
        ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
      return true;
    }
  }
  return super.shouldSkip(beanClass, beanName);
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@Override
protected List<Advisor> findCandidateAdvisors() {
  // Add all the Spring advisors found according to superclass rules.
  List<Advisor> advisors = super.findCandidateAdvisors();
  // Build Advisors for all AspectJ aspects in the bean factory.
  if (this.aspectJAdvisorsBuilder != null) {
    advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
  }
  return advisors;
}

shouldSkip 中调用 findCandidateAdvisors() 解析所有候选的切面,切面有两种切面,一种是基于接口的切面,一种是基于注解的切面。

解析接口方式的切面

一种是调用 super.findCandidateAdvisors() 解析所有实现Advisor接口的切面bean。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
protected List<Advisor> findCandidateAdvisors() {
  return this.advisorRetrievalHelper.findAdvisorBeans();
}

public List<Advisor> findAdvisorBeans() {
  String[] advisorNames = this.cachedAdvisorBeanNames;
		if (advisorNames == null) {
			// Do not initialize FactoryBeans here: We need to leave all regular beans
			// uninitialized to let the auto-proxy creator apply to them!
			advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
					this.beanFactory, Advisor.class, true, false);
			this.cachedAdvisorBeanNames = advisorNames;
		}
		if (advisorNames.length == 0) {
			return new ArrayList<>();
		}
    // ... 略
}

这里的核心操作是解析所有实现 Advisor 接口的bean, 缓存起来。

解析注解方式的切面

另一种调用 aspectJAdvisorsBuilder.buildAspectJAdvisors() 解析所有注解方式的切面。

1
2
3
4
// Advisor缓存,key是aspectNeam
private final Map<String, List<Advisor>> advisorsCache = new ConcurrentHashMap<>();

public List<Advisor> buildAspectJAdvisors() {}

buildAspectJAdvisors 的代码很长,这里略过,只说一下核心逻辑,它会解析Spring容器中取出所有的切面,构建成Advisor放入到advisorsCache缓存起来。

现在所有的切面都解析好并且缓存起来了,下面就是创建动态代理。

创建动态代理

AOP创建动态代理有两种方式,如果代理目标实现了接口,则采用JDK动态代理,如果没有实现接口,则采用Cglib动态代理。

image-20211209164425900

代理创建入口方法 postProcessAfterInitialization

前面说过在bean初始化后执行。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@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;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
    return bean;
  }
  if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
    return bean;
  }
  if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
  }

  // 根据当前bean获取候选的Advisor,这里做第一次筛选,初步筛选,只根据beanClass匹配。
  Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
  if (specificInterceptors != DO_NOT_PROXY) {
    this.advisedBeans.put(cacheKey, Boolean.TRUE);
    // 创建代理
    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;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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);
		}
    // 实例化代理工厂并设置创建代理所需的原料
		ProxyFactory proxyFactory = new ProxyFactory(); 
		proxyFactory.copyFrom(this);

		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, 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());
	}
  • 创建代理工厂,为代理工程设置原料,一个是要创建代理的代理目标,表明为哪些类创建代理对象,这里是当前bean对象。
  • 另一个是要植入的切面,为代理目标增强的那些功能。
1
2
3
4
public Object getProxy(@Nullable ClassLoader classLoader) {
   // 创建AOP代理工厂,创建代理对象
   return createAopProxy().getProxy(classLoader);
}
1
2
3
4
5
6
7
protected final synchronized AopProxy createAopProxy() {
   if (!this.active) {
      activate();
   }
   // 创建AOP代理工厂
   return getAopProxyFactory().createAopProxy(this);
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
   if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
      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.");
      }
      // 如果接口或已经是jdk代理,则走JDK动态代理。
      if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
         return new JdkDynamicAopProxy(config);
      }
      // CGLIB 动态代理
      return new ObjenesisCglibAopProxy(config);
   }
   else {
      // JDK 动态代理
      return new JdkDynamicAopProxy(config);
   }
}
  • 首先根据当前bean获取符合条件的签名通知列表。
  • 实例化代理工厂,设置代理目标,设置代理切面通知。
  • 在代理工厂中又创建AOP代理工厂,根据代理目标选择Cglib或jdk动态代理。
  • 最后调用代理工厂中 getProxy 方法生成代理对象。

CglibAopProxy cglib动态代理

Cglib可以为普通类和接口创建代理类,原理是在应用启动是通过asm技术生成新的字节码文件,新的字节码都统一的签注$$。

实例:

代理目标类 Person.java

1
2
3
4
5
6
public class Person {

    public void sayHello() {
        System.out.println("hello word!");
    }
}

代理工厂类 CglibProxyFactory.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class CglibProxyFactory implements MethodInterceptor {

    /**
     * 代理目标
     */
    private final Object target;
    private final Enhancer enhancer;
  
    public CglibProxyFactory(Object target) {
        this.target = target;
        this.enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
    }


    public Object getProxy() {
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("业务方法执行前...");
        Object result = methodProxy.invokeSuper(o, objects);
        System.out.println("业务方法执行后...");
        return result;
    }
}

测试 & 执行结果

1
2
3
4
5
public static void main(String[] args) {
    CglibProxyFactory proxyFactory = new CglibProxyFactory(new Person());
    Person person = (Person) proxyFactory.getProxy();
    person.sayHello();
}
1
2
3
业务方法执行前...
hello word!
业务方法执行后...

JdkDynamicAopProxy JDK动态代理

jdk 动态代理只能为实现接口的类创建代理。

jdk 动态代理底层通过生成字节码实现,生成的代理类都会继承一个模板类Proxy, 生成的类名一般为 $Proxy0这样,这也是什么jdk动态代理不能为普通类创建代理的原因,它已经继承Proxy类了,没发再继承另一个了。

实例:创建代理目标和接口

1
2
3
public interface Animal {
    void test();
}
1
2
3
4
5
6
public class Dog implements Animal {
    @Override
    public void test() {
        System.out.println("dog 会跑!");
    }
}

代理工厂 JdkDynamicProxyFactory.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class JdkDynamicProxyFactory implements InvocationHandler {

    /**
     * 代理目标
     */
    private final Object target;

    public JdkDynamicProxyFactory(Object target) {
        this.target = target;
    }

    public Object getProxy() {
        return  Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("业务方法执行前...");
        Object result = method.invoke(target, args);
        System.out.println("业务方法执行后...");
        return result;
    }
}

测试 & 执行结果

1
2
3
4
5
public static void main(String[] args) {
  JdkDynamicProxyFactory proxyFactory = new JdkDynamicProxyFactory(new Dog());
  Animal animal = (Animal) proxyFactory.getProxy();
  animal.test();
}
1
2
3
业务方法执行前...
dog 会跑!
业务方法执行后...

调用代理方法

JDK 动态代理调用切面方法

jdk动态代理调用是通过实现 InvocationHandler 接口的 invoke 方法调用切面方法。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
  @Override
	@Nullable
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		MethodInvocation invocation;
		Object oldProxy = null;
		boolean setProxyContext = false;

		TargetSource targetSource = this.advised.targetSource;
		Object target = null;

		try {
      // 如果是 equals、hashCode 等方法不用调用切面方法,最终调用原方法。
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				// The target does not implement the equals(Object) method itself.
				return equals(args[0]);
			}
  
			else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				// The target does not implement the hashCode() method itself.
				return hashCode();
			}
    
			else if (method.getDeclaringClass() == DecoratingProxy.class) {
				// There is only getDecoratedClass() declared -> dispatch to proxy config.
				return AopProxyUtils.ultimateTargetClass(this.advised);
			}
  
			else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
				// Service invocations on ProxyConfig with the proxy config...
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;

			if (this.advised.exposeProxy) {
				// Make invocation available if necessary.
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

			// Get as late as possible to minimize the time we "own" the target,
			// in case it comes from a pool.
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			// 获取方法的连拦截链,这里会根据方法名最进一步的筛选
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

			if (chain.isEmpty()) {
			  // 如果拦截链为空,调用原方法
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				// 构建调用链,使用责任链模式,执行切面方法。
				invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// Proceed to the joinpoint through the interceptor chain.
				retVal = invocation.proceed();
			}

			// Massage return value if necessary.
			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;
			}
			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 {
			if (target != null && !targetSource.isStatic()) {
				// Must have come from TargetSource.
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				// Restore old proxy.
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}
}

Cglib 动态代理调用切面方法

Cglib 通过实现 MethodInterceptor 接口的 intercept 方法调用切面方法。

1
2
3
public interface MethodInterceptor extends Callback {
    Object intercept(Object var1, Method var2, Object[] var3, MethodProxy var4) throws Throwable;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
  
  	@Override
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object oldProxy = null;
			boolean setProxyContext = false;
			Object target = null;
			TargetSource targetSource = this.advised.getTargetSource();
			try {
				if (this.advised.exposeProxy) {
					// Make invocation available if necessary.
					oldProxy = AopContext.setCurrentProxy(proxy);
					setProxyContext = true;
				}
				// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
				target = targetSource.getTarget();
				Class<?> targetClass = (target != null ? target.getClass() : null);
        // 获取拦截链
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
				Object retVal;
				// Check whether we only have one InvokerInterceptor: that is,
				// no real advice, but just reflective invocation of the target.
				if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
					// We can skip creating a MethodInvocation: just invoke the target directly.
					// Note that the final invoker must be an InvokerInterceptor, so we know
					// it does nothing but a reflective operation on the target, and no hot
					// swapping or fancy proxying.
					Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
					retVal = methodProxy.invoke(target, argsToUse);
				}
				else {
					// 责任连调用,切面方法。
					retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
				}
				retVal = processReturnType(proxy, target, method, retVal);
				return retVal;
			}
			finally {
				if (target != null && !targetSource.isStatic()) {
					targetSource.releaseTarget(target);
				}
				if (setProxyContext) {
					// Restore old proxy.
					AopContext.setCurrentProxy(oldProxy);
				}
			}
		}

}

cglib的调用类 CglibMethodInvocation 继承 ReflectiveMethodInvocation。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
private static class CglibMethodInvocation extends ReflectiveMethodInvocation {

		private final MethodProxy methodProxy;

		private final boolean publicMethod;

		public CglibMethodInvocation(Object proxy, @Nullable Object target, Method method,
				Object[] arguments, @Nullable Class<?> targetClass,
				List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {

			super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);
			this.methodProxy = methodProxy;
			this.publicMethod = Modifier.isPublic(method.getModifiers());
		}
	}
  • jdk动态代理调用是通过实现 InvocationHandler 接口的 invoke 方法调用切面方法。
  • Cglib 通过实现 MethodInterceptor 接口的 intercept 方法调用切面方法。
  • ReflectiveMethodInvocation 通责任连模式对象切面的调用。

附:AOP启动流程图

https://raw.gitmirror.com/telzhou618/images/main/img01/Spring%20AOP%20%E5%8A%A0%E8%BD%BD%E6%B5%81%E7%A8%8B.png

0%