Spring AOP原理 应用增强创建代理

以下源代码基于Spring aop 5.2.0

经过上篇的长篇大论分析Spring AOP原理 收集切面和实例化增强器_Alan CGH的博客-CSDN博客,我们知道了Spring是如何收集切面类并把其中的增强方法封装成增强器的。然后筛选出适用于bean的增强器数组返回。其实上一篇写的太过细节了,本篇不会再深入细节,重点放在逻辑流程上。

整个AOP代理对象的工作入口发生于AbstractAutoProxyCreator类,它同时是InstantiationAwareBeanPostProcessor,在bean的加载过程中的bean实例化前,resolveBeforeInstantion()逻辑中触发AutoProxyCreator的后置处理。所以线程会执行到这里来。在对bean收集到可适用的增强器后就是创建代理对象的工作。

1. AutoProxyCreator.getAdvicesAndAdvisorsForBean() 之后,创建代理对象

protected ob<x>ject wrapIfNecessary(ob<x>ject bean String beanName ob<x>ject cacheKey) {
   if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(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;
   }
   // 拿到一堆适用于bean的增强器,这回跑不掉了,要创建代理对象返回。
   ob<x>ject[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass() beanName null);
   if (specificInterceptors != DO_NOT_PROXY) {
      this.advisedBeans.put(cacheKey Boolean.TRUE);
        // 1.1 根据用户配置选择合适的代理策略
      ob<x>ject 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.1 将增强器转成统一的Advisor接口。初始化ProxyFactory对象,用它选择代理策略创建代理。

protected ob<x>ject createProxy(Class<?> beanClass @Nullable String beanName
      @Nullable ob<x>ject[] specificInterceptors TargetSource targetSource) {
   if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
      AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory beanName beanClass);
   }
   ProxyFactory proxyFactory = new ProxyFactory();
   proxyFactory.copyFrom(this);
   if (!proxyFactory.isProxyTargetClass()) {
      if (shouldProxyTargetClass(beanClass beanName)) {
         proxyFactory.setProxyTargetClass(true);
      }
      else {
         evaluateProxyInterfaces(beanClass proxyFactory);
      }
   }
// AOP的增强器实现对象各有不同,需要统一转成Advisor接口,为了方便叙述还是称其为增强器
   Advisor[] advisors = buildAdvisors(beanName specificInterceptors);
// 给代理工厂传入增强器
   proxyFactory.addAdvisors(advisors);
// 给代理工厂指定要代理的目标对象
   proxyFactory.setTargetSource(targetSource);
// 模板方法设计模式运用,留给子类自定义代理工厂的机会
   customizeProxyFactory(proxyFactory);
   proxyFactory.setFrozen(this.freezeProxy);
   if (advisorsPreFiltered()) {
      proxyFactory.setPreFiltered(true);
   }
// 1.2 创建代理
   return proxyFactory.getProxy(getProxyClassLoader());
}

1.2 根据配置选择代理模式,创建代理

public ob<x>ject getProxy(@Nullable ClassLoader classLoader) {
    // 1.3 createAopProxy() 选择代理模式
    // 1.4 getProxy() 创建代理对象
   return createAopProxy().getProxy(classLoader);
}

1.3 选择代理模式,CGLIB代理还是JDK代理。在用户配置文件中的proxyTargetClass属性在此生效,proxy-target-class是指是否直接代理目标对象的Class对象,proxy-target-class=true时会优先选择CGLIB生成子类直接继承目标类Class对象。除非目标类本身是final或目标类是接口或已经是代理对象。

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
   if (!IN_NATIVE_IMAGE &&
         (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
      // 要代理的目标对象的Class对象
      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);
   }
}

1.4 getProxy() 创建代理对象。根据上一步知道创建代理对象有2条分支

CGLIB创建代理

创建完毕代理对象后,那么CGLIB代理对象怎么调用目标对象的目标方法呢?

