当前位置:首页 > > 切换IP软件

深入分析 Spring 框架中 AOP 与动态代理的整合原理

来源:我爱加倍游 时间:2020-01-29

Spring AOP动态代理支持的核心

1.jdk动态代理:java.lang.reflect.InvocationHandler

对应的方法拦截器:

publicObject invoke(Object proxy, Method method, Object[] args)

throws Throwable;

调用时使用method.invoke(Object, args)

该动态代理是基于接口的动态代理,所以并没有一个原始方法的调用过程,整个方法都是被拦截的。

2.通过cglib动态创建类进行动态代理。org.springframework.cglib.proxy包下的原生接口,同net.sf.cglib.proxy包下的接口,都是源自cglib库。Spring内部的cglib动态代理使用了这种方式。

对应的方法拦截器:

org.springframework.cglib.proxy.Callback、 org.springframework.cglib.proxy.MethodInterceptor

publicinterface MethodInterceptor extends Callback {

Object intercept(Object obj, Method m, Object[] args, MethodProxy mp)throws Throwable

}

调用时,使用mp.invoke(Object obj, Object[] args)调用其他同类对象的原方法或者mp.invokeSuper(Object obj, Object[] args)调用原始(父类)方法。

3.org.aopalliance的拦截体系

该包是AOP组织下的公用包,用于AOP中方法增强和调用。相当于一个jsr标准,只有接口和异常。在AspectJ、Spring等AOP框架中使用。

对应的方法拦截器org.aopalliance.intercept.MethodInterceptor:

publicinterface MethodInterceptor extends Interceptor {

Object invoke(MethodInvocation inv)throws Throwable;

}

调用时使用inv.proceed()调用原始方法。

附aopalliance包介绍:

详细介绍:

Advice 增强器标记接口
Interceptor 拦截器,Advice的子接口,标记拦截器。拦截器是增强器的一种。
MethodInterceptor 方法拦截器,Interceptor的子接口,拦截方法并处理。
ConstructorInterceptor 构造器拦截器,Interceptor的子接口,拦截构造器并处理。
Joinpoint 连接点。在拦截器中使用,封装了原方法调用的相关信息,如参数、原对象信息,以及直接调用原方法的proceed方法。
Invocation Joinpoint的子类,添加了获取调用参数方法。
MethodInvocation Invocation的子类,包含了获取调用方法的方法。
ConstructorInvocation Invocation的子类,包含了获取构造器的方法。
Spring AOP框架的整合

先看一下通过Spring生成代理对象的代码:

// 生成基于实例的代理

publicObject createProxy(Object bean, Advice advice){

ProxyFactory proxyFactory = newProxyFactory();

proxyFactory.setTarget(bean);

proxyFactory.addAdvice(advice);

returnproxyFactory.getProxy();

}

// 生成基于接口的代理

publicT createProxy(Class<T> interface, Interceptor interceptor){

T proxy = newProxyFactory(interface, interceptor).getProxy();

// 或者ProxyFactory.getProxy(interface, interceptor).getProxy();

returnproxy;

}

针对上面的代码,结合源码进行分析,得到整个代理对象的创建过程。

准备:过程中出现的对象

AopProxyFactory接口 AopProxy代理工厂类,用于生成代理对象AopProxy。
publicinterface AopProxyFactory {

AopProxy createAopProxy(AdvisedSupport config)throws AopConfigException;

}

AopProxy 代表一个AopProxy代理对象,可以通过这个对象构造代理对象实例。
publicinterface AopProxy {

Object getProxy();

Object getProxy(ClassLoader classLoader);

}

Advised接口 代表被Advice增强的对象,包括添加advisor的方法、添加advice等的方法。
ProxyConfig类 一个代理对象的配置信息,包括代理的各种属性,如基于接口还是基于类构造代理。
AdvisedSupport类 对Advised的构建提供支持,Advised的实现类以及ProxyConfig的子类。
ProxyCreatorSupport类 AdvisedSupport的子类,创建代理对象的支持类,内部包含AopProxyFactory工厂成员,可直接使用工厂成员创建Proxy。
ProxyFactory类 ProxyCreatorSupport的子类,用于生成代理对象实例的工厂类,生成代码参考下面。
Advisor接口 代表一个增强器提供者的对象,内部包含getAdvice方法获取增强器。
AdvisorChainFactory接口 获取增强器链的工厂接口。提供方法返回所有增强器,以数组返回。
Pointcut接口 切入点,用于匹配类与方法,满足切入点的条件是才插入advice。相关接口:ClassFilter、MethodMatcher。
分析:结合源码分析创建过程

以上准备做完之后,就可以看源码了,从获取代理对象的实例入口ProxyFactory.getProxy()开始:

publicObject getProxy(){

// 创建AopProxy对象再获取代理对象实例

returncreateAopProxy().getProxy();

}

