Spring的AOP实现

本文深入探讨了Spring AOP的实现过程,从配置文件解析到动态代理的创建。通过分析`AopNamespaceHandler`、`AspectJAutoProxyBeanDefinitionParser`、`AnnotationAwareAspectJAutoProxyCreator`等关键类,揭示了如何根据@AspectJ注解生成代理,并详细解释了JDK动态代理的创建逻辑,包括拦截器链的执行流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如果需要在Spring中使用AOP是非常简单的,只需要在Bean上加上@AspectJ,在方法上加@PointCut、@Before等注解就可以实现你想要的逻辑,最后在XML配置文件中加入<aop:aspectj-autoproxy>即可。

那么Spring是如何实现的呢?

动态AOP标签

我们从AopNamespaceHandler中的init()方法开始分析:

1.配置文件中在遇到aspectj-autoproxy标签的时候我们会采用AspectJAutoProxyBeanDefinitionParser解析器

2.进入AspectJAutoProxyBeanDefinitionParser的parse方法,它将请求给了AopNamespaceUtils的registerAspectJAnnotationAutoProxyCreatorIfNecessary去处理

3.registerAspectJAnnotationAutoProxyCreatorIfNecessary方法中,先调用AopConfigUtils的registerAspectJAnnotationAutoProxyCreatorIfNecessary方法完成注册或者升级AnnotationAwareAspectJAutoProxyCreator类。对于AOP的实现,基本是靠AnnotationAwareAspectJAutoProxyCreator去完成的,它可以根据@point注解定义的切点来代理相匹配的bean。

4.接下来会调用useClassProxyingIfNecessary() 处理proxy-target-class以及expose-proxy属性

5.最后的调用registerComponentIfNecessary 方法,注册组建并且通知便于监听器做进一步处理。

2.创建AOP代理

AOP主要是依靠AnnotationAwareAspectJAutoProxyCreator的实现的。那么AnnotationAwareAspectJAutoProxyCreator是如何完成的?

AnnotationAwareAspectJAutoProxyCreator的层次结构:

这里写图片描述

AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessor接口,那就意味着这个类在spring加载实例化前会调用postProcessAfterInitialization方法。

public Object <strong>postProcessAfterInitialization</strong>(Object bean, String beanName) throws BeansException {  
    if (bean != null) {  
        Object cacheKey = getCacheKey(bean.getClass(), beanName);  
        if (!this.earlyProxyReferences.containsKey(cacheKey)) {  
            return wrapIfNecessary(bean, beanName, cacheKey);  
        }  
    }  
    return bean;  
}  

逻辑:
1.根据bean的class和name生成一个key。
2.如果适合代理就执行wrapIfNecessary(bean, beanName, cacheKey)。

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

逻辑:
1.如果以及处理过直接返回bean
2.不需要advisor返回bean
3.如果是基类或者说不需要自动代理返回bean。
4.获得此类的advisor
5.创建代理

2.1 getAdvicesAndAdvisorsForBean

getAdvicesAndAdvisorsForBean主要逻辑由findEligibleAdvisors实现

protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) {
2     List<Advisor> candidateAdvisors = findCandidateAdvisors();
3     List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
4     extendAdvisors(eligibleAdvisors);
5     if (!eligibleAdvisors.isEmpty()) {
6         eligibleAdvisors = sortAdvisors(eligibleAdvisors);
7     }
8     return eligibleAdvisors;
9 }

findEligibleAdvisors实现逻辑:
1.findCandidateAdvisors找到所有的Advisors
2.findAdvisorsThatCanApply找到匹配当前bean的Advisors。

findCandidateAdvisors源码逻辑:
1.获得beanFactory中注册所有的BeanName
2.遍历所有BeanName,找出有@AspectJ的类
3.对有@AspectJ的类提取advisor
4.将提取出的结果放入缓存。

findAdvisorsThatCanApply源码逻辑:
从findCandidateAdvisors获得的advisor中寻找适合当前class的advisor。

2.2 createProxy

protected Object createProxy(  
            Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {  

        ProxyFactory proxyFactory = new ProxyFactory();  
        // Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.  
        proxyFactory.copyFrom(this);  

        if (!shouldProxyTargetClass(beanClass, beanName)) {  
            // Must allow for introductions; can't just set interfaces to  
            // the target's interfaces only.  
            Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);  
            for (Class<?> targetInterface : targetInterfaces) {  
                proxyFactory.addInterface(targetInterface);  
            }  
        }  

        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);  
        for (Advisor advisor : advisors) {  
            proxyFactory.addAdvisor(advisor);  
        }  

        proxyFactory.<strong>setTargetSource</strong>(targetSource);  
        customizeProxyFactory(proxyFactory);  

        proxyFactory.setFrozen(this.freezeProxy);  
        if (advisorsPreFiltered()) {  
            proxyFactory.setPreFiltered(true);  
        }  
          //实现核心方法
        return proxyFactory.getProxy(this.proxyClassLoader);  
    }  

通过上面的源码我们可以知道,对于代理的创建,Springle交给了proxyFactory的getProxy方法去完成,而之前的所有主要是为proxyFactory做了初始准备而已。

2.2.1 ProxyFactory.getProxy(classLoader)

public object getProxy(ClassLoader classLoader){
    return createAopProxy().getProxy(classLoader);
}

createAopProxy创建代理:

protected final synchronized AopProxy createAopProxy(){
    if(!this.active){activate();}
    return getAopProxyFactory().createAopProxy(this);
}

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()) {  
            return new JdkDynamicAopProxy(config);  
        }  
        return CglibProxyFactory.createCglibProxy(config);  
    }  
    else {  
        return new JdkDynamicAopProxy(config);  
    }  
}  

上述代码中的if判断主要是对代理的选择,使用JDK或者CGLIB实现代理,选择完以后就创建了代理。

  • **optimize:**CGLIB创建的代理是否使用激进策略。
  • proxyTargetClass:当XML配置文件设置了<aop:aspectj-autoproxy proxy-target-class="true"/>时为true,表示使用CGLIB
  • hasNoUserSuppliedProxyInterfaces:是否存在代理接口。

获得代理

我们以使用JDK获得代理做一下分析:
使用JDK方式最关键两个方法:invoke和getProxy。
getProxy:获得代理对象。
invoke:执行被代理对象的方法。
我们看一下JdkDynamicAopProxy的核心代码invoke方法:

public Object invoke(Object proxy, Method method, Object[] args) throwsThrowable {  
       MethodInvocation invocation = null;  
       Object oldProxy = null;  
       boolean setProxyContext = false;  

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

       try {  
           //eqauls()方法,具目标对象未实现此方法  
           if (!this.equalsDefined && AopUtils.isEqualsMethod(method)){  
                return (equals(args[0])? Boolean.TRUE : Boolean.FALSE);  
           }  

           //hashCode()方法,具目标对象未实现此方法  
           if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)){  
                return newInteger(hashCode());  
           }  

           //Advised接口或者其父接口中定义的方法,直接反射调用,不应用通知  
           if (!this.advised.opaque &&method.getDeclaringClass().isInterface()  
                    &&method.getDeclaringClass().isAssignableFrom(Advised.class)) {  
                // Service invocations onProxyConfig with the proxy config...  
                return AopUtils.invokeJoinpointUsingReflection(this.advised,method, args);  
           }  

           Object retVal = null;  

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

           //获得目标对象的类  
           target = targetSource.getTarget();  
           if (target != null) {  
                targetClass = target.getClass();  
           }  

           //获取当前方法的拦截链
           List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method,targetClass);  

           //如果没有可以应用到此方法的通知(Interceptor),此直接反射调用 method.invoke(target, args)  
           if (chain.isEmpty()) {  
                retVal = AopUtils.invokeJoinpointUsingReflection(target,method, args);  
           } else {  
                //创建MethodInvocation,封装拦截器链  
                invocation = newReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);  
                retVal = invocation.proceed();  
           }  

           // Massage return value if necessary.  
           if (retVal != null && retVal == target &&method.getReturnType().isInstance(proxy)  
                    &&!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {  
                // Special case: it returned"this" and the return type of the method  
                // is type-compatible. Notethat we can't help if the target sets  
                // a reference to itself inanother returned object.  
                retVal = proxy;  
           }  
           return retVal;  
       } finally {  
           if (target != null && !targetSource.isStatic()) {  
                // Must have come fromTargetSource.  
               targetSource.releaseTarget(target);  
           }  
           if (setProxyContext) {  
                // Restore old proxy.  
                AopContext.setCurrentProxy(oldProxy);  
           }  
       }  
    }  

