Spring Aop是通过代理模式实现的,动态代理实现有两种:①cglib(基于父子类)。②JDK自带动态代理(基于接口)。Spring封装后提供了几种创建AOP的方式:①ProxyFactoryBean ②ProxyFactory ③Auto-proxy(又可分为三种:BeanNameAutoProxyCreator、DefaultAdvisorAutoProxyCreator、AnnotationAwareAspectJAutoProxyCreator) 。这三种方法最终都会创建ProxyFactory,本教程主要以AnnotationAwareAspectJAutoProxyCreator为例,讲解Spring如果进行AOP的。

1、ProxyFactory用法介绍

因为上边介绍的几种Spring创建AOP的方式,最终都会去创建ProxyFactory,所以我们先来介绍下ProxyFactory的用法。
通过ProxyFactory,我们不用关心到底是用jdk还是cglib了,它会自己判断,如果代理的对象实现了接口,那么会用jdk动态代理,如果没有实现接口,则会用cglib技术。下面的例子,User类没有实现接口,所以底层走的是cglib。

  1. @Component
  2. public class User {
  3. @Autowired
  4. private Dog dog;
  5. void say() {
  6. System.out.println("hi i am tom");
  7. }
  8. }
  1. @Configuration
  2. @ComponentScan("com.ioc.tuing.impl")
  3. public class MainStart {
  4. public static void main(String[] args) {
  5. // ProxyFactory
  6. User target = new User();
  7. ProxyFactory proxyFactory = new ProxyFactory();
  8. proxyFactory.setTarget(target);
  9. proxyFactory.addAdvice(new MethodInterceptor() {
  10. @Override
  11. public Object invoke(MethodInvocation invocation) throws Throwable {
  12. System.out.println("before...");
  13. Object result = invocation.proceed();
  14. System.out.println("after...");
  15. return result;
  16. }
  17. });
  18. User user = (User)proxyFactory.getProxy();
  19. user.say();
  20. }
  21. }

打印结果:

  1. before...
  2. hi i am tom
  3. after...

2、Spring AOP流程

我们在实际工作中,通常会用注解的方式来使用AOP,首先用@EnableAspectJAutoProxy注解开启AOP自动代理,然后配合@Aspect、@before、@Pointcut等注解使用,实际上这就是我们在上面说AnnotationAwareAspectJAutoProxyCreator方式。大致步骤如下图所示:六、Spring AOP - 图1

2.1、@EnableAspectJAutoProxy开启AOP

通过@EnableAspectJAutoProxy注解,导入配置类AspectJAutoProxyRegistrar,而AspectJAutoProxyRegistrar类会向容器中注册一个AnnotationAwareAspectJAutoProxyCreator的BeanDefinition,它本身也是一个BeanPostProcessor。
image.png
这个BeanDefinition会在org.springframework.context.support.AbstractApplicationContext#registerBeanPostProcessors这个方法中完成创建。
六、Spring AOP - 图3

2.2、postProcessBeforeInstantiation方法执行

执行AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInstantiation方法,实际上就是父类AbstractAutoProxyCreator的postProcessBeforeInstantiation被执行。这个方法的作用就是:确定哪些类不需要被代理。

2.3、postProcessAfterInitialization方法执行

实际上也是执行父类AbstractAutoProxyCreator中的方法,其中wrapIfNecessary完成了AOP代理,对应源码如下:

  1. public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
  2. if (bean != null) {
  3. Object cacheKey = getCacheKey(bean.getClass(), beanName);
  4. // 什么时候这个判断会成立呢?
  5. // 如果发生循环依赖的话,这个判断就不会成立(这里不做详细分析)
  6. // 目前你只需要知道wrapIfNecessary完成了AOP代理
  7. if (this.earlyProxyReferences.remove(cacheKey) != bean) {
  8. // 需要代理的话,在这里完成的代理
  9. return wrapIfNecessary(bean, beanName, cacheKey);
  10. }
  11. }
  12. return bean;
  13. }

2.4、wrapIfNecessary方法执行,生成代理对象。

  1. protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  2. // 在postProcessBeforeInstantiation方法中可能已经完成过代理了
  3. // 如果已经完成代理了,那么直接返回这个代理的对象
  4. if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
  5. return bean;
  6. }
  7. // 在postProcessBeforeInstantiation方法中可能已经将其标记为不需要代理了
  8. // 这种情况下,也直接返回这个Bean
  9. if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
  10. return bean;
  11. }
  12. // 跟在postProcessBeforeInstantiation方法中的逻辑一样
  13. // 如果不需要代理,直接返回,同时在advisedBeans中标记成false
  14. if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
  15. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  16. return bean;
  17. }
  18. // 获取可以应用到这个Bean上的通知
  19. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
  20. // 如果存在通知的话,说明需要被代理
  21. if (specificInterceptors != DO_NOT_PROXY) {
  22. this.advisedBeans.put(cacheKey, Boolean.TRUE);
  23. // 到这里创建代理,实际上底层就是new了一个ProxyFactory来创建代理的
  24. Object proxy = createProxy(
  25. bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
  26. this.proxyTypes.put(cacheKey, proxy.getClass());
  27. return proxy;
  28. }
  29. // 如果没有通知的话,也将这个Bean标记为不需要代理
  30. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  31. return bean;
  32. }

3、AOP底层逻辑

前面我们只是介绍了Spring AOP的过程,结合bean的生命周期,讲了Spring如何、在何时进行的AOP。但是AOP的底层逻辑(比如怎么解析的通知)我们没做讲解,这些步骤很杂、很多,这里放出一张思维图,供大家参考:
https://www.processon.com/view/link/5faa4ccce0b34d7a1aa2a9a5