您的位置:首页 > 编程语言 > Java开发

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是怎么产生的那?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: