本文來分析 Spring 中 JdkDynamicAopProxy
代理對(duì)象的生成 getProxy()
方法和攔截增強(qiáng) invoke
方法的相關(guān)處理邏輯。
上文我們研究過了 Pointcut
和 Advice
(Advisor
)接口以及它們?cè)?Spring AOP
代理中的作用永品,并利用幾個(gè) Demo 演示了其相關(guān)關(guān)系辽故。
為了方便閱讀,把上文中的 ProxyFactoryDemo
類代碼再次貼出來腐碱。
public class ProxyFactoryDemo {
public static void main(String[] args) {
// 1. 構(gòu)造目標(biāo)對(duì)象
Cat catTarget = new Cat();
// 2. 通過目標(biāo)對(duì)象誊垢,構(gòu)造 ProxyFactory 對(duì)象
ProxyFactory factory = new ProxyFactory(catTarget);
// 添加一個(gè)方法攔截器
factory.addAdvice(new MyMethodInterceptor());
// 3. 根據(jù)目標(biāo)對(duì)象生成代理對(duì)象
Object proxy = factory.getProxy();
Animal cat = (Animal) proxy;
cat.eat();
}
}
源碼分析
首先掉弛,我們從 ProxyFactory
類的 getProxy()
方法開始分析。
public Object getProxy() {
return createAopProxy().getProxy();
}
createAopProxy()
是 ProxyFactory
父類 ProxyCreatorSupport
中的方法的主要是根據(jù)當(dāng)前的 config
信息判斷是生成 JDK 動(dòng)態(tài)代理還是 CGLIB 動(dòng)態(tài)代理喂走。
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
// 1. 獲取 AopProxyFactory 工廠殃饿,用來創(chuàng)建 AopProxy 對(duì)象
// 注意 createAopProxy 的參數(shù) this,this 就是在 ProxyFactoryDemo 中定義的 ProxyFactory 對(duì)象芋肠。
return getAopProxyFactory().createAopProxy(this);
}
/*
* 子類構(gòu)造函數(shù)中如果不顯示調(diào)用父類的構(gòu)造函數(shù)乎芳,則會(huì)自動(dòng)調(diào)用父類的無參構(gòu)造函數(shù)
* 所以,ProxyCreatorSupport() 方法會(huì)在 ProxyFactory factory = new ProxyFactory(catTarget); 調(diào)用時(shí)被調(diào)用
*/
public ProxyCreatorSupport() {
this.aopProxyFactory = new DefaultAopProxyFactory();
}
public AopProxyFactory getAopProxyFactory() {
// DefaultAopProxyFactory 對(duì)象
return this.aopProxyFactory;
}
下面我們繼續(xù)來看 DefaultAopProxyFactory
類中的 createAopProxy
方法帖池。
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// config.isOptimize() 這個(gè)屬性沒有研究過
// 滿足下面三個(gè)條件的任意一個(gè)
// 1. 如果 optimize 屬性為 ture
// 2. 或者 proxyTargetClass 屬性為 ture
// 3. 被代理類沒有可代理的接口
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
// 如果被代理類的類型是接口奈惑,或者被代理類是 JDK 動(dòng)態(tài)代理生成的代理類,則使用 JDK 動(dòng)態(tài)代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 使用 CGLIB 動(dòng)態(tài)代理
return new ObjenesisCglibAopProxy(config);
}
else {
// 使用 JDK 動(dòng)態(tài)代理
return new JdkDynamicAopProxy(config);
}
}
ObjenesisCglibAopProxy
類在下一篇文章講解睡汹,先來看 JdkDynamicAopProxy
類的 getProxy()
方法肴甸。
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
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);
// 查找被代理的接口中是否包含 equals 和 hashCode 方法,如果有囚巴,則在代理類中進(jìn)行相應(yīng)的標(biāo)記原在,
// 從而在 invoke 方法中直接調(diào)用相關(guān)的方法,避免遞歸調(diào)用導(dǎo)致棧溢出
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 這里就是我們熟悉的 Proxy.newProxyInstance 方法了彤叉,用來生成 JDK 動(dòng)態(tài)代理對(duì)象庶柿。
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
// advised 就是在 ProxyFactoryDemo 中定義的 ProxyFactory 對(duì)象。
this.advised = config;
}
AopProxyUtils
類中的的 completeProxiedInterfaces()
方法需要講解下秽浇。
/**
* 返回要為給定 AOP 配置代理的完整接口集浮庐。
* 始終添加 SpringProxy 接口
* 如果 opaque 標(biāo)記為 false,則始終添加 Advised 接口
* @param advised 代理配置
* @param decoratingProxy 為 ture 則添加 DecoratingProxy 接口
*/
static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
// 1. 獲取到所有需要被代理的接口
Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
// 如果被代理的接口集合中沒有 SpringProxy 接口柬焕,則需要添加 SpringProxy 接口到被代理集合集合中
boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
// 如果 opaque 為 false(默認(rèn)是 false)审残,且被代理的接口集合中沒有 Advised 接口,則需要添加 Advised 接口到被代理集合集合中
boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);
// decoratingProxy 為 ture击喂,且被代理的接口集合中沒有 DecoratingProxy 接口维苔,則需要添加 DecoratingProxy 接口到被代理集合集合中
boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class));
// 省略添加邏輯...
return proxiedInterfaces;
}
由此,我們就知道了 JdkDynamicAopProxy
代理類的生成邏輯懂昂。
然后我們?cè)賮砜?JdkDynamicAopProxy
類的 invoke
方法介时。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// 不代理 equals 方法,通過 JdkDynamicAopProxy 中定義的 equals 方法進(jìn)行比較
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// 不代理 hashCode 方法凌彬,調(diào)用 JdkDynamicAopProxy 中定義的 hashCode 方法
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// DecoratingProxy 接口中只有 getDecoratedClass 方法沸柔,通過下面的方法實(shí)現(xiàn)其邏輯
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// opaque 為 false 才可能代理 Advised 接口
// 如果 method 是在 Advised 中聲明的,則直接把 method 轉(zhuǎn)移到 advised 對(duì)象上調(diào)用铲敛。
// 這樣就可以通過代理對(duì)象直接操作代理的配置褐澎,比如新增 Advisor。
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
// 如果需要在攔截器暴露 proxy 對(duì)象伐蒋,則把 proxy 對(duì)象添加到 ThreadLocal 中
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 獲取目標(biāo)對(duì)象和目標(biāo)對(duì)象類型
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 獲取此方法的攔截器鏈工三,這個(gè)方法后面會(huì)進(jìn)行討論
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
// 如果攔截器集合為空迁酸,說明當(dāng)前 method 不需要被增強(qiáng),則通過反射直接調(diào)用目標(biāo)對(duì)象上的方法
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 創(chuàng)建 ReflectiveMethodInvocation俭正,用來管理方法攔截器責(zé)任鏈
// 類似于 【Spring AOP (四) 多重代理和責(zé)任鏈模式】 中的 MyMethodInvocationImpl
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 通過 invocation.proceed 驅(qū)動(dòng)方法攔截器責(zé)任鏈的運(yùn)行奸鬓,并獲取到返回值。
retVal = invocation.proceed();
}
// 返回 this掸读,需要替換為 proxy 對(duì)象
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 (setProxyContext) {
// 把第一次調(diào)用 setCurrentProxy 返回的對(duì)象串远,重新設(shè)置到 ThreadLocal 中
AopContext.setCurrentProxy(oldProxy);
}
}
}
我們接下來分析一下在 invoke
方法中值得關(guān)注的地方。
advised
的 getInterceptorsAndDynamicInterceptionAdvice
方法儿惫,此方法定義在 AdvisedSupport
類中澡罚。
AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory();
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
// 1. 定義 method 的 cacheKey,用來緩存結(jié)果
MethodCacheKey cacheKey = new MethodCacheKey(method);
// 2. 從緩存中獲取 method 的攔截器列表
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
// 3. 通過 DefaultAdvisorChainFactory的 getInterceptorsAndDynamicInterceptionAdvice 獲取 method 的攔截器列表
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
// 4. 保存 method 的攔截器列表到緩存中
this.methodCache.put(cacheKey, cached);
}
return cached;
}
getInterceptorsAndDynamicInterceptionAdvice
方法中涉及 DefaultAdvisorChainFactory
類中的相關(guān)代碼清單如下所示肾请。
// 省略了方法中關(guān)于 Introduction 增強(qiáng)的處理邏輯
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// // 獲取一個(gè)全局唯一的 AdvisorAdapterRegistry 對(duì)象
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
// 這里的 config留搔,就是最開始定義的 ProxyFactory 對(duì)象
// 獲取到所有的 Advisor
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
for (Advisor advisor : advisors) {
// 如果 advisor 是 PointcutAdvisor 類型
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
// 如果 preFiltered 為 ture,或者目標(biāo)對(duì)象類型滿足 ClassFilter 的條件筐喳,則進(jìn)行下面的處理
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
// 進(jìn)行方法的靜態(tài)匹配
match = mm.matches(method, actualClass);
if (match) {
// 匹配則把 advisor 中的 Advice(MethodInterceptor 是 Advice 的子接口) 添加方法攔截器列表
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// 如果需要進(jìn)行方法的動(dòng)態(tài)匹配催式,則轉(zhuǎn)換為 InterceptorAndDynamicMethodMatcher 類型函喉,在 invoke 方法調(diào)用時(shí)進(jìn)行動(dòng)態(tài)匹配
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
// 不是 PointcutAdvisor 說明沒有 Pointcut避归,則匹配所有方法
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
getInterceptorsAndDynamicInterceptionAdvice
方法中一個(gè)容易忽略的地方就是 AdvisorAdapterRegistry
接口和其 getInterceptors
方法。
GlobalAdvisorAdapterRegistry
類的代碼清單如下所示管呵。
public final class GlobalAdvisorAdapterRegistry {
private GlobalAdvisorAdapterRegistry() {
}
/**
* 保存單個(gè)實(shí)例梳毙,以便我們給請(qǐng)求它的類使用。
*/
private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();
public static AdvisorAdapterRegistry getInstance() {
return instance;
}
static void reset() {
instance = new DefaultAdvisorAdapterRegistry();
}
}
DefaultAdvisorAdapterRegistry
類的代碼清單如下所示捐下。
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
/**
* 創(chuàng)建一個(gè)新的 DefaultAdvisorAdapterRegistry账锹,注冊(cè)默認(rèn)的 AdvisorAdapter。
*/
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
/**
* 返回給定 advice 的包裝類 advisor
* 默認(rèn)至少支持如下 Advice:
* org.aopalliance.intercept.MethodInterceptor
* org.springframework.aop.MethodBeforeAdvice
* org.springframework.aop.AfterReturningAdvice
* org.springframework.aop.ThrowsAdvice
*/
@Override
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
// 如果 adviceObject 已經(jīng)是 Advisor 實(shí)例坷襟,直接返回
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
// 如果 adviceObject 不是 Advice 實(shí)例奸柬,直接拋出異常
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// MethodInterceptor 不需要 wrap
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// 檢查 adapter 是否理解此 advice 對(duì)象? 即使用 Advisor 調(diào)用 getInterceptors 方法作為參數(shù)是否有效婴程?
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
// 如果上面的條件都不滿足廓奕,直接拋出異常
throw new UnknownAdviceTypeException(advice);
}
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
// 1. 如果 advice 是 MethodInterceptor 實(shí)例,直接添加到攔截器列表
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
// 2. 如果存在 adapter可以把 advisor 轉(zhuǎn)換為 MethodInterceptor档叔,也需要添加到攔截器列表
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
// 攔截器列表為空桌粉,則拋出異常
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
@Override
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
this.adapters.add(adapter);
}
}
我們繼續(xù)來看 AdvisorAdapter
的相關(guān)實(shí)現(xiàn)類中的 getInterceptor
方法。
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
// 返回 MethodInterceptor 接口實(shí)現(xiàn)類 MethodBeforeAdviceInterceptor
return new MethodBeforeAdviceInterceptor(advice);
}
}
class AfterReturningAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof AfterReturningAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice();
// 返回 MethodInterceptor 接口實(shí)現(xiàn)類 AfterReturningAdviceInterceptor
return new AfterReturningAdviceInterceptor(advice);
}
}
class ThrowsAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof ThrowsAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
// 返回 MethodInterceptor 接口實(shí)現(xiàn)類 ThrowsAdviceInterceptor
return new ThrowsAdviceInterceptor(advisor.getAdvice());
}
}
最后衙四,我們需要分析一下 ReflectiveMethodInvocation
類中 proceed
的邏輯铃肯,proceed
方法驅(qū)動(dòng)責(zé)任鏈模式的運(yùn)行。
/**
* 當(dāng)前攔截器列表索引传蹈,表示當(dāng)前已經(jīng)運(yùn)行到第幾個(gè) MethodInterceptor
*/
private int currentInterceptorIndex = -1;
public Object proceed() throws Throwable {
// 如果攔截器列表已經(jīng)執(zhí)行完畢押逼,則調(diào)用目標(biāo)對(duì)象的目標(biāo)方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 獲取責(zé)任鏈中的下一個(gè) MethodInterceptor步藕,用來對(duì)目標(biāo)方法做增強(qiáng)處理
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// 如果 interceptorOrInterceptionAdvice 是 InterceptorAndDynamicMethodMatcher 類型,說明需要對(duì)目標(biāo)方法進(jìn)行動(dòng)態(tài)匹配
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
// 方法動(dòng)態(tài)匹配成功挑格,才對(duì)目標(biāo)方法做增強(qiáng)處理
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// 方法動(dòng)態(tài)匹配失敗漱抓,則驅(qū)動(dòng)責(zé)任鏈向前運(yùn)行
return proceed();
}
}
else {
// 如果目標(biāo)方法不需要?jiǎng)討B(tài)匹配,則直接調(diào)用 MethodInterceptor 的 invoke 方法恕齐,對(duì)目標(biāo)方法做增強(qiáng)處理乞娄。
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
至此我們可以得知,Spring AOP 代理 是由如下兩個(gè)核心接口實(shí)現(xiàn)的显歧。
MethodInterceptor
接口中的invoke
方法對(duì)目標(biāo)方法做代理(增強(qiáng))處理仪或。MethodInvocation
接口中的proceed()
方法通過責(zé)任鏈模式對(duì)目標(biāo)方法做多重代理。在其實(shí)現(xiàn)類ReflectiveMethodInvocation
中實(shí)現(xiàn)此邏輯士骤。
Spring 中的 JDK AOP 代理類 JdkDynamicAopProxy
到這里就基本說完了范删,下一篇我們講解 CGLIB AOP 代理類 ObjenesisCglibAopProxy
類。
(正文完)
擴(kuò)展閱讀
- Spring AOP (一) 簡介
- Spring AOP (二) JDK 動(dòng)態(tài)代理
- Spring AOP (三) CGLIB 動(dòng)態(tài)代理
- Spring AOP (四) 多重代理和責(zé)任鏈模式
- Spring AOP(五)切入點(diǎn)和通知
喜歡本文的朋友們拷肌,歡迎關(guān)注微信公眾號(hào)【程序員小課堂】到旦,閱讀更多精彩內(nèi)容!