aop的一个例子
MockTask task = new MockTask();
ProxyFactory weaver = new ProxyFactory(task);
weaver.setInterfaces(new Class[]{ITask.class});
PrepareResourceBeforeAdvice beforeAdvice = new PrepareResourceBeforeAdvice();
ResourceCleanAfterReturningAdvice afterAdvice = new ResourceCleanAfterReturningAdvice();
weaver.addAdvice(beforeAdvice);
weaver.addAdvice(afterAdvice);
ITask proxyObject = (ITask) weaver.getProxy();
proxyObject.execute();
在本示例中,ProxyFactory.getProxy 会调用 JdkDynamicAopProxy.getProxy 获取代理类。
// JdkDynamicAopProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
在 getProxy 中为 newProxyInstance 的 InvocationHandler 参数传入 this,即 JdkDynamicAopProxy 就是一个 InvocationHandler 的实现,其 invoke 方法如下:
// JdkDynamicAopProxy
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 通过advised(创建对象时初始化)获得指定的advice
// 会将advice用相应的MethodInterceptor封装下
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 创建一个MethodInvocation
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 调用procced,开始进入拦截链(执行目标对象方法和MethodInterceptor的advice)
retVal = invocation.proceed();
}
return retVal;
}
首先获得指定的 advice,这里包含 beforeAdvice 和 afterAdvice 实例,但会用 MethodInterceptor 封装一层,为了后面的拦截链。
再创建一个 RelectiveMethodInvocation 对象,最后通过 proceed 进入拦截链。
RelectiveMethodInvocation 就是 Spring AOP 中 Joinpoint 的一个实现,其类图如下:
首先看下 RelectiveMethodInvocation 的构造函数:
protected ReflectiveMethodInvocation(
Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments,
@Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {
this.proxy = proxy;
this.target = target;
this.targetClass = targetClass;
this.method = BridgeMethodResolver.findBridgedMethod(method);
this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
}
做了些相关属性的赋值,然后看向 proceed 方法,如何调用目标对象和拦截器。
public Object proceed() throws Throwable {
// currentInterceptorIndex从-1开始
// 当达到已调用了所有的拦截器后,通过invokeJoinpoint调用目标对象的方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 获得拦截器,调用其invoke方法
// currentInterceptorIndex加1
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
currentInterceptorIndex 从 -1 开始,interceptorsAndDynamicMethodMatchers 里有两个拦截器,再由于减 1,所有调用目标对象方法的条件是currentInterceptorIndex等于 1。
首先由于 -1 != 1,会获得包含了 beforeAdvice 的MethodBeforeAdviceInterceptor 实例, currentInterceptorIndex 加 1 变为 0。调用其 invoke 方法,由于是 Before-Advice,所以先执行 beforeAdvice 的 before 方法,然后调用 proceed 进入拦截链的下一环。
// MethodBeforeAdviceInterceptor
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
又回到了 proceed 方法,0 != 1,再次获得 advice,这次获得的是包含 afterAdvice的 AfterReturningAdviceInterceptor实例, currentInterceptorIndex 加 1 变为 1。调用其 invoke 方法,由于是 After-Returning-Adivce,所以会先执行 proceed 进入拦截链的下一环。
// AfterReturningAdviceInterceptor
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
再次来到 proceed 方法,1 == 1,已调用完所有的拦截器,将执行目标对象的方法。然后 return 返回,回到 invoke 中,调用 afterAdvice 的 afterReturning。
所以在 Joinpoint 的实现中,通过 MethodInterceptor 完成了 目标对象方法和 Advice 的先后执行。

275

被折叠的 条评论
为什么被折叠?



