Spring源码阅读(三):AOP实现原理

AOP实现原理

1、切面(Aspect):面向规则,具有相同规则的方法的集合体。
2、通知(Advice):回调。
3、切入点(Pointcut):需要代理的具体方法。
4、目标对象(Target Object):被代理的对象。
5、AOP代理(AOP Proxy):主要有两种方式 JDK和CGLib。
6、前置通知(Before Advice):在invoke Pointcut之前调用、织入的方法。
7、后置通知(After Advice):Pointcut之后调用、织入的方法。
8、返回后通知(After Return Advice):返回值为非void的织入的方法。
9、环绕通知(Around Advice):只要触发调用,就织入的方法。
10、异常通知(After Throwing Advice):Pointcut抛出异常就织入的方法。

AOP的流程分三步:

  • 创建代理类
  • 代码织入(invoke)
  • 回调通知

创建代理类

AbstractAutowireCapableBeanFactory类中的doCreateBean()方法中,在populateBean()方法之后,有一个initializeBean()方法,初始化Bean对象用的:

//初始容器创建的Bean实例对象,为其添加BeanPostProcessor后置处理器
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
   //JDK的安全机制验证权限
   if (System.getSecurityManager() != null) {
      //实现PrivilegedAction接口的匿名内部类
      AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
         invokeAwareMethods(beanName, bean);
         return null;
      }, getAccessControlContext());
   }
   else {
      //为Bean实例对象包装相关属性,如名称,类加载器,所属容器等信息
      invokeAwareMethods(beanName, bean);
   }

   Object wrappedBean = bean;
   //对BeanPostProcessor后置处理器的postProcessBeforeInitialization
   //回调方法的调用,为Bean实例初始化前做一些处理
   if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }

   //调用Bean实例对象初始化的方法,这个初始化方法是在Spring Bean定义配置
   //文件中通过init-method属性指定的
   try {
      invokeInitMethods(beanName, wrappedBean, mbd);
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null),
            beanName, ""Invocation of init method failed"", ex);
   }
   //对BeanPostProcessor后置处理器的postProcessAfterInitialization
   //回调方法的调用,为Bean实例初始化之后做一些处理
   if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }

   return wrappedBean;
}

直接看bean初始化后的回调处理方法:applyBeanPostProcessorsAfterInitialization();

在这个方法,进入postProcessAfterInitialization()方法。此处会有多个类可以选择,我们选择AbstractAutoProxyCreator类:

进入这个方法:

@Override
public Object postProcessAfterInitialization(@Nullable 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;
}

这个方法return了另一个方法wrapIfNecessary(),顾名思义,需要包装这个bean的时候才包装:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
   if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
      return bean;
   }

   // 判断是否不应该代理这个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;
   }

   // 获取这个bean的advice
   // Create proxy if we have advice.
   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;
}

前面一段是用来判断这个bean是否需要包装,后面的createProxy()就是创建代理了。首先通过getAdvicesAndAdvisorsForBean()方法,获取这个bean附带了哪些通知advice,获取这个bean的advice后,才能创建代理。

if (specificInterceptors != DO_NOT_PROXY)

DO_NOT_PROXY定义为null,这句话表示如果这个bean没有任何的通知,则不创建代理。

进入getAdvicesAndAdvisorsForBean()方法:(AbstractAdvisorAutoProxyCreator类)

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

进入findEligibleAdvisors()方法:

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
   List<Advisor> candidateAdvisors = findCandidateAdvisors();
   List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
   extendAdvisors(eligibleAdvisors);
   if (!eligibleAdvisors.isEmpty()) {
      eligibleAdvisors = sortAdvisors(eligibleAdvisors);
   }
   return eligibleAdvisors;
}

来看一下对advice的排序动作:

protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
   AnnotationAwareOrderComparator.sort(advisors);
   return advisors;
}

通过比较器AnnotationAwareOrderComparator的排序规则来排序。

回到findEligibleAdvisors(Class<?> beanClass, String beanName)方法,通过这个方法的参数:Class<?> beanClass, String beanName,可以知道这个方法只能得到的是bean类有哪些advice,还不知道这个类具体是什么方法有advice。

现在我们获取到了这个bean的List\<Advisor>,回到AbstractAutowireCapableBeanFactory类的wrapIfNecessary()方法,看它的createProxy()方法:
这个方法主要通过proxyFactory.getProxy(getProxyClassLoader())这句话来创建代理,进入ProxyFactory的getProxy()方法:

public Object getProxy(@Nullable ClassLoader classLoader) {
   return createAopProxy().getProxy(classLoader);
}

进入createAopProxy()方法:

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

再进入createAopProxy(this),来到了DefaultAopProxyFactory类:

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);
   }
}

这个方法用以判断是用JDK方式还是用Cglib方式生成代理。

  if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
     return new JdkDynamicAopProxy(config);
  }
  return new ObjenesisCglibAopProxy(config);

