AOP执行增强-Spring 源码系列(5)

AOP增强实现-Spring 源码系列(5)

目录:

Ioc容器beanDefinition-Spring 源码(1)

Ioc容器依赖注入-Spring 源码(2)

Ioc容器BeanPostProcessor-Spring 源码(3)

事件机制-Spring 源码(4)

AOP执行增强-Spring 源码系列(5)

AOP的核心就是个动态代理,Spring进行了大量抽象和封装形成一个方便上层使用的基础模块。

而动态代理的两种实现都在上一篇中提供了代码

直接ProxyFactoryBean入手来看Spring是如何产生这个代理对象的:

ProxyFactoryBean中getObject 作为入口:

    //获得代理
    //需要对target的增强都在这个入口里处理完成
    public Object getObject() throws BeansException {
      // 初始化通知链
        initializeAdvisorChain();
        // 默认单例
        if (isSingleton()) {
            return getSingletonInstance();
        }
        else {
            if (this.targetName == null) {
                logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
                        "Enable prototype proxies by setting the ‘targetName‘ property.");
            }
            return newPrototypeInstance();
        }
    }

singletonInstance缓存单例:

private synchronized Object getSingletonInstance() {
    //
        if (this.singletonInstance == null) {
            this.targetSource = freshTargetSource();
            if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
                // Rely on AOP infrastructure to tell us what interfaces to proxy.
                Class<?> targetClass = getTargetClass();
                if (targetClass == null) {
                    throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
                }
                // 存住target继承的全部接口 ClassUtils api getAllInterfacesForClass
                setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
            }
            // Initialize the shared singleton instance.
            super.setFrozen(this.freezeProxy);
            // 这里createAopProxy产生一个AopProxy,在spring中的两个AopProxy实现你已经猜到了吧
            this.singletonInstance = getProxy(createAopProxy());
        }
        return this.singletonInstance;
    }
    // AopProxyFactory里去做了一个区分是用jdk的还是cglib
    protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        // 默认DefaultAopProxyFactory
        return getAopProxyFactory().createAopProxy(this);
    }
    

DefaultAopProxyFactory实现,这个方法参数需要AdvisedSupport,在上面的调用代码上传的是this,因为它也继承了AdvisedSupport:

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.");
            }
            // 有接口就用jdk方式
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }

再回去看getProxy方法:

public Object getProxy() {
// 调用JdkDynamicAopProxy 或 ObjenesisCglibAopProxy的getProxy方法
return createAopProxy().getProxy();
}

这里就只看一下JdkDynamicAopProxy实现,两者最终目的相同:

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);
   // 筛选Equals方法和HashCode方法
   findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
   // 这个代码就熟悉了 调用newProxyInstance方法,最后传入的InvocationHandler是this,那么JdkDynamicAopProxy继承InvocationHandler,实现了invoke方法,增强都在这个方法里做文章
   return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

invoke方法:

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

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

   try {
      if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
         // The target does not implement the equals(Object) method itself.
         return equals(args[0]);
      }
      if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
         // The target does not implement the hashCode() method itself.
         return hashCode();
      }
      if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
            method.getDeclaringClass().isAssignableFrom(Advised.class)) {
         // Service invocations on ProxyConfig with the proxy config...
         return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
      }

      Object retVal;

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

      // May be null. Get as late as possible to minimize the time we "own" the target,
      // in case it comes from a pool.
      target = targetSource.getTarget();
      if (target != null) {
         targetClass = target.getClass();
      }

      // Get the interception chain for this method.
      // 拦截器链
      List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

      // Check whether we have any advice. If we don‘t, we can fallback on direct
      // reflective invocation of the target, and avoid creating a MethodInvocation.
      if (chain.isEmpty()) {
         // We can skip creating a MethodInvocation: just invoke the target directly
         // Note that the final invoker must be an InvokerInterceptor so we know it does
         // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
         Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
         // 使用AopUtils直接使用反射机制调用目标方法
         retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
      }
      else {
         // We need to create a method invocation...
         invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
         // Proceed to the joinpoint through the interceptor chain.
         // 执行拦截器链
         retVal = invocation.proceed();
      }

      // Massage return value if necessary.
      Class<?> returnType = method.getReturnType();
      if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
            !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
         // Special case: it returned "this" and the return type of the method
         // is type-compatible. Note that we can‘t help if the target sets
         // a reference to itself in another returned object.
         retVal = proxy;
      }
      else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
         throw new AopInvocationException(
               "Null return value from advice does not match primitive return type for: " + method);
      }
      return retVal;
   }
   finally {
      if (target != null && !targetSource.isStatic()) {
         // Must have come from TargetSource.
         targetSource.releaseTarget(target);
      }
      if (setProxyContext) {
         // Restore old proxy.
         AopContext.setCurrentProxy(oldProxy);
      }
   }
}

