Spring学习10-- AOP实现原理

来源:互联网 发布:网络拓扑画图软件 编辑:程序博客网 时间:2024/05/18 14:28

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
原创粉丝点击