Spring学习10-- AOP实现原理

AOP的原理不需要多讲,动态代理。那么,Spring在bean对象实例化的时候,是如何动态代理一个类的呢?又是如何完成方法织入的呢,来看一看源码。

1、AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsBeforeInstantiation
翻开Spring学习08的内容,里面有讲到后置处理器BeanPostProcessor的实现原理,在给Bean实例化的过程中,调用了该类中的ceaterBean方法,里面有处理后置处理器的入口函数的调用

// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
if (beanClass != null && !mergedBeanDefinition.isSynthetic()) {
//bean对象初始化之前的处理入口
Object bean = applyBeanPostProcessorsBeforeInstantiation(beanClass, beanName);
    if (bean != null) {
    //bean对象初始化之后的处理入口
        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
        return bean;
    }
}

以applyBeanPostProcessorsAfterInitialization为例子,进入该方法

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)  
           throws BeansException {  
       Object result = existingBean;  
       //遍历容器为所创建的Bean添加的所有BeanPostProcessor后置处理器  
       for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {  
           //调用Bean实例所有的后置处理中的初始化后处理方法,为Bean实例对象在  
           //初始化之后做一些自定义的处理操作  
           result = beanProcessor.postProcessAfterInitialization(result, beanName);  
           if (result == null) {  
               return result;  
           }  
       }  
       return result;  
    }

真正处理的方法是postProcessAfterInitialization,继续进去看看,AbstractAutowireCapableBeanFactory类中并没有实现这个方法,查看一下子类,真正实现的地方在AbstractAutoProxyCreator

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (isInfrastructureClass(bean.getClass(), beanName) || shouldSkip(bean.getClass(), beanName)) {
            return bean;
        }

        // Create proxy if we have advice.
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            //创建代理
            return createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        }

        return bean;
    }

真正创建代理的地方入口就在这里,进入createProxy

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

        // handle prototypes correctly
        //获取所有的advisor, Advisor:充当Advice和Pointcut的适配器,类似使用Aspect的@Aspect注解的类(前一章节所//述)。一般有advice和pointcut属性
        Advisor[] commonInterceptors = resolveInterceptorNames();

        List allInterceptors = new ArrayList();
        if (specificInterceptors != null) {
            allInterceptors.addAll(Arrays.asList(specificInterceptors));
            if (commonInterceptors != null) {
                if (this.applyCommonInterceptorsFirst) {
                    allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
                }
                else {
                    allInterceptors.addAll(Arrays.asList(commonInterceptors));
                }
            }
        }
        if (logger.isDebugEnabled()) {
            int nrOfCommonInterceptors = commonInterceptors != null ? commonInterceptors.length : 0;
            int nrOfSpecificInterceptors = specificInterceptors != null ? specificInterceptors.length : 0;
            logger.debug(
                    "Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
                    " common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
        }

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

        if (!isProxyTargetClass()) {
            // Must allow for introductions; can't just set interfaces to
            // the target's interfaces only.
            Class[] targetsInterfaces = ClassUtils.getAllInterfacesForClass(beanClass);
            for (int i = 0; i < targetsInterfaces.length; i++) {
                proxyFactory.addInterface(targetsInterfaces[i]);
            }
        }

        for (Iterator it = allInterceptors.iterator(); it.hasNext();) {
            Advisor advisor = this.advisorAdapterRegistry.wrap(it.next());
            proxyFactory.addAdvisor(advisor);
        }
        proxyFactory.setTargetSource(targetSource);
        customizeProxyFactory(proxyFactory);

        proxyFactory.setFrozen(this.freezeProxy);
        //返回代理对象
        return proxyFactory.getProxy();
    }

正在返回代理的地方就是最后的getProxy()方法,进入,但是类中没有实现,在子类JdkDynamicAopProxy中有了实现

/** 
    * <ol> 
    * <li>获取代理类要实现的接口,除了Advised对象中配置的,还会加上SpringProxy, Advised(opaque=false) 
    * <li>检查上面得到的接口中有没有定义 equals或者hashcode的接口 
    * <li>调用Proxy.newProxyInstance创建代理对象 
    * </ol> 
    */  
   public Object getProxy(ClassLoader classLoader) {  
       if (logger.isDebugEnabled()) {  
           logger.debug("Creating JDK dynamic proxy: target source is " +this.advised.getTargetSource());  
       }  
       Class[] proxiedInterfaces =AopProxyUtils.completeProxiedInterfaces(this.advised);  
       findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);  
       return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);  
}  