这一段表示,当这个类是一个接口,或者是一个代理类时,使用的是JDK的动态代理,否则使用Cglib动态代理。返回的是JdkDynamicAopProxy或者CglibAopProxy,这两个统一implements了AopProxy,所以createAopProxy()方法返回的就是AopProxy

先来看一下JdkDynamicAopProxygetProxy()方法:

public Object getProxy(@Nullable ClassLoader classLoader) {
   if (logger.isDebugEnabled()) {
      logger.debug(""Creating JDK dynamic proxy: target source is "" + this.advised.getTargetSource());
   }
   Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
   findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
   return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

来看Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);,这个方法有三个参数:

public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
    throws IllegalArgumentException

这个方法有三个参数:

  • loader:用哪个类加载器去加载代理对象

  • interfaces:动态代理类需要实现的接口

  • h:动态代理方法在执行时,会调用h里面的invoke方法去执行

这个方法就是用于为指定类装载器、一组接口及调用处理器生成动态代理类实例的方法。通过这个方法,我们生成了一个代理类。


代码织入(invoke)

代理类生成之后,就需要对其方法进行织入。主要有两个组件:

  • Intercepter:拦截器,责任链的组件,invoke();
  • Invocation:调用器,调用通知回调的组件,proceed(),执行这个拦截器里的方法。

JdkDynamicAopProxy为例,JdkDynamicAopProxy实现了InvocationHandler接口,重写了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;
   Object target = null;

   try {
       //如果没有重写equals()方法
      if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
         // The target does not implement the equals(Object) method itself.
         return equals(args[0]);
      }
      else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
         // The target does not implement the hashCode() method itself.
         return hashCode();
      }
      else if (method.getDeclaringClass() == DecoratingProxy.class) {
         // There is only getDecoratedClass() declared -> dispatch to proxy config.
         return AopProxyUtils.ultimateTargetClass(this.advised);
      }
      //Advised接口或者其父接口中定义的方法,直接反射调用,不应用通知
      else 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;
      }

      // Get as late as possible to minimize the time we ""own"" the target,
      // in case it comes from a pool.
      //获得目标对象的类
      target = targetSource.getTarget();
      Class<?> targetClass = (target != null ? target.getClass() : null);

      // Get the interception chain for this method.
      //获取可以应用到此方法上的Interceptor列表
      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.
      //如果没有可以应用到此方法的通知(Interceptor),此直接反射调用 method.invoke(target, args)
      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);
         retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
      }
      else {
         // We need to create a method invocation...
         //创建MethodInvocation
         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 != Object.class && 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);
      }
   }
}

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
这句话获取到了这个通知的拦截器链chain(责任链)。

进入这个getInterceptorsAndDynamicInterceptionAdvice()方法:

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
   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获取所有拦截器。

若这个chain不为空,则执行:
retVal = invocation.proceed();
进入proceed()方法(ReflectiveMethodInvocation类):

public Object proceed() throws Throwable {
   // We start with an index of -1 and increment early.
      //如果Interceptor执行完了,则执行joinPoint
      if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
         return invokeJoinpoint();
      }

      Object interceptorOrInterceptionAdvice =
            this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
      //如果要动态匹配joinPoint
      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)) {
            return dm.interceptor.invoke(this);
         }
         else {
            // Dynamic matching failed.
            // Skip this interceptor and invoke the next in the chain.
            //动态匹配失败时,略过当前Intercetpor,调用下一个Interceptor
            return proceed();
         }
   }
   else {
      // It's an interceptor, so we just invoke it: The pointcut will have
      // been evaluated statically before this object was constructed.
      //执行当前Intercetpor
      return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
   }
}

首先判断这次执行的下标(currentInterceptorIndex)是不是责任链的最后一个,若是则执行invokeJoinpoint(),若不是则往下执行(++currentInterceptorIndex)。

然后后判断是不是一个Interceptor,若不是,则继续下一个proceed();若是,则调用dm.interceptor.invoke(this)(interceptor此时是封装在InterceptorAndDynamicMethodMatcher即dm中,所以调用dm的interceptor的invoke方法),这个invoke(this)每次会将this即ReflectiveMethodInvocation对象作为参数传入,以便在方法结束后回到proceed()方法。

进入invoke方法,会出现许多类,我们选择其中一个例如MethodBeforeAdviceInterceptor(before)的invoke方法:

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
   this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
   return mi.proceed();
}

调用advice的before()方法,再调用proceed()。

换after的方法例如AfterReturningAdviceInterceptor的invoke()看一下:

public Object invoke(MethodInvocation mi) throws Throwable {
   Object retVal = mi.proceed();
   this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
   return retVal;
}

此时,先进行proceed()之后再调用advice的after方法。

再来看看异常通知After Throwing Advice,例如ThrowsAdviceInterceptor的invoke():

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;
   }
}

此时代码会在catch里执行。

时序图:

文章已创建 17

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部