// createAopProxy方法在父类ProxyCreatorSupport中

protectedfinal synchronized AopProxy createAopProxy(){

if(! this.active) {

activate();

}

// 先获取AopProxy的工厂对象,再把自己作为createAopProxy的参数AdvisedSupport传进去,用自己作为代理对象的配置

returngetAopProxyFactory().createAopProxy( this);

}

代理对象实例最终是使用AopProxy.getProxy()得到的,他的调用是在AopProxyFactory.createAopProxy(AdvisedSupport config,createAopProxy有两个结果。一个是基于接口的JDK动态代理JdkDynamicAopProxy,一个是基于CGLib的生成类代理ObjenesisCglibAopProxy。源码如下:

publicclassDefaultAopProxyFactory implements AopProxyFactory, Serializable {

@ Override

publicAopProxy createAopProxy(AdvisedSupport config)throws AopConfigException {

if(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {

// 如果是需要优化的代理,或者标记代理目标类,或者代理配置中没有需要代理的接口

Class<?> targetClass = config.getTargetClass();

if(targetClass == null) {

thrownewAopConfigException( "TargetSource cannot determine target class: "+

"Either an interface or a target is required for proxy creation.");

}

if(targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {

// 如果目标类是接口,或者已经是Jdk的动态代理类,则创建jdk动态代理

returnnewJdkDynamicAopProxy(config);

}

// 否则创建Cglib动态代理

returnnewObjenesisCglibAopProxy(config);

}

else{

// 如果声明创建Jdk动态代理则返回Jdk动态代理

returnnewJdkDynamicAopProxy(config);

}

}

}

传入的AdvisedSupport config中包含了需要注册的Method拦截器,AopProxy会保存这个config为advised对象。

基于JDK的动态代理

JdkDynamicAopProxy中getProxy会返回:

publicObject getProxy(ClassLoader classLoader){

if(logger.isDebugEnabled()) {

logger.debug( "Creating JDK dynamic proxy: target source is "+ this.advised.getTargetSource());

}

// 获取所有需要代理的接口

Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces( this.advised, true);

findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);

// 返回代理对象的实例

returnProxy.newProxyInstance(classLoader, proxiedInterfaces, this);

}

自己作为InvocationHandler注册,看他的invoke方法

publicObject invoke(Object proxy, Method method, Object[] args)throws Throwable {

MethodInvocation invocation;

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方法,调用equals方法时,委托调用。

returnequals(args[ 0]);

}

elseif(! this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {

// The target does not implement the hashCode() method itself.

// 没有声明hashCode方法,调用hashCode方法时,委托调用。

returnhashCode();

}

elseif(method.getDeclaringClass() == DecoratingProxy. class) {

// There is only getDecoratedClass() declared -> dispatch to proxy config.

// 如果调用的方法是DecoratingProxy中的方法,因为其中只有一个getDecoratedClass方法,这里直接返回被装饰的Class即可

returnAopProxyUtils.ultimateTargetClass( this.advised);

}

elseif(! this.advised.opaque && method.getDeclaringClass().isInterface() &&

method.getDeclaringClass().isAssignableFrom(Advised. class)) {

// 代理不是不透明的,且是接口中声明的方法,且是Advised或其父接口的方法,则直接调用构造时传入的advised对象的相应方法

// Service invocations on ProxyConfig with the proxy config...

returnAopUtils.invokeJoinpointUsingReflection( this.advised, method, args);

}

Object retVal;

if( this.advised.exposeProxy) {

// Make invocation available if necessary.

// 如果暴露代理,则用AopContext保存当前代理对象。用于多级代理时获取当前的代理对象,一个有效应用是同类中调用方法,代理拦截器会无效。可以使用AopContext.currentProxy()获得代理对象并调用。

oldProxy = AopContext.setCurrentProxy(proxy);

setProxyContext = true;

}

// May be null. 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

// 这里是关键,获得拦截链chain,是通过advised对象,即config对象获得的。

method.

List<Object> 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.

Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);

retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);

}

else{

// We need to create a method invocation...

// 否则创建一个MethodInvocation对象,用于链式调用拦截器链chain中的拦截器。

invocation = newReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);

// Proceed to the joinpoint through the interceptor chain.

// 开始执行链式调用,得到返回结果

retVal = invocation.proceed();

}

// Massage return value if necessary.

Class<?> returnType = method.getReturnType();

if(retVal != null && retVal == target &&

returnType != Object. class&& returnType.isInstance(proxy) &&

!RawTargetAccess. class.isAssignableFrom(method.getDeclaringClass())) {

// 处理返回值

// 如果返回结果是this,即原始对象,且方法所在类没有标记为RawTargetAccess(不是RawTargetAccess的实现类或者子接口),则返回代理对象。

// 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;

}