这样一个过程下来,一个代理对象就产生了,但是问题又来了,这个对象是如何工作的,也就是说,是如何织入的呢?

2、织入过程
上面说到类JdkDynamicAopProxy中geyProxy方法产生了一个代理对象,我们在动态代理中说过,动态代理最重要的地方就是实现InvocationHandler接口,其中invoke函数是代理生效的方法,正好,类JdkDynamicAopProxy就实现了这个接口,来找一下invoke方法,看里面做了写什么。

//AOP代理对象的回调方法  
publicObject invoke(Object proxy, Method method, Object[] args) throws Throwable {  
MethodInvocationinvocation;  
ObjectoldProxy = null;  
booleansetProxyContext = false;  
//获取通知的目标源  
TargetSourcetargetSource = this.advised.targetSource;  
ClasstargetClass = null;  
Objecttarget = null;  
try{  
//如果代理目标对象的接口中没有定义equals()方法,且当前调用的方法  
//是equals()方法,即目标对象没有自己实现equals()方法  
if(!this.equalsDefined && AopUtils.isEqualsMethod(method)) {  
returnequals(args[0]);  
}  
//如果代理目标对象的接口中没有定义hashCode()方法,且当前调用的方法  
//是hashCode()方法,即目标对象没有自己实现hashCode()方法  
if(!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {  
returnhashCode();  
}  
//如果AOP配置了通知,使用反射机制调用通知的同名方法  
if(!this.advised.opaque && method.getDeclaringClass().isInterface()&&                                method.getDeclaringClass().isAssignableFrom(Advised.class)){  
returnAopUtils.invokeJoinpointUsingReflection(this.advised, method, args);  
}  
ObjectretVal;  
//如果当前通知暴露了代理,则将当前代理使用currentProxy()方法变为可用代理  
if(this.advised.exposeProxy) {  
oldProxy= AopContext.setCurrentProxy(proxy);  
setProxyContext= true;  
}  
//获取目标对象  
target= targetSource.getTarget();  
if(target != null) {  
targetClass= target.getClass();  
}  
//获取目标对象方法配置的拦截器(通知器)链  
List<Object>chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method,targetClass);  
//如果没有配置任何通知  
if(chain.isEmpty()) {  
//没有配置通知,使用反射直接调用目标对象的方法,并获取方法返回值  
retVal= AopUtils.invokeJoinpointUsingReflection(target, method, args);  
}  
//如果配置了通知  
else{  
//为目标对象创建方法回调对象,需要在调用通知之后才调用目标对象的方法  
invocation= new ReflectiveMethodInvocation(proxy, target, method, args, targetClass,chain);  
//调用通知链,沿着通知器链调用所有配置的通知  
retVal= invocation.proceed();  
}  
//如果方法有返回值,则将代理对象最为方法返回  
if(retVal != null && retVal == target &&method.getReturnType().isInstance(proxy) &&  
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())){  
retVal= proxy;  
}  
returnretVal;  
}  
finally{  
if(target != null && !targetSource.isStatic()) {  
//释放目标对象  
targetSource.releaseTarget(target);  
}  
if(setProxyContext) {  
//存储代理对象  
AopContext.setCurrentProxy(oldProxy);  
}  
}  
}

过程如下:
1、Advised接口或者其父接口中定义的方法,直接反射调用,不应用通知
2、获取可以应用到此方法上的通知链(Interceptor Chain),如果有,则应用通知,并执行joinpoint; 如果没有,则直接反射执行joinpoint

获取通知链的过程getInterceptorsAndDynamicInterceptionAdvice,进入查看一下。这个方法在子类中实现。

    public List getInterceptorsAndDynamicInterceptionAdvice(
            Advised config, Object proxy, Method method, Class targetClass) {

        List cached = (List) this.methodCache.get(method);
        if (cached == null) {
            // recalculate
            cached = AdvisorChainFactoryUtils.calculateInterceptorsAndDynamicInterceptionAdvice(
                    config, proxy, method, targetClass);
            this.methodCache.put(method, cached);
        }
        return cached;
    }

实际调用的是calculateInterceptorsAndDynamicInterceptionAdvice,进入查看

