上文介紹了代理類是由默認AOP代理工廠DefaultAopProxyFactory中createAopProxy方法產生的。如果代理對象是接口類型,則生成JdkDynamicAopProxy代理;否則生成ObjenesisCglibAopProxy代理,ObjenesisCglibAopProxy代理是繼承於CglibAopProxy。下面先從熟悉的入手,選擇JdkDynamicAopProxy分析。
構造器
查看源碼,可以看到JdkDynamicAopProxy是一個final類,不能被繼承和實現。其實現了AopProxy, InvocationHandler, Serializable接口,如下所示:
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable
下面看看JdkDynamicAopProxy 構造器,源碼如下:
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
throw new AopConfigException("No advisors and no TargetSource specified");
}
this.advised = config;
}
從構造器可以看出,JdkDynamicAopProxy依賴於AdvisedSupport,根據config配置信息創建動態代理對象。代碼中config.getAdvisors()提供的是Advisor列表。
getProxy
getProxy 方法是實現AopProxy接口,源碼如下:
@Override
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
@Override
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, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
/**
* Finds any {@link #equals} or {@link #hashCode} method that may be defined
* on the supplied set of interfaces.
* @param proxiedInterfaces the interfaces to introspect
*/
private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) {
for (Class<?> proxiedInterface : proxiedInterfaces) {
Method[] methods = proxiedInterface.getDeclaredMethods();
for (Method method : methods) {
if (AopUtils.isEqualsMethod(method)) {
this.equalsDefined = true;
}
if (AopUtils.isHashCodeMethod(method)) {
this.hashCodeDefined = true;
}
if (this.equalsDefined && this.hashCodeDefined) {
return;
}
}
}
}
在創建代理時,既可以采用默認的類加載器,也可以指定特定的類加載器。JDK動態代理的代理對象是接口類型,先獲取被代理對象的完整接口、根據指定的類加載器以及實現的調用處理器應用靜態方法Proxy.newProxyInstance創建代理對象。
invoke
上文介紹了InvocationHandler 接口,invoke該接口中唯一一個定義的方法。JdkDynamicAopProxy 是final類並且實現了InvocationHandler 接口,那么也必然實現了invoke方法,其源碼如下:
@Override
public Object 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)) {
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
前面只是一些校驗,直接省略,步入重點。通過target = targetSource.getTarget()得到被代理對象的類名。再根據被代理類名和方法名得到攔截鏈,也即通知鏈。如下所示:
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
如果攔截鏈為空,則直接反射調用被代理方法,否則需要創建代理方法,此代理方法中已經加入附加處理(通知)。如下:
if (chain.isEmpty()) {
//處理被代理方法參數
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
//反射執行被代理方法
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 創建代理方法
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 執行代理方法
retVal = invocation.proceed();
}
反射執行被代理方法是調用工具類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);
}
}
創建代理方法是通過ReflectiveMethodInvocation實現的,然后調用proceed()方法執行攔截鏈和被代理方法。ReflectiveMethodInvocation實現了Joinpoint接口,其構造器如下:
protected ReflectiveMethodInvocation(
Object proxy, Object target, Method method, Object[] arguments,
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;
}
ReflectiveMethodInvocation調用proceed方法執行代理,proceed方法是在Joinpoint接口中定義的,ReflectiveMethodInvocation中進行了實現。具體實現如下:
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
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);
}
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);
}
}
從上面分析源碼大致可以了解Spring AOP 動態代理的設計思想,采用類加載器根據接口產生代理方法,代理方法是在原方法的基礎上加上通知鏈,以實現AOP功能。當執行方法時,判斷該方法通知鏈是否為空,若為空,則通過反射直接調用原方法;若不為空,則產生代理方法,執行代理方法。下一節將繼續探討Spring AOP 的另一種實現方法CGLIB