elseif(retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {

thrownewAopInvocationException(

"Null return value from advice does not match primitive return type for: "+ method);

}

returnretVal;

}

finally {

if(target != null && !targetSource.isStatic()) {

// Must have come from TargetSource.

targetSource.releaseTarget(target);

}

if(setProxyContext) {

// Restore old proxy.

AopContext.setCurrentProxy(oldProxy);

}

}

}

注册的Method拦截器都是通过AdvisedSupport这个config对象的addAdvice或者addAdvisor注册进去的。

publicvoidaddAdvice(intpos, Advice advice)throws AopConfigException {

Assert.notNull(advice, "Advice must not be null");

if(advice instanceof IntroductionInfo) {

// We don't need an IntroductionAdvisor for this kind of introduction:

// It's fully self-describing.

// 如果是引介,则加入引介advisor。(新增功能)

addAdvisor(pos, newDefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));

}

elseif(advice instanceof DynamicIntroductionAdvice) {

// We need an IntroductionAdvisor for this kind of introduction.

// jdk动态代理不支持动态引介

thrownewAopConfigException( "DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");

}

else{

// 把advice转换为advisor并添加,目标是DefaultPointcutAdvisor。

addAdvisor(pos, newDefaultPointcutAdvisor(advice));

}

}

其实也是把advice转成了advisor注册的。 看下最上面invoke方法中有一个方法调用:

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

publicList<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {

MethodCacheKey cacheKey = newMethodCacheKey(method);

List<Object> cached = this.methodCache.get(cacheKey);

if(cached == null) {

// 其实是通过advisorChainFactory工厂对象获得的

cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(

this, method, targetClass);

this.methodCache.put(cacheKey, cached);

}

returncached;

}

是通过AdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法获取的,也把config对象传入了,且加的有缓存。其实是通过method获取该method对应的advisor。下面是他的唯一实现:

publicclassDefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {

@Override

publicList<Object> getInterceptorsAndDynamicInterceptionAdvice(

Advised config, Method method, Class<?> targetClass) {

// This is somewhat tricky... We have to process introductions first,

// but we need to preserve order in the ultimate list.

List<Object> interceptorList = newArrayList<Object>(config.getAdvisors().length);

Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());

boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);

AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

for(Advisor advisor : config.getAdvisors()) {

if(advisor instanceof PointcutAdvisor) {

// Add it conditionally.

PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;

if(config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {

MethodInterceptor[] interceptors = registry.getInterceptors(advisor);

MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();

if(MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {

if(mm.isRuntime()) {

// Creating a new object instance in the getInterceptors() method

// isn't a problem as we normally cache created chains.

for(MethodInterceptor interceptor : interceptors) {

interceptorList.add( newInterceptorAndDynamicMethodMatcher(interceptor, mm));

}

}

else{

interceptorList.addAll(Arrays.asList(interceptors));

}

}

}

}

elseif(advisor instanceof IntroductionAdvisor) {

IntroductionAdvisor ia = (IntroductionAdvisor) advisor;

if(config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {

Interceptor[] interceptors = registry.getInterceptors(advisor);

interceptorList.addAll(Arrays.asList(interceptors));

}

}

else{

Interceptor[] interceptors = registry.getInterceptors(advisor);

interceptorList.addAll(Arrays.asList(interceptors));

}

}

returninterceptorList;

}

/**

* Determine whether the Advisors contain matching introductions.

*/

privatestaticboolean hasMatchingIntroductions(Advised config, Class<?> actualClass){

for( inti = 0; i < config.getAdvisors().length; i++) {

Advisor advisor = config.getAdvisors();

if(advisor instanceof IntroductionAdvisor) {

IntroductionAdvisor ia = (IntroductionAdvisor) advisor;

if(ia.getClassFilter().matches(actualClass)) {

returntrue;

}

}

}

returnfalse;

}

}

上面包括了各种对Advisor包装,通过Pointcut等的判断把Advisor中的Advice包装成MethodInterceptor、InterceptorAndDynamicMethodMatcher或者Interceptor。

之后在调用方法前,又把chain转换为了aopalliance体系的的MethodInvocation。

invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);

最终执行的是retVal = invocation.proceed()。 在ReflectiveMethodInvocation的proceed方法中,有整个拦截器链的责任链模式的执行过程,可以仔细看看,通过责任链序号方式执行的。