/**
     * Return the static interceptors and dynamic interception advice that may apply
     * to this method invocation.
     * @return list of MethodInterceptor and InterceptionAdvice (if there's a dynamic
     * method matcher that needs evaluation at runtime)
     */
    public static List calculateInterceptorsAndDynamicInterceptionAdvice(
            Advised config, Object proxy, Method method, Class targetClass) {

        // this is somewhat tricky... we have to process introductions first,
        // but we need to preserve order in the ultimate list.
        List interceptorList = new ArrayList(config.getAdvisors().length);
        boolean hasIntroductions = hasMatchingIntroductions(config,targetClass);
        AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
        for (int i = 0; i < config.getAdvisors().length; i++) {
            Advisor advisor = config.getAdvisors()[i];
            if (advisor instanceof PointcutAdvisor) {
                // add it conditionally
                PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
                if (pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) {
                    Interceptor[] interceptors = registry.getInterceptors(advisor);
                    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                    if (methodMatches(mm,method, targetClass,hasIntroductions)) {
                        if (mm.isRuntime()) {
                            // Creating a new object instance in the getInterceptors() method
                            // isn't a problem as we normally cache created chains.
                            for (int j = 0; j < interceptors.length; j++) {
                                interceptorList.add(new InterceptorAndDynamicMethodMatcher((MethodInterceptor) interceptors[j], mm));
                            }
                        }
                        else {
                            interceptorList.addAll(Arrays.asList(interceptors));
                        }
                    }
                }
            }
            else if (advisor instanceof IntroductionAdvisor) {
                IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
                if (ia.getClassFilter().matches(targetClass)) {
                    Interceptor[] interceptors = registry.getInterceptors(advisor);
                    interceptorList.addAll(Arrays.asList(interceptors));
                }
            }
        }
        return interceptorList;
    }

这个方法的作用就是
* 从提供的配置实例config中获取advisor列表,遍历处理这些advisor.如果是IntroductionAdvisor,
* 则判断此Advisor能否应用到目标类targetClass上.如果是PointcutAdvisor,则判断
* 此Advisor能否应用到目标方法method上.将满足条件的Advisor通过AdvisorAdaptor转化成Interceptor列表返回.
调用此方法获取目标对象方法配置的拦截器(通知器)链 。

返回上一层代码,查看一下拦截器链是怎么起作用的

JdkDynamicAopProxy 和CglibAopProxy创建AOPProxy代理对象,以及对目标对象的通知器回调我们了解到,当目标对象配置了通知器时,在对目标对象方法调用前首先需要回调通知器链,JdkDynamicAopProxy和CglibAopProxy都是通过将目标对象方法、方法参数、和通知器链、代理对象等封装为ReflectiveMethodInvocation类,然后通过ReflectiveMethodInvocation.proceed()方法调用通知器链
proceed方法源码如下

//通用通知器链
public Object proceed() throws Throwable {
//如果拦截器链中通知已经调用完毕
if(this.currentInterceptorIndex ==this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//这个方法调用AopUtils.invokeJoinpointUsingReflection方法,
//通过反射机制直接调用目标对象方法
returninvokeJoinpoint();
}
//获取拦截器链中的通知器或通知
ObjectinterceptorOrInterceptionAdvice=           this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//如果获取的通知器或通知是动态匹配方法拦截器类型
if(interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher){
//动态匹配方法拦截器
InterceptorAndDynamicMethodMatcherdm =
    (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
if(dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
//如果匹配,调用拦截器的方法
returndm.interceptor.invoke(this);
}
else{
//如果不匹配,递归调用proceed()方法,知道拦截器链被全部调用为止
returnproceed();
}
}
else{
//如果不是动态匹配方法拦截器,则切入点在构造对象之前进行静态匹配,调用
//拦截器的方法
return((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}

总结一下
1、AOP创建代理对象通过ProxyFactory创建的。
2、JdkDynamicAopProxy通过JDK提供的动态代理创建代理类,实现方式有两种一种是jdk的动态代理,如果没有实现接口,则使用CGLIB字节码技术生成代理类。
3、代理类创建通过invoke方法调用,主要是获取目标对象方法、方法参数、和通知器链、代理对象等。
4、将上述获取到的目标对象数据封装为ReflectiveMethodInvocation类,然后通过ReflectiveMethodInvocation.proceed()方法调用通知器链。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值