CGLIB的关键是MethodInterceptor,给代理对象注入callback[]时,将适用于代理对象的advised增强器配置对象封装成DynamicAdvisedInterceptor对象,它实现了MethodInterceptor接口。让后将DynamicAdvisedInterceptor加入callback[]。调用代理对象的方法时,所有方法被转发到拦截器链的intercept()方法。advised变量就是AdvisedSupport类是AOP配置对象,里面封装有适用bean的增强器链。

@Override
@Nullable
public ob<x>ject intercept(ob<x>ject proxy Method method ob<x>ject[] args MethodProxy methodProxy) throws Throwable {
   ob<x>ject oldProxy = null;
   boolean setProxyContext = false;
   ob<x>ject target = null;
   TargetSource targetSource = this.advised.getTargetSource();
   try {
      // expose-proxy属性生效。原理是每次方法执行时将代理对象放入线程的LocalMap中。每次拦截器和方法执行完毕再移除
      if (this.advised.exposeProxy) {
         oldProxy = AopContext.setCurrentProxy(proxy);
         setProxyContext = true;
      }
      target = targetSource.getTarget();
      Class<?> targetClass = (target != null ? target.getClass() : null);
      // 将增强器做成链
      List<ob<x>ject> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method targetClass);
      ob<x>ject retVal;
      // Check whether we only have one InvokerInterceptor: that is
      // no real advice but just reflective invocation of the target.
      if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
         // 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.
         ob<x>ject[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method args);
         retVal = methodProxy.invoke(target argsToUse);
      }
      else {
         // 增强器链非空。创建ReflectiveMethodInvocation对象执行增强器链。该方法的增强方法都会在这里执行
         retVal = new CglibMethodInvocation(proxy target method args targetClass chain methodProxy).proceed();
      }
      retVal = processReturnType(proxy target method retVal);
      return retVal;
   }
   finally {
      if (target != null && !targetSource.isStatic()) {
         targetSource.releaseTarget(target);
      }
      if (setProxyContext) {
         // Restore old proxy.
         AopContext.setCurrentProxy(oldProxy);
      }
   }
}

最后来看看JDK代理对象

Spring创建的JdkDynamicAopProxy是直接实现了InvocationHandler接口。handler是链接代理对象和目标对象的中间桥梁。代理对象所有方法调用被转发到invoke(),所以在invoke()中实现了增强器的执行和目标方法的执行。

所有代理对象的被增强过的方法调用时,都会先来到这里

@Override
@Nullable
public ob<x>ject invoke(ob<x>ject proxy Method method ob<x>ject[] args) throws Throwable {
   ob<x>ject oldProxy = null;
   boolean setProxyContext = false;
   TargetSource targetSource = this.advised.targetSource;
   ob<x>ject target = null;
   try {
      if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
         // The target does not implement the equals(ob<x>ject) 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);
      }
      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);
      ob<x>ject retVal;
      if (this.advised.exposeProxy) {
         // expose proxy生效
         oldProxy = AopContext.setCurrentProxy(proxy);
         setProxyContext = true;
      }
      target = targetSource.getTarget();
      Class<?> targetClass = (target != null ? target.getClass() : null);
      // 拿到方法的增强器链
      List<ob<x>ject> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method targetClass);
      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.
         ob<x>ject[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method args);
         retVal = AopUtils.invokeJoinpointUsingReflection(target method argsToUse);
      }
      else {
         // 创建增强器链,链式执行。各增强器自己维护和目标方法的顺序,即是先执行增强方法还是先执行目标方法。
         MethodInvocation invocation = new ReflectiveMethodInvocation(proxy target method args targetClass chain);
         retVal = invocation.proceed();
      }
      // 省略代码..
      return retVal;
   }
   finally {
      if (target != null && !targetSource.isStatic()) {
         // Must have come from TargetSource.
         targetSource.releaseTarget(target);
      }
      if (setProxyContext) {
         // Restore old proxy.
         AopContext.setCurrentProxy(oldProxy);
      }
   }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值