接著上一篇 Spring AOP(六)細(xì)究 JdkDynamicAopProxy 類 ,我們來繼續(xù)分析 Spring 中 CGLIB 代理對象的生成和如何對方法進(jìn)行增強(qiáng)處理的邏輯烈钞。
回到 DefaultAopProxyFactory
類中的 createAopProxy
方法多矮,我們發(fā)現(xiàn)有兩個 AOP 代理類稻薇,除了 JdkDynamicAopProxy
類還有 ObjenesisCglibAopProxy
類兔乞。
為了方便閱讀半夷,把上文中的 createAopProxy
方法的代碼清單再次貼出來机杜。
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// config.isOptimize() 這個屬性沒有研究過
// 滿足下面三個條件的任意一個
// 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 動態(tài)代理生成的代理類其弊,則使用 JDK 動態(tài)代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 使用 CGLIB 動態(tài)代理
return new ObjenesisCglibAopProxy(config);
}
else {
// 使用 JDK 動態(tài)代理
return new JdkDynamicAopProxy(config);
}
}
源碼分析
下面我們就從 ObjenesisCglibAopProxy
類開始分析,ObjenesisCglibAopProxy
類的代碼清單如下所示膀斋。
class ObjenesisCglibAopProxy extends CglibAopProxy {
private static final SpringObjenesis objenesis = new SpringObjenesis();
public ObjenesisCglibAopProxy(AdvisedSupport config) {
super(config);
}
@Override
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
// 通過 Objenesis 技術(shù)實(shí)例化代理對象
}
}
可以看到 ObjenesisCglibAopProxy
中就只有實(shí)例化代理對象的方法梭伐,getProxy()
方法在其父類 CglibAopProxy
類中定義,代碼清單如下所示仰担。
public Object getProxy() {
return getProxy(null);
}
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
// CGLIB 代理類通過繼承被代理類實(shí)現(xiàn)動態(tài)代理
// 1. 獲得需要被代理的的類
Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
// 如果被代理類已經(jīng)是被 CGLIB 代理過的了舶沛,則代理其父類,避免出現(xiàn) java.lang.ClassFormatError: Duplicate method name "newInstance" 異常
// 舉個例子:rootClass 是 【Spring AOP (三) CGLIB 動態(tài)代理】Service 的代理類 Service$$EnhancerByCGLIB$$bdabbd96 卷要,那么這里的 proxySuperClass 就是 Service
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
// 添加代理類實(shí)現(xiàn)的相關(guān)接口,addInterface 方法中會對接口做去重處理
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);
// 2. 配置 CGLIB Enhancer愉耙,還記得 【Spring AOP (三) CGLIB 動態(tài)代理】 中通過 enhancer 創(chuàng)建代理類的例子嗎?
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
// 設(shè)置被代理類為代理類的父類
enhancer.setSuperclass(proxySuperClass);
// 設(shè)置代理類需要實(shí)現(xiàn)的接口
// AopProxyUtils.completeProxiedInterfaces 方法在 【Spring AOP(六)細(xì)研JdkDynamicAopProxy類】中有詳細(xì)描述拌滋,這里就不贅述
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
// 設(shè)置 CGLIB 代理類的命名策略
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
// 設(shè)置 CGLIB 代理類字節(jié)碼的默認(rèn)生成策略
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
// 3. 獲取到生成代理類所需的所有 Callback
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// 一個 method 只能被一個 Callback 增強(qiáng)處理
// 4. 存在超過一個 Callback 的情況下朴沿,就需要設(shè)置 CallbackFilter,用來分配一個 method 由哪個 Callback 增強(qiáng)處理
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// 5. 生成代理類并創(chuàng)建代理類實(shí)例败砂。
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
接下來分析在 getProxy
方法中一些需要關(guān)注的地方赌渣。
SpringNamingPolicy
類的代碼清單如下所示。
public class SpringNamingPolicy extends DefaultNamingPolicy {
public static final SpringNamingPolicy INSTANCE = new SpringNamingPolicy();
@Override
protected String getTag() {
// DefaultNamingPolicy 中返回 ByCGLIB昌犹,
// 所有通過類名我們就可以知道是 Spring 生成的代理類坚芜,還是 CGLIB 原生生成的代理類
return "BySpringCGLIB";
}
}
DefaultNamingPolicy
類在 Spring AOP (三) CGLIB 動態(tài)代理 一文中已經(jīng)討論過了,這里就不再贅述斜姥。
getCallbacks
的代碼清單如下所示鸿竖。
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// Parameters used for optimization choices...
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
// 定義一個用于 AOP 調(diào)用的 MethodInterceptor (DynamicAdvisedInterceptor)
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// targetInterceptor 是不對方法做增強(qiáng)處理的 MethodInterceptor,直接在 intercept 調(diào)用目標(biāo)對象的目標(biāo)方法
Callback targetInterceptor;
if (exposeProxy) {
targetInterceptor = (isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
}
else {
targetInterceptor = (isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
}
// 不需要返回 this 的 method疾渴,可以用 StaticDispatcher 進(jìn)行代理千贯,即直接通過 target 對象調(diào)用目標(biāo)方法
Callback targetDispatcher = (isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
Callback[] mainCallbacks = new Callback[] {
aopInterceptor, // for normal advice
targetInterceptor, // invoke target without considering advice, if optimized
// 不需要增強(qiáng)的方法
new SerializableNoOp(),
targetDispatcher,
// 通過 advised 直接調(diào)用 Advised 接口的方法
this.advisedDispatcher,
// 專門用來處理 equals 方法的攔截器,和 JdkDynamicAopProxy 類似
new EqualsInterceptor(this.advised),
// 專門用來處理 equals 方法的攔截器搞坝,和 JdkDynamicAopProxy 類似
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// 忽略了 isStatic && isFrozen 條件的邏輯處理
callbacks = mainCallbacks;
return callbacks;
}
ProxyCallbackFilter
類的代碼清單如下所示,我們主要關(guān)注 accept
方法魁袜。
// CGLIB callback 數(shù)組索引常量
private static final int AOP_PROXY = 0; // DynamicAdvisedInterceptor
private static final int INVOKE_TARGET = 1; // StaticUnadvisedExposedInterceptor或 DynamicUnadvisedExposedInterceptor
private static final int NO_OVERRIDE = 2; // SerializableNoOp
private static final int DISPATCH_TARGET = 3; // StaticDispatcher
private static final int DISPATCH_ADVISED = 4; // AdvisedDispatcher
private static final int INVOKE_EQUALS = 5; // EqualsInterceptor
private static final int INVOKE_HASHCODE = 6; // HashCodeInterceptor
private static class ProxyCallbackFilter implements CallbackFilter {
private final AdvisedSupport advised;
/**
* 實(shí)現(xiàn) CallbackFilter.accept() 以返回我們需要的 Callbacks 數(shù)組中的 index 值桩撮。
*/
@Override
public int accept(Method method) {
// finalize 方法不需要代理類重寫
if (AopUtils.isFinalizeMethod(method)) {
return NO_OVERRIDE;
}
// Advised 接口的方法由 AdvisedDispatcher 增強(qiáng)處理,即直接調(diào)用 advised 中的對應(yīng)方法
if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return DISPATCH_ADVISED;
}
// equals 方法由 EqualsInterceptor 代理
if (AopUtils.isEqualsMethod(method)) {
return INVOKE_EQUALS;
}
// hashCode 方法由 HashCodeInterceptor 代理
if (AopUtils.isHashCodeMethod(method)) {
return INVOKE_HASHCODE;
}
Class<?> targetClass = this.advised.getTargetClass();
List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// chain 不為空峰弹,表示當(dāng)前 method 需要被增強(qiáng)處理
boolean haveAdvice = !chain.isEmpty();
boolean exposeProxy = this.advised.isExposeProxy();
boolean isStatic = this.advised.getTargetSource().isStatic();
boolean isFrozen = this.advised.isFrozen();
if (haveAdvice || !isFrozen) {
// 如果公開代理店量,讓其在整個攔截器責(zé)任鏈種可見,則必須使用 AOP_PROXY鞠呈,即 DynamicAdvisedInterceptor
if (exposeProxy) {
return AOP_PROXY;
}
String key = method.toString();
// 檢查我們是否有固定攔截器來增強(qiáng)當(dāng)前 method融师。
if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) {
// 通過 FixedChainStaticTargetInterceptor 對攔截器做特定的優(yōu)化處理
int index = this.fixedInterceptorMap.get(key);
return (index + this.fixedInterceptorOffset);
}
else {
// 否則使用 AOP_PROXY,即 DynamicAdvisedInterceptor
return AOP_PROXY;
}
}
else {
// 如果需要暴露代理對象蚁吝,或者 target 對象是可變的旱爆,則通過 StaticUnadvisedExposedInterceptor 代理
if (exposeProxy || !isStatic) {
return INVOKE_TARGET;
}
// 如果當(dāng)前方法的返回類型是目標(biāo)對象的類型,則通過 StaticUnadvisedExposedInterceptor 代理
Class<?> returnType = method.getReturnType();
if (targetClass != null && returnType.isAssignableFrom(targetClass)) {
return INVOKE_TARGET;
}
else {
// 否則窘茁,通過 StaticDispatcher 進(jìn)行代理
return DISPATCH_TARGET;
}
}
}
}
然后我們重點(diǎn)關(guān)注 Spring AOP
的實(shí)現(xiàn)邏輯怀伦,在 DynamicAdvisedInterceptor
類中可以看到完整的代碼清單。
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
private final AdvisedSupport advised;
public DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
}
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
// 如果需要在攔截器暴露 proxy 對象山林,則把 proxy 對象添加到 ThreadLocal 中
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 獲取目標(biāo)對象和目標(biāo)對象類型
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 獲取此方法的攔截器鏈房待,這個方法在【Spring AOP(六)細(xì)研JdkDynamicAopProxy類】種已經(jīng)討論過了,這里就不贅述了
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// 如果攔截器集合為空,說明當(dāng)前 method 不需要被增強(qiáng)桑孩,則通過 methodProxy 直接調(diào)用目標(biāo)對象上的方法
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// 創(chuàng)建 CglibMethodInvocation拜鹤,用來管理方法攔截器責(zé)任鏈
// 通過 proceed 方法驅(qū)動攔截器責(zé)任鏈的運(yùn)行,并獲取到返回值流椒。
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// 把第一次調(diào)用 setCurrentProxy 返回的對象敏簿,重新設(shè)置到 ThreadLocal 中
AopContext.setCurrentProxy(oldProxy);
}
}
}
}
可以看到 DynamicAdvisedInterceptor
類中的 intercept
方法和 JdkDynamicAopProxy
類的 invoke
方法十分類似。
最后镣隶,我們再來看下 CglibMethodInvocation
類的詳細(xì)代碼清單极谊。
private static class CglibMethodInvocation extends ReflectiveMethodInvocation {
@Nullable
private final MethodProxy methodProxy;
public CglibMethodInvocation(Object proxy, @Nullable Object target, Method method,
Object[] arguments, @Nullable Class<?> targetClass,
List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {
super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);
// 僅對非 Object 類的方法使用 methodProxy 進(jìn)行調(diào)用,詳見 invokeJoinpoint() 方法
this.methodProxy = (Modifier.isPublic(method.getModifiers()) &&
method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&
!AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method) ?
methodProxy : null);
}
/**
* 重寫 ReflectiveMethodInvocation 中通過反射調(diào)用目標(biāo)方法的邏輯
*/
@Override
protected Object invokeJoinpoint() throws Throwable {
if (this.methodProxy != null) {
return this.methodProxy.invoke(this.target, this.arguments);
}
else {
return super.invokeJoinpoint();
}
}
}
CglibMethodInvocation
類繼承了 ReflectiveMethodInvocation
類安岂,并且僅重寫了其 invokeJoinpoint()
方法轻猖,而 proceed
方法在 Spring AOP(六)細(xì)究 JdkDynamicAopProxy 類 中已經(jīng)詳細(xì)講解,所以這里就不再贅述域那。
至此咙边,Spring 中的 CGLIB AOP 代理 就基本說完了。
(正文完)