Spring 如何实现 AOP,请不要再说 cglib 了!

来源:juejin.im/post/6844903970658320391

  1. 从注解入手找到对应核心类
  2. 画核心类类图,猜测核心方法
  3. 读重点方法,理核心流程
  4. 总结
  5. 从注解入手找到对应核心类

最近工作中我都是基于注解实现 AOP 功能,常用的开启 AOP 的注解是 @EnableAspectJAutoProxy,我们就从它入手。
在这里插入图片描述

上面的动图的流程的步骤就是:@EnableAspectJAutoProxy --> AspectJAutoProxyRegistrar -->AopConfigUtils .registerAspectJAnnotationAutoProxyCreatorIfNecessary -->AnnotationAwareAspectJAutoProxyCreator.class

“AnnotationAwareAspectJAutoProxyCreator 查看其中文注释(如下),确定它就是 AOP 的核心类!–
温安适 20191020

AspectJAwareAdvisorAutoProxyCreator的子类 ,用于处理当前应用上下文中的注解切面
任何被AspectJ注解的类将自动被识别。
若SpringAOP代理模式可以识别,优先使用Spring代理模式。
它覆盖了方法执行连接点
如果使用aop:include元素, 则只有名称与include模式匹配的@aspectj bean才被视为切面 ,并由spring自动代理。
Spring Advisors的处理请查阅,

org.springframework.aop
.framework.autoproxy.AbstractAdvisorAutoProxyCreator

@SuppressWarnings("serial")
public class AnnotationAwareAspectJAutoProxyCreator
extends AspectJAwareAdvisorAutoProxyCreator {
   
    //...省略实现
    }注解切面

虽然找到了核心类,但是并没有找到核心方法!下面我们尝试画类图确定核心方法。
2. 画核心类类图,猜测核心方法

AnnotationAwareAspectJAutoProxyCreator 的部分类图。
在这里插入图片描述
AnnotationAwareAspectJAutoProxyCreator 从类图看到了 AnnotationAwareAspectJAutoProxyCreator 实现了 BeanPostProcessor,而 AOP 功能应该在创建完 Bean 之后执行,猜测 AnnotationAwareAspectJAutoProxyCreator 实现 BeanPostProcessor 的 postProcessAfterInitialization(实例化 bean 后处理)是核心方法。查看 AnnotationAwareAspectJAutoProxyCreator 实现的 postProcessAfterInitialization 方法,实际该方法在其父类 AbstractAutoProxyCreator 中。

//AbstractAutoProxyCreator中的postProcessAfterInitialization实现
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
 throws BeansException {
   
   if (bean != null) {
   
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      if (!this.earlyProxyReferences.contains(cacheKey)) {
   
         return wrapIfNecessary(bean, beanName, cacheKey);
      }
   }
   return bean;
}

发现发现疑似方法 wrapIfNecessary,查看其源码如下,发现 createProxy 方法。确定找对了地方。

protected Object wrapIfNecessary
        (Object bean, String beanName, Object cacheKey) {
   
   if (beanName != null && 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;
   }

   // 创建代理
   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;
}

即 AnnotationAwareAspectJAutoProxyCreator 实现 BeanPostProcessor 的 postProcessAfterInitialization 方法,在该方法中由 wrapIfNecessary 实现了 AOP 的功能。wrapIfNecessary 中有 2 个和核心方法
getAdvicesAndAdviso

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring AOP使用CGLIB作为默认的代理方式来实现动态代理。代理过程中,首先需要定义一个被代理的目标对象或者叫做目标类。该目标对象可以是任何一个Java对象,它会在运行时被代理创建。然后,通过Spring配置文件或者注解,将该目标对象注入到Spring容器中。 接下来,需要定义一个切面类,该类中包含了代理的具体操作和条件。这些操作和条件可以是在目标对象的方法执行前后增加日志、事务控制、权限验证等。切面类通常会实现Advice接口或者继承AbstractAspectJAdvice类。 在Spring容器启动时,会根据配置文件或者注解自动扫描到切面类,并且生成代理对象。生成代理对象的方式有两种:JDK动态代理和CGLIB动态代理。在Spring AOP中,默认使用CGLIB动态代理方式,因为CGLIB可以代理没有实现接口的目标类。 当目标对象的方法被调用时,代理对象会先调用切面类的相应方法,然后再调用目标对象的方法。这样,代理对象就可以在目标对象方法执行前后,添加自己的逻辑。 CGLIB是一个强大的第三方类库,它通过继承的方式创建代理对象。通过修改字节码,可以在目标类中创建子类,并将代理逻辑插入到子类的方法中,从而实现代理的功能。 总之,Spring AOP使用CGLIB作为默认的代理方式来实现动态代理。代理过程中,首先需要定义目标对象和切面类,然后通过配置文件或者注解将它们注入到Spring容器中。在运行时,Spring容器会自动生成代理对象,并在方法执行前后执行切面逻辑,实现代理的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值