Spring源码学习-5.ProxyFactoryBean实现与源代码分析
2015-08-11 09:08
761 查看
1.AOP设计原理
proxyConfig<-AdvisedSupport<-proxyCreatorSupport<-(AspectJProxyFactory+ ProxyFactory + ProxyFactoryBean)在这个继承关系中,ProxyConfig是最底层的类,这是一个数据基类,为子类提供配置属性
AdvisedSupport: 封装了AOP对通知和通知器的操作
proxyCreatorSupport:子类创建AOP对象的一个辅助类
AspectJProxyFactory:集成AOP和AspectJ
ProxyFactory :封装AOP功能,需要编程式实现
ProxyFactoryBean封装AOP ,在IoC中实现声明式配置
2.第一步:得到AOP代理对象
ProxyFactoryBean生成Aop代理对象1.配置ProxyFactoryBean
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <span style="white-space:pre"> </span>xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" <span style="white-space:pre"> </span>xmlns:tx="http://www.springframework.org/schema/tx" <span style="white-space:pre"> </span>xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd <span style="white-space:pre"> </span>http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd <span style="white-space:pre"> </span>http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd <span style="white-space:pre"> </span>http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <span style="white-space:pre"> </span><bean id="testAdvisor" class="day0815.AopAdvisor"> <span style="white-space:pre"> </span></bean> <span style="white-space:pre"> </span><bean id="ttt" class="day0815.AopTestMethod"></bean> <span style="white-space:pre"> </span><bean id="testAOP" class="org.springframework.aop.framework.ProxyFactoryBean"> <span style="white-space:pre"> </span><property name="proxyInterfaces" > <span style="white-space:pre"> </span><value>day0815.TestProxyInterface</value> <span style="white-space:pre"> </span></property> <span style="white-space:pre"> </span><property name="target"> <span style="white-space:pre"> </span><ref bean="ttt"/> <span style="white-space:pre"> </span></property> <span style="white-space:pre"> </span><property name="interceptorNames" ><list><value>testAdvisor</value></list></property> <span style="white-space:pre"> </span></bean> </beans>
target是需要增强的对象
Demo中的代码为
package day0815; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringTest { public static void main(String[] args) { ApplicationContext a = new ClassPathXmlApplicationContext("classpath:ac20150811.xml"); TestProxyInterface aopTestMethod = (TestProxyInterface) a.getBean("testAOP"); aopTestMethod.service(); } }//============================================= package day0815; public interface TestProxyInterface { void service(); }//============================================== package day0815; public class AopTestMethod implements TestProxyInterface{ @Override public void service(){ System.out.println("Service method"); } }<pre name="code" class="java">//=============================================package day0815;import java.lang.reflect.Method;import org.springframework.aop.MethodBeforeAdvice;public class AopAdvisor implements MethodBeforeAdvice{@Overridepublic void before(Method arg0, Object[] arg1, Object arg2)throws Throwable
{// TODO Auto-generated method stubSystem.out.println("BeforeMethod~~");}}
2.生成代理对象
生成代理对象的入口是getObject.由于ProxyFactoryBean也是一个FactoryBean ,singleton和Prototype生成过程是不同的
//ProxyFactoryBean的实现是以getObject为入口实现的 public Object getObject() throws BeansException { initializeAdvisorChain();//初始化通知器 if (isSingleton()) {//如果是单例,以单例的方式生成aopProxy代理,Bean的默认就是单例,所以进入这个方法 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(); } }
下面是通知器初始过程,
advisorChainInitialized是是否已经初始化的标志,如果已经初始化就返回
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException { //如果已经初始化,就返回 if (this.advisorChainInitialized) { return; } if (!ObjectUtils.isEmpty(this.interceptorNames)) { if (this.beanFactory == null) { throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " + "- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames)); } // Globals can't be last unless we specified a targetSource using the property... if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) && this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) { throw new AopConfigException("Target required after globals"); } // Materialize interceptor chain from bean names. //添加Advisor链的调用,通过interceptorNames进行的 for (int i = 0; i < this.interceptorNames.length; i++) { String name = this.interceptorNames[i]; if (logger.isTraceEnabled()) { logger.trace("Configuring advisor or advice '" + name + "'"); } if (name.endsWith(GLOBAL_SUFFIX)) { if (!(this.beanFactory instanceof ListableBeanFactory)) { throw new AopConfigException( "Can only use global advisors or interceptors with a ListableBeanFactory"); } // addGlobalAdvisor((ListableBeanFactory) this.beanFactory, name.substring(0, name.length() - GLOBAL_SUFFIX.length())); } else { // If we get here, we need to add a named interceptor. // We must check if it's a singleton or prototype. //需要加入命名的拦截器Advice Object advice = null; if (this.singleton || this.beanFactory.isSingleton(this.interceptorNames[i])) { // Add the real Advisor/Advice to the chain. //调用getBean加载通知器或者通知 advice = this.beanFactory.getBean(this.interceptorNames[i]); } else { // It's a prototype Advice or Advisor: replace with a prototype. // Avoid unnecessary creation of prototype bean just for advisor chain initialization. advice = new PrototypePlaceholderAdvisor(this.interceptorNames[i]); } addAdvisorOnChainCreation(advice, this.interceptorNames[i]); } } } //已初始化,不需要再次初始化 this.advisorChainInitialized = true; }
singleton代理对象的生成是在getSingletonInstance中,这是生成代理对象的入口,
//生成代理代理对象 private synchronized Object getSingletonInstance() { if (this.singletonInstance == null) { //获取target属性 this.targetSource = freshTargetSource(); if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) { // Rely on AOP infrastructure to tell us what interfaces to proxy. //根据aop框架来判断需要代理的接口 Class targetClass = getTargetClass(); if (targetClass == null) { throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy"); } //设置需要代理的接口 setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader)); } // Initialize the shared singleton instance. super.setFrozen(this.freezeProxy); this.singletonInstance = getProxy(createAopProxy()); } return this.singletonInstance; }获取代理对象
public Object getProxy(ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); }
AopProxy是一个接口,他把代理对象的实现与框架分隔开
有两个子类实现了AopProxy
一个是JdkDynamicProxy,另一个是Cglib2AopProxy
createAopProxy生成aopProxy对象
//ProxyCreatorSupport类中的方法 protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } return getAopProxyFactory().createAopProxy(this); }
这里利用AopProxyFactory来创建AopProxy
//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."); } //如果support是接口,用jdk来生成代理 if (targetClass.isInterface()) { return new JdkDynamicAopProxy(config); } if (!cglibAvailable) { throw new AopConfigException( "Cannot proxy target class because CGLIB2 is not available. " + "Add CGLIB to the class path or specify proxy interfaces."); } //否则用cglib来生成 return CglibProxyFactory.createCglibProxy(config); } else { return new JdkDynamicAopProxy(config); } }
3.JDK和cglib生成AOP代理对象
1.使用jdk生成//JDK生成代理对象 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); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); //生成代理对象 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); } //实现InvocationHandler接口需要实现的方法 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation = null; 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]) ? Boolean.TRUE : Boolean.FALSE); } if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return new Integer(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 = null; if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // May be <code>null</code>. 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 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. retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); } 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. if (retVal != null && retVal == target && method.getReturnType().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; } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
2.使用cglib生成代理对象
//Cglib2AopProxy类中的方法 //使用cglib来生成代理对象 public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating CGLIB2 proxy: target source is " + this.advised.getTargetSource()); } try { //IoC容器中配制的Target对象 Class rootClass = this.advised.getTargetClass(); Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); Class proxySuperClass = rootClass; //如果这个类是cglib产生的,proxySuperClass = rootClass.getSuperclass(); if (AopUtils.isCglibProxyClass(rootClass)) { proxySuperClass = rootClass.getSuperclass(); Class[] additionalInterfaces = rootClass.getInterfaces(); for (int i = 0; i < additionalInterfaces.length; i++) { Class additionalInterface = additionalInterfaces[i]; this.advised.addInterface(additionalInterface); } } // Validate the class, writing log messages as necessary. validateClassIfNecessary(proxySuperClass); //验证代理对象的接口 //生成Enhancer // Configure CGLIB Enhancer... Enhancer enhancer = createEnhancer(); if (classLoader != null) { enhancer.setClassLoader(classLoader); if (classLoader instanceof SmartClassLoader && ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) { enhancer.setUseCache(false); } } enhancer.setSuperclass(proxySuperClass); enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class)); enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); enhancer.setInterceptDuringConstruction(false); Callback[] callbacks = getCallbacks(rootClass); enhancer.setCallbacks(callbacks); enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); Class[] types = new Class[callbacks.length]; for (int x = 0; x < types.length; x++) { types[x] = callbacks[x].getClass(); } enhancer.setCallbackTypes(types); //创建一个cglib代理的实例 // Generate the proxy class and create a proxy instance. Object proxy; if (this.constructorArgs != null) { proxy = enhancer.create(this.constructorArgTypes, this.constructorArgs); } else { proxy = enhancer.create(); } return proxy; } catch (CodeGenerationException ex) { throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: " + "Common causes of this problem include using a final class or a non-visible class", ex); } catch (IllegalArgumentException ex) { throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: " + "Common causes of this problem include using a final class or a non-visible class", ex); } catch (Exception ex) { // TargetSource.getTarget() failed throw new AopConfigException("Unexpected AOP exception", ex); } }
4.第二步:AOP拦截器调用的实现
1.JDK拦截器的设置在使用jdk或者cglib生成代理对象时就完成了,
如果是JDK的Proxy来实现代理对象的话,那么需要在InvocationHandler中来设置回调
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); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); //生成代理对象 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);//这个类继承了InvocationHandler接口,所以在这个类的invoke中 可以看到配置的过程 }
//JdkDynamicAopProxy类invoke方法 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation = null; 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. //如果目标没实现equals方法 return (equals(args[0]) ? Boolean.TRUE : Boolean.FALSE); } if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. //如果目标没实现hashcode return new Integer(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 = null; if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // May be <code>null</code>. 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 chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // Check whether we have any advice. If we don't, we can fallback on direct //构造MethodInvocation // 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. //没有设定拦截器,就直接调用target的对应方法 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); } 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. if (retVal != null && retVal == target && method.getReturnType().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; } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
2.CGLIB
this代表了这个类,这个类继承了InvocationHandler接口,所以在这个类的invoke中 可以看到配置的过程
如果是CGLIB的话,需要根据cglib使用要求,在dynamic-AdvisedInterceptor中完成.
CGLIB与jdk的实现类似,只是通过构造ReflectMethod-Invocation对象来完成
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { MethodInvocation invocation = null; Object oldProxy = null; boolean setProxyContext = false; Class targetClass = null; Object target = null; try { Object retVal = null; if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // May be <code>null</code>. Get as late as possible to minimize the time we // "own" the target, in case it comes from a pool. target = getTarget(); if (target != null) { targetClass = target.getClass(); } List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // 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. retVal = methodProxy.invoke(target, args); } else { // We need to create a method invocation... invocation = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy); // If we get here, we need to create a MethodInvocation. retVal = invocation.proceed(); } retVal = massageReturnTypeIfNecessary(proxy, target, method, retVal); return retVal; } finally { if (target != null) { releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
3.对于目标方法的调用
jdk的实现方法是使用反射得出的,而cglib是通过MethodProxy完成的
5.AOP拦截器链的调用
1.处理AOP配置的通知基本步骤:(1).获取AOP配置的通知Advice:
在AOP动态代理对象的回调方法中,都需要使用以下方式获取AOP配置的通知,并将获取到的通知和目标对象、代理对象等一起封装为ReflectiveMethodInvocation对象
//获取AOP配置的通知 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); …… //根据获取的通知、目标对象等创建ReflectiveMethodInvocation //如果是CGLIB方式,则创建CglibMethodInvocation对象: //new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy); invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); //沿着获取的通知链,递归调用所有配置的AOP通知 retVal = invocation.proceed();
(2).创建ReflectiveMethodInvocation对象:
a.创建CglibMethodInvocation对象:
(3).处理AOP配置的通知器:
Spring通过调用ReflectiveMethodInvocation类来处理AOP配置的通知,CglibMethodInvocation继承ReflectiveMethodInvocation,因此JDK和CGLIB方式都是通过调用ReflectiveMethodInvocation的proceed()方法来处理通知的,处理通知的源码如下:
/处理AOP配置的通知 public Object proceed() throws Throwable { //如果拦截器链中通知已经调用完毕 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { //这个方法调用AopUtils.invokeJoinpointUsingReflection方法, //通过反射机制直接调用目标对象方法 return invokeJoinpoint(); } //获取AOP配置的通知,在ReflectiveMethodInvocation初始化构方法中将获 //取到的AOP通知赋值给interceptorsAndDynamicMethodMatchers变量 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); //如果获取的通知器或通知是动态匹配方法拦截器类型 if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { //动态匹配方法拦截器 InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { //如果匹配,调用拦截器的方法 return dm.interceptor.invoke(this); } else { //如果不匹配,递归调用proceed()方法,知道拦截器链被全部调用为止 return proceed(); } } else { //如果不是动态匹配方法拦截器,则切入点在构造对象之前进行静态匹配,调用 //拦截器的方法 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
advisor是怎么产生的那?
相关文章推荐
- 关于Java数据库查询结果保存到DBF的小小总结^_^
- Java基本数据类型、包装类与String类之间的转换
- Spring学习笔记三(AOP中的那些事)
- java 各种排序算法
- java快速排序
- windows下(java环境)配置最新版的vlcj
- Spring3.1.0 jar包详解说明
- Msc系统上的eclipse遇到乱码问题解决方式
- 在Java中辅助报表工具展现json
- Java实现与调用Web Service
- 开源 自由 java CMS - FreeCMS1.9 分纪录
- Java语言的多态机制实现
- Java学习笔记16--异常
- Java学习笔记15--引用传递
- Java学习笔记14--动态代理
- Java学习笔记13--比较器(Comparable、Comparator)
- Java学习笔记11--Annotation
- Java学习笔记12--国际化
- Java学习笔记10--枚举
- Java学习笔记09--反射机制