publicObject proceed()throws Throwable {

// We start with an index of -1 and increment early.

if( this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {

// 链全部执行完,再次调用proceed时,返回原始对象方法调用执行结果。递归的终止。

returninvokeJoinpoint();

}

Object interceptorOrInterceptionAdvice =

this.interceptorsAndDynamicMethodMatchers.get(++ this.currentInterceptorIndex);

// 用currentInterceptorIndex记录当前的interceptor位置,初值-1,先++再获取。当再拦截器中调用invocation.proceed()时,递归进入此方法,索引向下移位,获取下一个拦截器。

if(interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {

// 如果是InterceptorAndDynamicMethodMatcher则再执行一次动态匹配

// Evaluate dynamic method matcher here: static part will already have

// been evaluated and found to match.

InterceptorAndDynamicMethodMatcher dm =

(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;

if(dm.methodMatcher.matches( this.method, this.targetClass, this.arguments)) {

// 匹配成功,执行

returndm.interceptor.invoke( this);

}

else{

// Dynamic matching failed.

// Skip this interceptor and invoke the next in the chain.

// 匹配失败,跳过该拦截器,递归调用本方法,执行下一个拦截器。

returnproceed();

}

}

else{

// It's an interceptor, so we just invoke it: The pointcut will have

// been evaluated statically before this object was constructed.

// 如果是interceptor,则直接调用invoke。把自己作为invocation,以便在invoke方法中,调用invocation.proceed()来执行递归。或者invoke中也可以不执行invocation.proceed(),强制结束递归,返回指定对象作为结果。

return((MethodInterceptor) interceptorOrInterceptionAdvice).invoke( this);

}

}

基于Cglib的动态代理

看另外一种情况,Cglib的代理类:

ObjenesisCglibAopProxy继承自CglibAopProxy,整体对外暴露的接口和方法是与上面一致的,只有其真实实现换成了Cglib而已。

publicObject getProxy(ClassLoader classLoader){

if(logger.isDebugEnabled()) {

logger.debug( "Creating CGLIB proxy: target source is "+ this.advised.getTargetSource());

}

try{

Class<?> rootClass = this.advised.getTargetClass();

Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

Class<?> proxySuperClass = rootClass;

if(ClassUtils.isCglibProxyClass(rootClass)) {

proxySuperClass = rootClass.getSuperclass();

Class<?>[] additionalInterfaces = rootClass.getInterfaces();

for(Class<?> additionalInterface : additionalInterfaces) {

this.advised.addInterface(additionalInterface);

}

}

// Validate the class, writing log messages as necessary.

validateClassIfNecessary(proxySuperClass, classLoader);

// Configure CGLIB Enhancer...

// 使用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.setInterfaces(AopProxyUtils.completeProxiedInterfaces( this.advised));

// 命名策略是类名中加$$

enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);

// 设置类生成策略,直接生成类的字节码byte[],可以深入研究

enhancer.setStrategy( newClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

// 获取所有的callback,此时callback是cglib 的,getCallbacks中会把advisors封装成callback传入

Callback[] callbacks = getCallbacks(rootClass);

Class<?>[] types = newClass<?>[callbacks.length];

// 生成callback类型数组

for( intx = 0; x < types.length; x++) {

types[x] = callbacks[x].getClass();

}

// fixedInterceptorMap only populated at this point, after getCallbacks call above

// 加入是否需要进行callback的过滤器,根据filter的返回的int值,cglib会执行不同的callback,索引分别对应上面的callback数组的索引:

// 0:AOP_PROXY、1:INVOKE_TARGET、2:NO_OVERRIDE、3:DISPATCH_TARGET、4:DISPATCH_ADVISED、5:INVOKE_EQUALS、6:INVOKE_HASHCODE

enhancer.setCallbackFilter( newProxyCallbackFilter(

this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));

enhancer.setCallbackTypes(types);

// Generate the proxy class and create a proxy instance.

returncreateProxyClassAndInstance(enhancer, callbacks);

}

catch(CodeGenerationException ex) {

thrownewAopConfigException( "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) {

thrownewAopConfigException( "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(Throwable ex) {

// TargetSource.getTarget() failed

thrownewAopConfigException( "Unexpected AOP exception", ex);

}

}

protectedObject createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks){

// 不拦截构造方法

enhancer.setInterceptDuringConstruction( false);

// 设置拦截器callback

enhancer.setCallbacks(callbacks);

// 创建代理对象实例

return( this.constructorArgs != null ?

enhancer.create( this.constructorArgTypes, this.constructorArgs) :

enhancer.create());

}

直接看方法拦截器部分。注册拦截器是在getProxy方法中,注册进去的是cglib中的callback:

Callback[] callbacks = getCallbacks(rootClass)

enhancer.setCallbacks(callbacks);

privateCallback[] getCallbacks(Class<?> rootClass) throws Exception {

// Parameters used for optimization choices...

boolean exposeProxy = this.advised.isExposeProxy();

boolean isFrozen = this.advised.isFrozen();

boolean isStatic = this.advised.getTargetSource().isStatic();

// Choose an "aop" interceptor (used for AOP calls).

// 生成aopInterceptor,用于AOP调用,这是调用拦截器链的核心,详看后面。

Callback aopInterceptor = newDynamicAdvisedInterceptor( this.advised);

// Choose a "straight to target" interceptor. (used for calls that are

// unadvised but can return this). May be required to expose the proxy.

Callback targetInterceptor;

// 下面根据不同情况,返回不同的Callback。

// targetSource的isStatic为true表示targetSource中的target是静态的不改变的,故直接缓存target即可。

// 为false则代表是动态的target,每次都需要getTarget来获取,这两种返回不同的callback,以便后续执行时使用不同情况的target。

// 而exposeProxy代表是否暴露代理对象到AopProxyContext中。

// 为true代表暴露,false不暴露。都需要返回不同的callback。

// 故总共有四种callback,且四种callback都有一个processReturnType的过程,同JdkDynamicAopProxy中的处理返回值。前面的操作也与JdkDynamicAopProxy中开始的目的相同。

if(exposeProxy) {

targetInterceptor = isStatic ?

newStaticUnadvisedExposedInterceptor( this.advised.getTargetSource().getTarget()) :

newDynamicUnadvisedExposedInterceptor( this.advised.getTargetSource());

}

else{

targetInterceptor = isStatic ?

newStaticUnadvisedInterceptor( this.advised.getTargetSource().getTarget()) :

newDynamicUnadvisedInterceptor( this.advised.getTargetSource());

}

// Choose a "direct to target" dispatcher (used for

// unadvised calls to static targets that cannot return this).

// 直接调用target的callback

Callback targetDispatcher = isStatic ?

newStaticDispatcher( this.advised.getTargetSource().getTarget()) : newSerializableNoOp();

// callbackFilter返回的是callback的索引,用于调用这里的索引值对应的callback。

Callback[] mainCallbacks = newCallback[] {

aopInterceptor, // for normal advice

// 经过callbackFilter后,不需要被advice的对象,直接调用这个interceptor,性能最高。

targetInterceptor, // invoke target without considering advice, if optimized

newSerializableNoOp(), // no override for methods mapped to this

targetDispatcher,

// 调用advised中方法时,直接分配到advised中。

this.advisedDispatcher,

// equals方法

newEqualsInterceptor( this.advised),

// hashCode方法

newHashCodeInterceptor( this.advised)

};

Callback[] callbacks;

// If the target is a static one and the advice chain is frozen,

// then we can make some optimizations by sending the AOP calls

// direct to the target using the fixed chain for that method.

// 这是一个优化,如果target是个不可变的静态对象,且advice链是固定不变的,则进行优化。内容见后面。

if(isStatic && isFrozen) {

Method[] methods = rootClass.getMethods();

Callback[] fixedCallbacks = newCallback[methods.length];

this.fixedInterceptorMap = newHashMap<String, Integer>(methods.length);

// TODO:small memory optimization here (can skip creation for methods with no advice)

for( intx = 0; x < methods.length; x++) {

// 遍历所有方法,返回每个方法的拦截器链,并为每个方法生成一个包含拦截器链的callback。

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);

fixedCallbacks[x] = newFixedChainStaticTargetInterceptor(

chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());

// 注意,这个fixedInterceptorMap还与callbackFilter关联,以便达到filter的目的。

// 同时保存索引到map中,以用于callbackFilter中返回索引。

this.fixedInterceptorMap.put(methods[x].toString(), x);

}

// Now copy both the callbacks from mainCallbacks

// and fixedCallbacks into the callbacks array.

// 聚合所有callback

callbacks = newCallback[mainCallbacks.length + fixedCallbacks.length];

System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);

System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);

// 标记fixedInterceptor的偏移量,也会传入filter。

this.fixedInterceptorOffset = mainCallbacks.length;

}

else{

callbacks = mainCallbacks;

}

returncallbacks;

}

上面提到callbackFilter的作用是返回需要调用的callback的序号,与上面的getCallbacks有比较大的关联,源码如下

// aopInterceptor: DynamicAdvisedInterceptor

privatestaticfinal intAOP_PROXY = 0;

// targetInterceptor: 没有advise的方法

privatestaticfinal intINVOKE_TARGET = 1;

// noOp: SerializableNoOp

privatestaticfinal intNO_OVERRIDE = 2;

// targetDispatcher: isStatic ? StaticDispatcher : SerializableNoOp

privatestaticfinal intDISPATCH_TARGET = 3;

// advisedDispatcher: AdvisedDispatcher

privatestaticfinal intDISPATCH_ADVISED = 4;

// EqualsInterceptor

privatestaticfinal intINVOKE_EQUALS = 5;

// HashCodeInterceptor

privatestaticfinal intINVOKE_HASHCODE = 6;

// 其他索引直接通过fixedInterceptorMap获得

// 下面逻辑基本对应JdkDynamicAopProxy中判断逻辑

publicintaccept(Method method){

if(AopUtils.isFinalizeMethod(method)) {

// 如果是final的方法,则返回NO_OVERRIDE

logger.debug( "Found finalize() method - using NO_OVERRIDE");

returnNO_OVERRIDE;

}

if(! this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&

method.getDeclaringClass().isAssignableFrom(Advised. class)) {

if(logger.isDebugEnabled()) {

logger.debug( "Method is declared on Advised interface: "+ method);

}

// advised上的方法,直接调用advised对象的对应方法

returnDISPATCH_ADVISED;

}

// We must always proxy equals, to direct calls to this.

if(AopUtils.isEqualsMethod(method)) {

// 返回调用equals

logger.debug( "Found 'equals' method: "+ method);

returnINVOKE_EQUALS;

}

// We must always calculate hashCode based on the proxy.

if(AopUtils.isHashCodeMethod(method)) {

// 返回调用hashCode

logger.debug( "Found 'hashCode' method: "+ method);

returnINVOKE_HASHCODE;

}

Class<?> targetClass = this.advised.getTargetClass();

// Proxy is not yet available, but that shouldn't matter.

List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

// 判断是否有拦截器链

boolean haveAdvice = !chain.isEmpty();

boolean exposeProxy = this.advised.isExposeProxy();

boolean isStatic = this.advised.getTargetSource().isStatic();

boolean isFrozen = this.advised.isFrozen();

if(haveAdvice || !isFrozen) {

// 如果有advice或者不是冻结的(不可改变的)

// If exposing the proxy, then AOP_PROXY must be used.

if(exposeProxy) {

if(logger.isDebugEnabled()) {

logger.debug( "Must expose proxy on advised method: "+ method);

}

// 如果需要暴露Proxy则返回aop代理

returnAOP_PROXY;

}

String key = method.toString();

// Check to see if we have fixed interceptor to serve this method.

// Else use the AOP_PROXY.

if(isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) {

// 通过fixedInterceptorMap获得对应索引,返回callback。

if(logger.isDebugEnabled()) {

logger.debug( "Method has advice and optimizations are enabled: "+ method);

}

// We know that we are optimizing so we can use the FixedStaticChainInterceptors.

intindex = this.fixedInterceptorMap.get(key);

return(index + this.fixedInterceptorOffset);

}

else{

if(logger.isDebugEnabled()) {

logger.debug( "Unable to apply any optimizations to advised method: "+ method);

}

returnAOP_PROXY;

}

}

else{

// See if the return type of the method is outside the class hierarchy of the target type.

// If so we know it never needs to have return type massage and can use a dispatcher.

// If the proxy is being exposed, then must use the interceptor the correct one is already

// configured. If the target is not static, then we cannot use a dispatcher because the

// target needs to be explicitly released after the invocation.

if(exposeProxy || !isStatic) {

// 如果需要暴露,则要使用targetInterceptor

returnINVOKE_TARGET;

}

Class<?> returnType = method.getReturnType();

if(returnType.isAssignableFrom(targetClass)) {

// 如果返回类型是被代理类型的父类或者接口,有可能是返回this引用,需要用INVOKE_TARGET对返回值做处理

if(logger.isDebugEnabled()) {

logger.debug( "Method return type is assignable from target type and "+

"may therefore return 'this' - using INVOKE_TARGET: "+ method);

}

returnINVOKE_TARGET;

}

else{

if(logger.isDebugEnabled()) {

logger.debug( "Method return type ensures 'this' cannot be returned - "+

"using DISPATCH_TARGET: "+ method);

}

// 不需要拦截,直接返回目标调用

returnDISPATCH_TARGET;

}

}

}

这里的核心是把advised对象转成了Callback,注册到Enhancer中,那么拦截器链的执行应该是在

Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

// 下面这段代码在我们调试Spring的时候回经常进来,特别是进入一个Bean的方法后再返回上一级调用时,最常见的就是这里。

// 这段代码基本与JdkDynamicAopProxy的invoke方法一致

publicObject intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)throws Throwable {

Object oldProxy = null;

boolean setProxyContext = false;

Class<?> targetClass = null;

Object target = null;

try{

if( this.advised.exposeProxy) {

// 需要则暴露

// Make invocation available if necessary.

oldProxy = AopContext.setCurrentProxy(proxy);

setProxyContext = true;

}

// May be null. 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<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

Object retVal;

// 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.

// 如果链是空且是public方法,则直接调用

Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);

retVal = methodProxy.invoke(target, argsToUse);

}

