一、Spring抽象出了AopProxy接口,用处:
1)用来抽象JDK和Cglib
2)暗示统一了他们的自调用行为:调用Target的方法。
Note:CGlib可以实现自调用时走代理对象,但是Spring统一了动态代理的规则,使其和jdk的动态代理保持一致,致使程序在使用不同的代理时能表现一致。(非不能也,实不为也。)
二、CglibAopProxy源码
从以下代码的路径中可以发现,Cglib使用methodProxy.invoke(target, argsToUse)
而非methodProxy.invoke(proxy, argsToUse)
,来保持和jdk动态代理同样的逻辑。
- 位置:org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept
public Object 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
位置:org.springframework.aop.framework.CglibAopProxy.CglibMethodInvocation
private static class CglibMethodInvocation extends ReflectiveMethodInvocation {
private final MethodProxy methodProxy;
private final boolean publicMethod;
public CglibMethodInvocation(Object proxy, Object target, Method method, Object[] arguments,
Class> targetClass, List
位置:org.springframework.aop.support.AopUtils#invokeJoinpointUsingReflection
public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)
throws Throwable {
// Use reflection to invoke the method.
try {
ReflectionUtils.makeAccessible(method);
return method.invoke(target, args);
}
catch (InvocationTargetException ex) {
// Invoked method threw a checked exception.
// We must rethrow it. The client won't see the interceptor.
throw ex.getTargetException();
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
method + "] on target [" + target + "]", ex);
}
catch (IllegalAccessException ex) {
throw new AopInvocationException("Could not access method [" + method + "]", ex);
}
}