Spring aop 分析之一
分析Spring之前先看一个demo, 以对AOP有一个直观的了解:
package com.test.aop;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;
public class TestAOP {
public static void main(String[] args) {
ProxyFactory f = new ProxyFactory();
// 设置代理目标
f.setTarget(new Hello());
// 设置一个前置通知
f.addAdvice(new MethodBeforeAdvice() {
@Override
public void before(Method method, Object[] args, Object target)
throws Throwable {
System.out.println("start hello aop.....");
}
});
// 取得代理对象
IHello h = (IHello) f.getProxy();
h.hello();
}
}
interface IHello {
public void hello();
}
class Hello implements IHello {
@Override
public void hello() {
System.out.println("hello aop");
}
}
执行结果:
start hello aop.....
hello aop
二:
上述demo中IHello接口类型是通过
IHello h = (IHello) f.getProxy(); 方式获取的,f.getProxy()做了什么处理,
来看下getProxy()方法:
可以看出, 创建的AopProxy对象可能是 Cglib2AopProxy, JdkDynamicAopProxy, ProxyFactory .
这里只关注 JdkDynamicAopProxy
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
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);
}
注:
Class[] proxiedInterfaces= AopProxyUtils.completeProxiedInterfaces(this.advised); // 这里获取的proxiedInterfaces 包含了IHello接口
Return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); //返回的对象实现了 proxiedInterfaces 中的接口, 而proxiedInterfaces中包含IHello接口, 故可以被转换成 IHello类型
接下去看看调用代理对象的 hello方法时会做什么:
当调用hello()时会进入到下面的invoke函数
/**
* Implementation of <code>InvocationHandler.invoke</code>.
* <p>Callers will see exactly the exception thrown by the target,
* unless a hook method throws an exception.
*/
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 {
Object retVal = null;
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
// Get the interception chain for this method.
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // 得到拦截器链
if (chain.isEmpty()) { // 如果拦截器链为空, 就直接通过java反射调用目标对象的方法
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
}
else {
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed(); // 先执行拦截器链,等所有拦截器执行完后再执行目标对象方法
}
if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
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);
}
}
}
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed(); // 这里是怎么来执行拦截器的, 从ReflectiveMethodInvocation构造函数可以知道,invocation实例持有一个拦截器链
通过 invocation.proceed() 方法又是如何遍历拦截器的呢?
来看proceed方法:
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
// currentInterceptorIndex 当前拦截器执行索引, 如果已执行完毕所有拦截器, 则调用目标对象方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint(); // 调用目标对象方法
}
// 得到一个拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof 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)) {
return dm.interceptor.invoke(this); // 将this作为参数传入interceptor.invoke, interceptor中有一个通知, 执行完通知后,又会调用proceed方法, 这样就形成一个递归调用过程, 直到所有处理器都便利完成
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
最后以一个demo来 说明拦截器和MethodInvocation 之间相互调用过程
package com.test.aop;
import java.util.ArrayList;
import java.util.List;
public class Test {
public String test() {
return "hello test";
}
public static void main(String[] args) {
// 创建通知1
Advice advice1 = new Advice() {
@Override
public void advice() {
System.out.println("advice1....");
}
};
// 创建通知2
Advice advice2 = new Advice() {
@Override
public void advice() {
System.out.println("advice2....");
}
};
// 创建拦截器链
List<Interceptor> interceptorList = new ArrayList<Interceptor>();
interceptorList.add(new Interceptor(advice1));
interceptorList.add(new Interceptor(advice2));
// 创建目标对象
Test target = new Test();
// 创建Invocation
Invocation invocation = new Invocation(interceptorList, target);
Object ret = invocation.proceed(); // start
System.out.println(ret);
}
}
/**
* 模拟拦截器
*
*/
class Interceptor {
private Advice advice;
public Interceptor(Advice advice) {
this.advice = advice;
}
public Object invoke(Invocation invocation) {
advice.advice(); // 先执行通知
return invocation.proceed();
}
}
/**
* 模拟通知
*
*/
interface Advice {
public void advice();
}
/**
* 模拟调用
*
*/
class Invocation {
private int interceptorIndex = -1; // 当前拦截器链索引
private List<Interceptor> interceptorList; // 持有的拦截器链
private Test target;
public Invocation(List<Interceptor> interceptorList, Test target) {
this.interceptorList = interceptorList;
this.target = target;
}
public Object proceed() {
if (++interceptorIndex >= interceptorList.size()) {
return target.test();
}
Interceptor interceptor = interceptorList.get(interceptorIndex);
return interceptor.invoke(this);// 将当前实例作为invoke参数传入
}
}
执行结果:
advice1....
advice2....
hello test