else{

// We need to create a method invocation...

// 否则创建一个CglibMethodInvocation以便驱动拦截器链

retVal = newCglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();

}

// 处理返回值,同JDK动态代理

retVal = processReturnType(proxy, target, method, retVal);

returnretVal;

}

finally {

if(target != null) {

releaseTarget(target);

}

if(setProxyContext) {

// Restore old proxy.

AopContext.setCurrentProxy(oldProxy);

}

}

}

这个和上面的jdk动态代理的invoke就比较像了,一样有List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

最终的执行则是:

retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();

一样是转换为了aopalliance的invocation。注意CglibMethodInvocation是ReflectiveMethodInvocation的子类。区别在于CglibMethodInvocation内维护了cglib的MethodProxy,调用链执行完进行最终真实调用时,是调用了methodProxy.invoke(this.target, this.arguments)。

protectedObject invokeJoinpoint()throws Throwable {

if( this.publicMethod) {

returnthis.methodProxy.invoke( this.target, this.arguments);

}

else{

returnsuper.invokeJoinpoint();

}

}

其父类ReflectiveMethodInvocation的该方法是:

protectedObject invokeJoinpoint()throws Throwable {

returnAopUtils.invokeJoinpointUsingReflection( this.target, this.method, this.arguments);

}

