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