1)获取拦截器:getInterceptorsAndDynamicInterceptionAdvice
2)判断拦截器链是否为空,如果是空的话直接调用切点方法
3)如果拦截器不为空的话那么便创建ReflectiveMethodInvocation类,把拦截器方法都封装在里面
4)对拦截器链中的拦截器逐一调用:invocation.proceed()

看一下proceed方法:

public Object proceed() throws Throwable {  
       //  We start with an index of -1and increment early.  
       if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size()- 1) {  
           //如果Interceptor执行完了,则执行joinPoint  
           return invokeJoinpoint();  
       }  
       //获得下一个拦截器interceptor
       Object interceptorOrInterceptionAdvice =  
           this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);  

       //如果要动态匹配joinPoint  
       if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher){  

           InterceptorAndDynamicMethodMatcher dm =  
                (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;  
           //动态匹配:运行时参数是否满足匹配条件  
           if (dm.methodMatcher.matches(this.method, this.targetClass,this.arguments)) {  
                //执行当前Intercetpor  
                returndm.interceptor.invoke(this);  
           }  
           else {  
                //动态匹配失败时,略过当前Intercetpor,调用下一个Interceptor  
                return proceed();  
           }  
       }  
       else {  
           //对于普通拦截器
           //执行当前Intercetpor  
           return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);  
       }  
}  

ReflectiveMethodInvocation中维护了拦截器调用的计数器,用来记录当前调用链接的位置,使得可以有序的对拦截器逐一调用。

实现Aop自动代理总结:

1.<aop:aspectj-autoproxy/>解析注册AnnotationAwareAspectJAutoProxyCreator类
2.AnnotationAwareAspectJAutoProxyCreator完成动态代理

AnnotationAwareAspectJAutoProxyCreator完成动态代理实现逻辑:
2.1.执行postProcessAfterInitialization()
———–如果适合代理就执行wrapIfNecessary()方法。

2.1.1wrapIfNecessary()实现逻辑:
1.判断是否需要生成代理
2.如果需要则调用getAdvicesAndAdvisorsForBean()方法获得当前类的advisor
3调用createProxy()创建代理。

2.1.1.2getAdvicesAndAdvisorsForBean()逻辑:
主要交给findEligibleAdvisors,实现逻辑:
—-1.findCandidateAdvisors找到所有的Advisors
—-2.findAdvisorsThatCanApply找到匹配当前bean的Advisors。

findCandidateAdvisors源码逻辑:
—-1.获得beanFactory中注册所有的BeanName
—-2.遍历所有BeanName,找出有@AspectJ的类
—-3.对有@AspectJ的类提取advisor
—-4.将提取出的结果放入缓存。

findAdvisorsThatCanApply源码逻辑:
—-从findCandidateAdvisors获得的advisor中寻找适合当前class的advisor。

2.1.1.3.调用createProxy()创建代理实现逻辑:
—-1.对ProxyFactory进行初始化
—-2.调用ProxyFactory.getProxy()创建代理

2.1.1.3.2.ProxyFactory.getProxy()实现逻辑:
调用 createAopProxy.getProxy(classLoader),逻辑如下
—-1.创建AopProxy:
——-对实现代理方式进行选择:JDK?CGLIB?
——-调用JdkDynamicAopProxy的构造方法获得代理。

JdkDynamicAopProxy的invoke方法:
1)获取拦截器:getInterceptorsAndDynamicInterceptionAdvice
2)判断拦截器链是否为空,如果是空的话直接调用切点方法
3)如果拦截器不为空的话那么便创建ReflectiveMethodInvocation类,把拦截器方法都封装在里面
4)对拦截器链中的拦截器逐一调用:invocation.proceed()

proceed()方法:ReflectiveMethodInvocation中维护了拦截器调用的计数器,用来记录当前调用链接的位置,使得可以有序的对拦截器逐一调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值