到这里基本问题都已经解决,还差最后一个优化点没有说,上面的FixedChainStaticTargetInterceptor与DynamicAdvisedInterceptor的区别在哪?代码如下,一看便知

publicObject intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)throws Throwable {

// 直接生成了CglibMethodInvocation,因为adviceChain是固定不变的,故在创建时已经传入,不需要每次执行时动态再计算了。

// 省略了暴露代理判断,无需进行context设置

MethodInvocation invocation = newCglibMethodInvocation(proxy, this.target, method, args,

this.targetClass, this.adviceChain, methodProxy);

// If we get here, we need to create a MethodInvocation.

Object retVal = invocation.proceed();

retVal = processReturnType(proxy, this.target, method, retVal);

returnretVal;

}

致此结束,后面进行总结。

总结

再回顾一下上面的config对象,config为AdvisedSupport对象,其实整体是个代理配置对象

publicclassProxyConfig implements Serializable

- publicclassAdvisedSupport extends ProxyConfig implements Advised

-- publicclassProxyCreatorSupport extends AdvisedSupport

--- publicclassProxyFactory extends ProxyCreatorSupport

最下层的ProxyFactory包含了特殊的功能,只能创建proxy对象,他是通过AopProxyFactory来做的:

publicObject getProxy(){

returncreateAopProxy().getProxy();

}

