千家信息网

Spring如何实现AOP

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章主要介绍"Spring如何实现AOP",在日常操作中,相信很多人在Spring如何实现AOP问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"Spring如何实现A
千家信息网最后更新 2026年11月02日Spring如何实现AOP

这篇文章主要介绍"Spring如何实现AOP",在日常操作中,相信很多人在Spring如何实现AOP问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"Spring如何实现AOP"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

1. 从注解入手找到对应核心类

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

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

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

/**1.AspectJAwareAdvisorAutoProxyCreator的子类,用于处理当前应用上下文中的注解切面2.任何被AspectJ注解的类将自动被识别。3.若SpringAOP代理模式可以识别,优先使用Spring代理模式。4.它覆盖了方法执行连接点5.如果使用元素,  则只有名称与include模式匹配的@aspectj bean才被视为切面  ,并由spring自动代理。6. Spring Advisors的处理请查阅,org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator */@SuppressWarnings("serial")public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {    //...省略实现    }注解切面

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

2.画核心类类图,猜测核心方法

AnnotationAwareAspectJAutoProxyCreator的部分类图。

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

//AbstractAutoProxyCreator中的postProcessAfterInitialization实现@Overridepublic 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个和核心方法

  • getAdvicesAndAdvisorsForBean获取当前bean匹配的增强器

  • createProxy为当前bean创建代理
    要想明白核心流程还需要分析这2个方法。

3.读重点方法,理核心流程

3.1 getAdvicesAndAdvisorsForBean获取当前bean匹配的增强器

查看源码如下,默认实现在AbstractAdvisorAutoProxyCreator中。

@Override@Nullableprotected Object[] getAdvicesAndAdvisorsForBean(      Class beanClass, String beanName,       @Nullable TargetSource targetSource) {   List advisors = findEligibleAdvisors(beanClass, beanName);   if (advisors.isEmpty()) {      return DO_NOT_PROXY;   }   return advisors.toArray();}

查阅findEligibleAdvisors方法,就干了3件事

  • 找所有增强器,也就是所有@Aspect注解的Bean

  • 找匹配的增强器,也就是根据@Before,@After等注解上的表达式,与当前bean进行匹配,暴露匹配上的。

  • 对匹配的增强器进行扩展和排序,就是按照@Order或者PriorityOrdered的getOrder的数据值进行排序,越小的越靠前。

protected List findEligibleAdvisors(Class beanClass, String beanName) {   //找所有增强器   List candidateAdvisors = findCandidateAdvisors();   //找所有匹配的增强器   List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);   extendAdvisors(eligibleAdvisors);   if (!eligibleAdvisors.isEmpty()) {       //排序      eligibleAdvisors = sortAdvisors(eligibleAdvisors);   }   return eligibleAdvisors;}

AnnotationAwareAspectJAutoProxyCreator 重写了findCandidateAdvisors,下面我们看看具体实现了什么

3.1.1findCandidateAdvisors找所有增强器,也就是所有@Aspect注解的Bean

@Overrideprotected List findCandidateAdvisors() {   // Add all the Spring advisors found according to superclass rules.   List advisors = super.findCandidateAdvisors();   // Build Advisors for all AspectJ aspects in the bean factory.   if (this.aspectJAdvisorsBuilder != null) {      //@Aspect注解的类在这里除了      advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());   }   return advisors;}

从该方法我们可以看到处理@Aspect注解的bean的方法是:this.aspectJAdvisorsBuilder.buildAspectJAdvisors()。 这个方法如下:

public List buildAspectJAdvisors() {   List aspectNames = this.aspectBeanNames;   if (aspectNames == null) {      synchronized (this) {         aspectNames = this.aspectBeanNames;         if (aspectNames == null) {            List advisors = new ArrayList<>();            aspectNames = new ArrayList<>();            //找到所有BeanName            String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(                  this.beanFactory, Object.class, true, false);            for (String beanName : beanNames) {               if (!isEligibleBean(beanName)) {                  continue;               }               // 必须注意,bean会提前暴露,并被Spring容器缓存,但是这时还不能织入。               Class beanType = this.beanFactory.getType(beanName);               if (beanType == null) {                  continue;               }               if (this.advisorFactory.isAspect(beanType)) {                  //找到所有被@Aspect注解的类                  aspectNames.add(beanName);                  AspectMetadata amd = new AspectMetadata(beanType, beanName);                  if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {                     MetadataAwareAspectInstanceFactory factory =                           new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);                     //解析封装为Advisor返回                     List classAdvisors = this.advisorFactory.getAdvisors(factory);                     if (this.beanFactory.isSingleton(beanName)) {                        this.advisorsCache.put(beanName, classAdvisors);                     }                     else {                        this.aspectFactoryCache.put(beanName, factory);                     }                     advisors.addAll(classAdvisors);                  }                  else {                     // Per target or per this.                     if (this.beanFactory.isSingleton(beanName)) {                        throw new IllegalArgumentException("Bean with name '" + beanName +                              "' is a singleton, but aspect instantiation model is not singleton");                     }                     MetadataAwareAspectInstanceFactory factory =                           new PrototypeAspectInstanceFactory(this.beanFactory, beanName);                     this.aspectFactoryCache.put(beanName, factory);                     advisors.addAll(this.advisorFactory.getAdvisors(factory));                  }               }            }            this.aspectBeanNames = aspectNames;            return advisors;         }      }   }   if (aspectNames.isEmpty()) {      return Collections.emptyList();   }   List advisors = new ArrayList<>();   for (String aspectName : aspectNames) {      List cachedAdvisors = this.advisorsCache.get(aspectName);      if (cachedAdvisors != null) {         advisors.addAll(cachedAdvisors);      }      else {         MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);         advisors.addAll(this.advisorFactory.getAdvisors(factory));      }   }   return advisors;}

这个方法可以概括为:

  • 找到所有BeanName

  • 根据BeanName筛选出被@Aspect注解的类

  • 针对类中被Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class注解的方法,先按上边的注解顺序排序后按方法名称排序,每一个方法对应一个Advisor。

3.2 createProxy为当前bean创建代理。

3.2.1 创建代理的2种方式

众所周知,创建代理的常用的2种方式是:JDK创建和CGLIB,下面我们就看看这2中创建代理的例子。

3.2.1 .1 jdk创建代理的例子
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class JDKProxyMain {    public static void main(String[] args) {        JDKProxyTestInterface target = new JDKProxyTestInterfaceImpl();        // 根据目标对象创建代理对象        JDKProxyTestInterface proxy =         (JDKProxyTestInterface) Proxy         .newProxyInstance(target.getClass().getClassLoader(),                target.getClass().getInterfaces(),                 new JDKProxyTestInvocationHandler(target));        // 调用代理对象方法        proxy.testProxy();    }    interface JDKProxyTestInterface {        void testProxy();    }    static class JDKProxyTestInterfaceImpl                     implements JDKProxyTestInterface {        @Override        public void testProxy() {            System.out.println("testProxy");        }    }   static class JDKProxyTestInvocationHandler                            implements InvocationHandler {        private  Object target;        public JDKProxyTestInvocationHandler(Object target){            this.target=target;        }        @Override        public Object invoke(Object proxy, Method method,                             Object[] args) throws Throwable {            System.out.println("执行前");            Object result=  method.invoke(this.target,args);            System.out.println("执行后");            return result;        }    }
3.2.1 .2 cglib创建代理的例子
import org.springframework.cglib.proxy.Enhancer;import org.springframework.cglib.proxy.MethodInterceptor;import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class CglibProxyTest {   static class CglibProxyService {        public  CglibProxyService(){        }        void sayHello(){            System.out.println(" hello !");        }    }    static class CglibProxyInterceptor implements MethodInterceptor{        @Override        public Object intercept(Object sub, Method method,             Object[] objects, MethodProxy methodProxy)                                          throws Throwable {            System.out.println("before hello");            Object object = methodProxy.invokeSuper(sub, objects);            System.out.println("after hello");            return object;        }    }    public static void main(String[] args) {        // 通过CGLIB动态代理获取代理对象的过程        Enhancer enhancer = new Enhancer();        // 设置enhancer对象的父类        enhancer.setSuperclass(CglibProxyService.class);        // 设置enhancer的回调对象        enhancer.setCallback(new CglibProxyInterceptor());        // 创建代理对象        CglibProxyService proxy= (CglibProxyService)enhancer.create();        System.out.println(CglibProxyService.class);        System.out.println(proxy.getClass());        // 通过代理对象调用目标方法        proxy.sayHello();    }}
3.2.1 .3 jdk创建代理与cglib创建代理的区别
类型jdk创建动态代理cglib创建动态代理
原理java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理
核心类Proxy 创建代理利用反射机制生成一个实现代理接口的匿名类InvocationHandler 方法拦截器接口,需要实现invoke方法net.sf.cglib.proxy.Enhancer:主要增强类,通过字节码技术动态创建委托类的子类实例net.sf.cglib.proxy.MethodInterceptor:方法拦截器接口,需要实现intercept方法
局限性只能代理实现了接口的类不能对final修饰的类进行代理,也不能处理final修饰的方法

3.2.2 Spring如何选择的使用哪种方式

Spring的选择选择如何代理时在DefaultAopProxyFactory 中。

public class DefaultAopProxyFactory implements AopProxyFactory,                                                         Serializable {   @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.");         }         if (targetClass.isInterface()                  || Proxy.isProxyClass(targetClass)) {            return new JdkDynamicAopProxy(config);         }         return new ObjenesisCglibAopProxy(config);      }      else {         return new JdkDynamicAopProxy(config);      }   }   //...   }
  • config.isOptimize() 查看源码注释时发现,这个是配置使用cglib代理时,是否使用积极策略。这个值一般不建议使用!

  • config.isProxyTargetClass() 就是@EnableAspectJAutoProxy中的proxyTargetClass属性。

//exposeProxy=true AopContext 可以访问,proxyTargetClass=true CGLIB生成代理 @EnableAspectJAutoProxy(exposeProxy=true,proxyTargetClass=true)

  • hasNoUserSuppliedProxyInterfaces 是否存在可代理的接口

总结下Spring如何选择创建代理的方式:

  1. 如果设置了proxyTargetClass=true,一定是CGLIB代理

  2. 如果proxyTargetClass=false,目标对象实现了接口,走JDK代理

  3. 如果没有实现接口,走CGLIB代理

4.总结

Spring如何实现AOP?,您可以这样说:

  1. AnnotationAwareAspectJAutoProxyCreator是AOP核心处理类

  2. AnnotationAwareAspectJAutoProxyCreator实现了BeanProcessor,其中postProcessAfterInitialization是核心方法。

  3. 核心实现分为2步
    getAdvicesAndAdvisorsForBean获取当前bean匹配的增强器 createProxy为当前bean创建代理

  4. getAdvicesAndAdvisorsForBean核心逻辑如下
    a. 找所有增强器,也就是所有@Aspect注解的Bean
    b. 找匹配的增强器,也就是根据@Before,@After等注解上的表达式,与当前bean进行匹配,暴露匹配上的。
    c. 对匹配的增强器进行扩展和排序,就是按照@Order或者PriorityOrdered的getOrder的数据值进行排序,越小的越靠前。

  5. createProxy有2种创建方法,JDK代理或CGLIB
    a. 如果设置了proxyTargetClass=true,一定是CGLIB代理
    b. 如果proxyTargetClass=false,目标对象实现了接口,走JDK代理
    c. 如果没有实现接口,走CGLIB代理

到此,关于"Spring如何实现AOP"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

代理 方法 注解 核心 增强器 对象 接口 处理 排序 动态 也就是 就是 方式 目标 学习 生成 选择 例子 切面 功能 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 喔噻互联网科技有限公司 百单网互联网科技有限公司怎么样 疫情对互联网科技公司影响 互联网科技公司发展 赫美联合互联网科技 互联网科技网站 移动互联网科技股 汽车互联网创新科技园 中国互联网公司排名锤子科技 为客找房互联网科技公司怎么样 互联网企业科技类企业如何做账 互联网科技年终奖 全球科技与互联网公司市值变化 艺电能源互联网科技有限公司招聘 互联网金融运营模式中的金融科技 福仕德教育科技互联网 互联网科技自媒体灵感 六子台科技互联网展会 每日互联网科技新闻 广州全民伙伴互联网科技有限公司 互联网科技财经 互联网科技ppt模板 国外互联网科技网站 互联网实体化科技化 宝灵互联网科技有限公司 亳州好赞互联网科技有限公司 银川新华互联网科技学校联系电话 玉溪新华互联网科技好不好 卓翼科技产业互联网合作 高科技互联网套路
0