以上已经调用到增强部分的拦截器链,这些拦截器被调用由ReflectiveMethodInvocation来完成:

public Object proceed() throws Throwable {
        //    We start with an index of -1 and increment early.
        // 拦截器都被执行完成,跳出递归
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return invokeJoinpoint();
        }

        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        // 分两种拦截器:InterceptorAndDynamicMethodMatcher 和 MethodInterceptor
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            // Evaluate dynamic method matcher here: static part will already have
            // been evaluated and found to match.
            // 匹配一遍拦截器
            InterceptorAndDynamicMethodMatcher dm =
                    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
              // 执行拦截器的invoke方法
                return dm.interceptor.invoke(this);
            }
            else {
                // Dynamic matching failed.
                // Skip this interceptor and invoke the next in the chain.
                // 递归调用
                return proceed();
            }
        }
        else {
            // It‘s an interceptor, so we just invoke it: The pointcut will have
            // been evaluated statically before this object was constructed.
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

其中调用目标方法的方式采用反射方式具体调用代码值得阅读,实际场景中可以借鉴:

protected Object invokeJoinpoint() throws Throwable {
   return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}
public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)
      throws Throwable {

   // Use reflection to invoke the method.
   try {
      ReflectionUtils.makeAccessible(method);
      return method.invoke(target, args);
   }
   catch (InvocationTargetException ex) {
      // Invoked method threw a checked exception.
      // We must rethrow it. The client won‘t see the interceptor.
      throw ex.getTargetException();
   }
   catch (IllegalArgumentException ex) {
      throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
            method + "] on target [" + target + "]", ex);
   }
   catch (IllegalAccessException ex) {
      throw new AopInvocationException("Could not access method [" + method + "]", ex);
   }
}

到这里,基本流通了一个代理类如何产生,实际增强执行,和目标方法最终被调用的流程,增强如何轻松配置的呢?

Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);

拦截器是叫interceptorsAndDynamicMethodMatchers的list在前面invoke方法中取得:

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

调用基类AdvisedSupport方法:

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
  // 这里对缓存的key做了封装
   MethodCacheKey cacheKey = new MethodCacheKey(method);
   List<Object> cached = this.methodCache.get(cacheKey);
   if (cached == null) {
      cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
            this, method, targetClass);
      this.methodCache.put(cacheKey, cached);
   }
   return cached;
}

advisorChainFactory 通知器链工厂

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
      Advised config, 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<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
   Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
   boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
   AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
   // config.getAdvisors来自ioc容器的组装,也就是通过xml配置,注解等元数据来描述的通知器
   for (Advisor advisor : config.getAdvisors()) {
      if (advisor instanceof PointcutAdvisor) {
         // Add it conditionally.
         PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
         if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
           // 通知器转变成拦截器,拦截器才是执行链路上可以直接用于增强的
            MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
            MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
            // 匹配规则在Pointcut里
            if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
               if (mm.isRuntime()) {
                  // Creating a new object instance in the getInterceptors() method
                  // isn‘t a problem as we normally cache created chains.
                  for (MethodInterceptor interceptor : interceptors) {
                     interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                  }
               }
               else {
                  interceptorList.addAll(Arrays.asList(interceptors));
               }
            }
         }
      }
      else if (advisor instanceof IntroductionAdvisor) {
         IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
         if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
            Interceptor[] interceptors = registry.getInterceptors(advisor);
            interceptorList.addAll(Arrays.asList(interceptors));
         }
      }
      else {
         Interceptor[] interceptors = registry.getInterceptors(advisor);
         interceptorList.addAll(Arrays.asList(interceptors));
      }
   }

   return interceptorList;
}

将advisor转化成拦截器在DefaultAdvisorAdapterRegistry中完成:

public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
   List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
   Advice advice = advisor.getAdvice();
   if (advice instanceof MethodInterceptor) {
      interceptors.add((MethodInterceptor) advice);
   }
   // 遍历全部适配器,调用supportsAdvice方法
   for (AdvisorAdapter adapter : this.adapters) {
      if (adapter.supportsAdvice(advice)) {
         interceptors.add(adapter.getInterceptor(advisor));
      }
   }
   if (interceptors.isEmpty()) {
      throw new UnknownAdviceTypeException(advisor.getAdvice());
   }
   return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
}

这里使用了适配器模式,也是spring中经常拿来做例子的代码,因为非常清晰。

我们可以查看DefaultAdvisorAdapterRegistry的代码发现默认只有三个适配器:

MethodBeforeAdviceAdapter
AfterReturningAdviceAdapter
ThrowsAdviceAdapter

对应这三个Advice

MethodBeforeAdvice
AfterReturningAdvice
ThrowsAdvice

转变的三个拦截器:

MethodBeforeAdviceInterceptor
AfterReturningAdviceInterceptor
ThrowsAdviceInterceptor

而在前面的流程中调用到拦截器的入口在ReflectiveMethodInvocation的interceptor.invoke(this)方法,这三个拦截器的invoke方法如下:

public Object invoke(MethodInvocation mi) throws Throwable {
   this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
   return mi.proceed();
}
public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
   Assert.notNull(advice, "Advice must not be null");
   this.advice = advice;
}
public Object invoke(MethodInvocation mi) throws Throwable {
   try {
      return mi.proceed();
   }
   catch (Throwable ex) {
      Method handlerMethod = getExceptionHandler(ex);
      if (handlerMethod != null) {
         invokeHandlerMethod(mi, ex, handlerMethod);
      }
      throw ex;
   }
}

注意mi.proceed();的执行位置,这里继续递归了ReflectiveMethodInvocation的interceptor.invoke(this)方法

那么这个代码最终就可以实现一个执行链:

这样就明白了如何在目标方法执行后再执行配置的增强业务代码,我个人觉得这个递归的实现是整个串联执行链路的核心了,不得不说递归的写法非常简洁而高效。

另外我们一定使用过spring环绕增强,根据上面的分析,那它也只要继承MethodBeforeAdvice,AfterReturningAdvice两者即可实现。

时间: 2024-09-29 08:57:22

AOP执行增强-Spring 源码系列(5)的相关文章

Spring源码系列 — BeanDefinition扩展点

前言 前文介绍了Spring Bean的生命周期,也算是XML IOC系列的完结.但是Spring的博大精深,还有很多盲点需要摸索.整合前面的系列文章,从Resource到BeanDefinition,再到容器扩展点,最后到Bean创键,这个过程中无处不存在Spring预留的扩展口. 本篇文章介绍Spring的另一种扩展点:BeanDefinition扩展点,该扩展点是为处理BeanDefinition而设计.本文主要从以下几点分析: BeanDefinition扩展点的几种方式 BeanDef

spring源码系列——spring循环引用

众所周知spring在默认单例的情况下是支持循环引用的 Appconfig.java类的代码 @Configurable@ComponentScan("com.shadow")public class Appconfig {}1234X.java类的代码 package com.shadow.service; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.

Spring源码系列:BeanFactory的创建

