Insight 根据advisor生成Proxy过程 | AOP调用性能解疑

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tt50335971/article/details/51837366

疑问: 1、context 如何根据bean-factory中的advisor 生成proxy(比如@Aspect Advice作用在指定的方法)

2.AOP对方法执行性能的影响是怎样的(Proxy 的生成时机?、方法执行会动态匹配Advice ?)

...

需要明确的是:

a.spring初始化的过程中,BeanFactory.initializeBean会在post-bean 阶段委托bean-post-processor进行处理。

b.关于是否生成AOP代理由bean-post-processor: AbstractAutoProxyCreator完成。

...

processor调用postProcessAfterInitialization、wrapIfNecessary,关键处理如下所示:

// Create proxy if we have advice.
// bean初始化过程中,find匹配到的Advice,作为构造Proxy的intercepter
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
   this.advisedBeans.put(cacheKey, Boolean.TRUE);
   // !动态Proxy(cglib、JDKProxy)
   Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
   this.proxyTypes.put(cacheKey, proxy.getClass());
   return proxy;
}

...

委托CglibAopProxy生成代理类(此时,class已经生成),Proxy class列表如下:

RedisDataServiceImpl$$EnhancerBySpringCGLIB$$26df96fd$$FastClassBySpringCGLIB$$86cb2da1.class
// 真正的Proxy Class(CglibAopProxy 生成)
RedisDataServiceImpl$$EnhancerBySpringCGLIB$$26df96fd.class
// Cglib FastClass
RedisDataServiceImpl$$FastClassBySpringCGLIB$$6bf6a919.class
// 原有的实现Class
RedisDataServiceImpl.class

-------------------------------------------------------------------------------------------------------------------

涉及到AOP方法的调用:
入口 CglibAopProxy$DynamicAdvisedInterceptor.intercept()
构造MethodInvocation,委托method进行targetClass 方法调用。interceptors信息全部在proxy (反编译导出的代理类,不如debug 过程中看的清楚)
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
在调用过程中可以看到,在Spring 容器的初始化过程中,随着bean的初始化,代理类提前完成生成、初始化。不会在方法执行过程中再做这些事情,调用过程中只有invokeJoinpointUsingReflection();


结论:

1.参考AbstractAutowireCapableBeanFactory.initializeBean(),Bean初始化过程-AfterPost阶段,会有APC.wrapProxyIfNecessary的过程,此时会查找匹配的Advice并生成Proxy instance,最后将proxy 暴露给bean-factory。

2.注入的bean就是上述的Proxy instance,正常方法调用时,由Proxy类发起调用,根据Advice 的类型,决定调用的顺序,没有动态匹配Advisor过程,性能的影响主要是invokeUsingReflection造成的。

method.invoke(target, args)

3.Advice方法Class内部调用,interceptor不会生效,从Proxy class 列表看,是由完全不同的类发起调用,只是从源码中无法感知。

4.Java查看动态代理生成的代码 http://www.cnblogs.com/ctgulong/p/5011614.html


附带AopProxyFactory实现:

// 根据Interface决定采用JDK动态代理或者Cglib动态代理
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()) {
         return new JdkDynamicAopProxy(config);
      }
      return CglibProxyFactory.createCglibProxy(config);
   }
   else {
      return new JdkDynamicAopProxy(config);
   }
}




阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页