createAopProxy()方法是ProxyCreatorSupport类支持的:

protectedfinal synchronized AopProxy createAopProxy(){

if(! this.active) {

activate();

}

returngetAopProxyFactory().createAopProxy( this);

}

publicAopProxyFactory getAopProxyFactory(){

returnthis.aopProxyFactory;

}

publicProxyCreatorSupport(){

this.aopProxyFactory = newDefaultAopProxyFactory();

}

这样,ProxyFactory(AdvisedSupport config)就和AopProxyFactory有了联系,AopProxyFactory和AopProxy也有了联系,AopProxy和Proxy也有了联系。

结论

那么最终的结论是,Spring使用了Jdk动态代理和Cglib做代理,但是会把两种代理的拦截器转换为aopalliance这种标准形式进行处理。但是在公开给外部时,其实使用的是advisor这种形式,都注册为advisor或者advised即可。这样就统一了入口。

AspectJ框架也使用了aopalliance这种标准形式进行AOP代理,Spring对AspectJ在上层也有包装,可以研究一下。

相关研究

Spring与aopalliance标准相关的类图 SpringAopAlliance Advice实现类中有一些adaptor,以及org.springframework.aop.framework.adapter包下一些其他适配器,他们的作用是把advice包装为advisor,把advice包装为MethodInterceptor。
Spring其他声明代理对象Bean的方法 1.BeanNameAutoProxyCreator
// org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator

@ Bean

publicBeanNameAutoProxyCreator beanNameAutoProxyCreator(){

BeanNameAutoProxyCreator beanNameAutoProxyCreator = newBeanNameAutoProxyCreator();

beanNameAutoProxyCreator.setBeanNames( "test");

beanNameAutoProxyCreator.setInterceptorNames( "testInterceptor");

returnbeanNameAutoProxyCreator;

}

基本原理是使用BeanNameAutoProxyCreator自动对特定的Bean转换为特定拦截包装后的代理Bean,依然是使用了BeanPostProcessor,相关类参考下面。

publicclassBeanNameAutoProxyCreator extends AbstractAutoProxyCreator

publicabstract classAbstractAutoProxyCreator extends ProxyProcessorSupport

implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware

publicclassProxyProcessorSupport extends ProxyConfig implements Ordered, BeanClassLoaderAware, AopInfrastructureBean

publicinterface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor

publicinterface InstantiationAwareBeanPostProcessor extends BeanPostProcessor

ii. 使用@Aspect自动织入拦截器

@Component

@Aspect