Spring的Ioc容器其实就是一个bean的关系网,依赖于core,bean,context三个组件来构建的.在spring中最核心的就是对于bean的管理.而bean又依托于我们的容器.本文将从顶层分析一下spring中beanFactory的具体创建过程,为后续的bean的生命周期提供一个基础. BeanFactory的继承体系 图片描述(最多50字) 从上图可以看到,BeanFactory有三个子类:ListableBeanFactoryHierarchicalBeanFactoryAu

死磕Spring源码系列

一.Spring总体架构 1.架构图 2.SpringIOC:核心容器提供 Spring 框架的基本功能.核心容器的主要组件是 BeanFactory,它是工厂模式的实现.BeanFactory 使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开. 3.SpringAOP:通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中.所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP.Spring AOP 模块为

Spring核心框架 - AOP的原理及源码解析

一.AOP的体系结构 如下图所示:(引自AOP联盟) 层次3语言和开发环境:基础是指待增加对象或者目标对象:切面通常包括对于基础的增加应用:配置是指AOP体系中提供的配置环境或者编织配置,通过该配置AOP将基础和切面结合起来,从而完成切面对目标对象的编织实现. 层次2面向方面系统:配置模型,逻辑配置和AOP模型是为上策的语言和开发环境提供支持的,主要功能是将需要增强的目标对象.切面和配置使用AOP的API转换.抽象.封装成面向方面中的逻辑模型. 层次1底层编织实现模块:主要是将面向方面系统抽象封

spring源码剖析(六)AOP实现原理剖析

Spring的AOP实现原理,酝酿了一些日子,写博客之前信心不是很足,所以重新阅读了一边AOP的实现核心代码,而且又从网上找了一些Spring Aop剖析的例子,但是发现挂羊头买狗肉的太多,标题高大上,内容却大部分都是比较浅显的一些介绍,可能也是由于比较少人阅读这部分的核心代码逻辑把,然后写这部分介绍的人估计也是少之又少,不过说实话,Spring Aop的核心原理实现介绍确实不太好写,里面涉及的类之间的调用还是蛮多的,关系图画的太细的画也很难画,而且最重要的一点就是,如果对AOP的概念以及spr

【Spring源码分析】AOP源码解析(上篇)

前言 前面写了六篇文章详细地分析了Spring Bean加载流程,这部分完了之后就要进入一个比较困难的部分了,就是AOP的实现原理分析.为了探究AOP实现原理,首先定义几个类,一个Dao接口: 1 public interface Dao { 2 3 public void select(); 4 5 public void insert(); 6 7 } Dao接口的实现类DaoImpl: 1 public class DaoImpl implements Dao { 2 3 @Overrid

Spring源码阅读:Spring AOP设计与实现(一):动态代理

在Spring的有两个核心:IOC与AOP,AOP又是基于动态代理模式实现的.所以要了解SpringAOP是如何设计的之前,还是先了解一下Java中的动态代理比较好. 认识代理模式 代理模式是这么描述的: 代理模式是为其他对象提供一种代理以控制对这个对象的访问 代理对象的功能: 通过创建一个代理对象,用这个代理对象去代理真实的对象,客户端得到这个代理对象后,对客户端并没有什么影响,就跟真实的对象一样(因为代理对象和真是对象实现了同一接口). 下面看看代理模式的类图: 解说: RealSubjec

Spring源码阅读:使用标准AOP的API模拟Spring AOP + AspectJ的设计与实现

在上一篇博客中,提到了标准AOP与Spring AOP.这一篇就来把他们模拟出来. 在模拟之前,还需要提及的是,在Spring框架中,对于AOP的支持: Spring 支持的AOP AspectJ是另外一个有名的AOP框架,Spring也集成AspectJ,同时Spring AOP与AspectJ有一定程度的集成,这样一来Spring中就支持两种AOP:1)Spring AOP.2)AspectJ.而使用AOP的方式却又三种: 1)完全使用Spring AOP 2)完全使用AspectJ(分为注