Spring源码学习-5.ProxyFactoryBean实现与源代码分析

来源:互联网 发布:怎么看淘宝店网址 编辑:程序博客网 时间:2024/06/05 07:19


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{@Overridepublic 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.//需要加入命名的拦截器AdviceObject 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() failedthrow 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.//如果目标没实现hashcodereturn 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是怎么产生的那?


0 0