publicclassLogAspect {

@Pointcut( "execution(* com.demo.service..*.*(..))")

publicvoidinServiceLayer(){ }

@Before(value = "execution(public * com.demo.service..*.*(..))")

publicvoidbeforeShow(){

System.out.println( "before show.");

}

@After(value = "execution(public * com.demo.service..*.*(..))")

publicvoidafterShow(){

System.out.println( "after show.");

}

@Around( "inServiceLayer()")

publicObject around(ProceedingJoinPoint thisJoinPoint)throws Throwable {

returnthisJoinPoint.proceed();

}

}

详细原理参考3

Spring中@Aspect注解声明的各种接入点是如何代理到Bean里面的,以及@Pointcut、@Before、@After、@AfterReturning、@AfterThrowing、@Around被包装为了什么。

4. 其他各种注解如何影响对象,如@Async、@Transactional(参考5)等。

基本原理是在@Async等的bpp(BeanPostProcessor,详细作用参考后续文章)的处理阶段中,检查目标bean是否被标记Advised接口,如果是则直接添加自己声明的实现特定功能的advisor,否则则使用ProxyFactory生成代理并添加自己的advisor。最终返回代理对象实例。

5.Transaction 在 Controller 层的探索

补充案例

Spring中一个动态代理实例,一个类中的一个方法,直接调用本类的@Async方法不触发代理,而@Configuration注解配置类却可以进行代理。为什么?

@Component

publicclassAsyncService {

AsyncService asyncService;

publicvoidsetCurrent(AsyncService asyncService){

this.asyncService = asyncService;

}

publicvoidasync1(){

System.out.println( "1:"+ Thread.currentThread().getName());

// 通过代理对象调用

asyncService.async3();

// 通过this调用,不通过代理。因为this不是代理对象,而是真实对象。

this.async3();

// 即使创建了代理,最后一层的调用仍然是调用原始对象的对应方法,而不是使用代理对象的super.method()来进行调用的。

}

publicvoidasync2(){

System.out.println( "2:"+ Thread.currentThread().getName());

async3();

}

@ Async

publicvoidasync3(){

System.out.println( "3:"+ Thread.currentThread().getName());

}

}

当基于接口进行代理时,又是怎样的一种情况?

欲知详情,可参考本人下一篇文章

小技巧

1.如何导出被cglib代理的类:

Spring调用Enhance生成类时,最终总会生成类的字节码,在生成的地方导出即可,调试下发现是在这里:

org.springframework.cglib.core.DefaultGeneratorStrategy.generate(ClassGenerator cg)方法。

cglib生成类时,callbackFilter是生成时已经确定的,而不是动态调用filter来获得要调用的callback。即类生成时,每个方法要调用的callback已经自动织入到被代理方法的调用中了。在callbackFilter的accept方法中打断点,就能看到整个类的生成过程了。找到生成类的字节码也是在这里打断点找到的。

导出类文件:

File file = newFile( "E:Test.class");

// 建立输出字节流

FileOutputStream fos = null;

try{

fos = newFileOutputStream(file);

} catch(FileNotFoundException e) {

e.printStackTrace();

}

// 用FileOutputStream 的write方法写入字节数组

try{

fos.write(b);

} catch(IOException e) {

e.printStackTrace();

}

System.out.println( "写入成功");

// 为了节省IO流的开销,需要关闭

try{

fos.close();

} catch(IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

也可使用javaagent来导出,见后面。

扩展知识

Advice:增强,在目标方法范围内织入

Introduction: 引介,直接在类级别上添加目标未实现的接口方法

上面提到的动态代理有两种:

Jdk动态代理 Jdk自带的动态代理,使用Sun内部实现动态生成类,限制是只能对接口进行动态代理。
CGLIB动态字节码生成 动态生成现有类的子类并加载,可代理非接口。缺点是对于final声明的类以及private的方法无法进行代理。
除了上述两种方法外,还有以下三种代理方式返回搜狐,查看更多

自定义类加载器 通过自定义的类加载器,在类加载前对原类字节码进行替换,返回加入动态代理后的类的字节码加载到内存中。这种方式可代理任意类、接口。包括private方法和final类。但是当项目中使用了一些其他类加载器时,会导致使用其他类加载器的类代理无效化。参考FakeClassloader。
使用java agent进行字节码转换 使用java.lang.Instrumentation接口提供的方法,在java agent的方法中进行动态字节码转换。 对于预先加载的agent,可使用premain在main方法执行前进行类替换。对于动态attach的java agent,可在agentmain方法中动态替换当前内存中的类。 对于预先加载的agent来说,这种方式几乎是万能的,除了需要额外加入启动参数外,几乎没有缺点。而对于动态attach的,则略微有些限制,只能替换方法中的实现,而不能修改方法签名。
静态AOP 例如AspectJ框架,就是个静态代理的框架,在编译期直接编译进入字节码。对系统性能几乎无损耗,但是灵活度略微有些欠缺。

Copyright @ 2014-2015 我爱加倍游 版权所有

提示:“我爱加倍游”仅能对游戏进行加速,谢绝用于任何非法用途!