Java中Cglib代理類重寫邏輯詳解
前言
要看懂Spring Aop,必須先看懂不同cglib回調(diào)類型所應(yīng)用的方法,在代理類中的重寫邏輯。
引入包
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency>
Callback回調(diào)
Callback_NoOp
public class Callback_NoOp implements NoOp { }
Callback_MethodInterceptor
public class Callback_MethodInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("enter MethodInterceptor..."); return null; } }
Callback_LazyLoader
public class Callback_LazyLoader implements LazyLoader { @Override public Object loadObject() throws Exception { System.out.println("enter LazyLoader..."); return null; } }
Callback_InvocationHandler
public class Callback_InvocationHandler implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("enter InvocationHandler..."); return null; } }
Callback_FixedValue
public class Callback_FixedValue implements FixedValue { @Override public Object loadObject() throws Exception { System.out.println("enter Callback_FixedValue..."); return null; } }
Callback_Dispatcher
public class Callback_Dispatcher implements Dispatcher { @Override public Object loadObject() throws Exception { System.out.println("enter Callback_Dispatcher..."); return null; } }
CustomizedCallbackFilter
public class CustomizedCallbackFilter implements CallbackFilter { @Override public int accept(Method method) { String methodName = method.getName(); switch (methodName) { case "noOp": return 0; case "methodInterceptor": return 1; case "lazyLoader": return 2; case "invocationHandler": return 3; case "fixedValue": return 4; case "dispatcher": return 5; } return 0; } }
MyService
目標(biāo)類
public class MyService { public void noOp() { System.out.println("myService no op"); } public void methodInterceptor() { System.out.println("myService method interceptor"); } public void lazyLoader() { System.out.println("myService lazy loader"); } public void invocationHandler() { System.out.println("myService invocation handler"); } public void fixedValue() { System.out.println("myService fixed value"); } public void dispatcher() { System.out.println("myService dispatcher"); } }
Test01
public class Test01 { public static void main(String[] args) { System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\Projects\\learning\\proxy-dynamic-demo\\target\\classes"); Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(MyService.class); Callback_NoOp callback_noOp = new Callback_NoOp(); Callback_MethodInterceptor callback_methodInterceptor = new Callback_MethodInterceptor(); Callback_LazyLoader callback_lazyLoader = new Callback_LazyLoader(); Callback_InvocationHandler callback_invocationHandler = new Callback_InvocationHandler(); Callback_FixedValue callback_fixedValue = new Callback_FixedValue(); Callback_Dispatcher callback_dispatcher = new Callback_Dispatcher(); enhancer.setCallbacks(new Callback[]{ callback_noOp, callback_methodInterceptor, callback_lazyLoader, callback_invocationHandler, callback_fixedValue, callback_dispatcher }); enhancer.setCallbackFilter(new CustomizedCallbackFilter()); Object enhancedObj = enhancer.create(); } }
結(jié)論
NoOp
代理類中只會(huì)維護(hù)NoOp這個(gè)回調(diào)屬性,并不會(huì)生成目標(biāo)類MyService中的noOp所對(duì)應(yīng)的方法
MethodInterceptor
可見,代理類中生成了目標(biāo)類MyService中的methodInterceptor方法所對(duì)應(yīng)的 CGLIB$methodInterceptor$1 和 methodInterceptor方法 這種類型的回調(diào)最為常用,它里面利用了FastClass,這種FastClass建立了調(diào)用邏輯和方法簽名和索引之間的映射關(guān)系,能夠快速的根據(jù)索引找到所對(duì)應(yīng)的調(diào)用邏輯。
final void CGLIB$methodInterceptor$1() { // 直接調(diào)用父類的methodInterceptor方法 super.methodInterceptor(); } public final void methodInterceptor() { // 獲取綁定的回調(diào)對(duì)象 MethodInterceptor var10000 = this.CGLIB$CALLBACK_1; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_1; } // 如果有設(shè)置的話(框架里面一般都設(shè)置了) if (var10000 != null) { // 第一個(gè)參數(shù)就是當(dāng)前代理類對(duì)象this // 第二個(gè)參數(shù)是MyService的methodInterceptor方法 // 第三個(gè)參數(shù)是參數(shù),因?yàn)檫@個(gè)方法沒有參數(shù),就用固定的這個(gè)CGLIB$emptyArgs,如果有參數(shù)的話,就會(huì)傳入方法的參數(shù) // 最后一個(gè)參數(shù)是MethodProxy類型的,它與FastClass機(jī)制的使用相關(guān) var10000.intercept(this, CGLIB$methodInterceptor$1$Method, CGLIB$emptyArgs, CGLIB$methodInterceptor$1$Proxy); } else { super.methodInterceptor(); } }
LazyLoader
可見,代理類中生成了目標(biāo)類MyService中的lazyLoader方法所對(duì)應(yīng)的 lazyLoader 方法
public final void lazyLoader() { // 每次都會(huì)調(diào)用下面這個(gè)CGLIB$LOAD_PRIVATE_2()方法 ((MyService)this.CGLIB$LOAD_PRIVATE_2()).lazyLoader(); } private final synchronized Object CGLIB$LOAD_PRIVATE_2() { // 獲取CGLIB$LAZY_LOADER_2屬性,即綁定的回調(diào)對(duì)象 Object var10000 = this.CGLIB$LAZY_LOADER_2; // 如果從CGLIB$LAZY_LOADER_2屬性獲取的是null,則走下面邏輯 // 如果不為null,直接將結(jié)果返回,所以這種類型會(huì)將結(jié)果返回并保存, // 等下次調(diào)用,直接返回結(jié)果 // 也就是說(shuō)這種類型的回調(diào)對(duì)象只會(huì)被調(diào)用 1 次 if (var10000 == null) { // 如果還未綁定 LazyLoader var10001 = this.CGLIB$CALLBACK_2; if (var10001 == null) { CGLIB$BIND_CALLBACKS(this); var10001 = this.CGLIB$CALLBACK_2; } // 調(diào)用回調(diào)對(duì)象的loadObject方法, // 并將調(diào)用結(jié)果返回作為方法的返回值 // 并將返回的結(jié)果設(shè)置給this.CGLIB$LAZY_LOADER_2屬性 var10000 = this.CGLIB$LAZY_LOADER_2 = var10001.loadObject(); } // 返回調(diào)用結(jié)果或直接返回 return var10000; }
InvocationHandler
public final void invocationHandler() { try { // 獲取綁定的回調(diào)對(duì)象CGLIB$CALLBACK_3 InvocationHandler var10000 = this.CGLIB$CALLBACK_3; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_3; } // 直接調(diào)用回調(diào)對(duì)象的invoke方法,參數(shù)CGLIB$invocationHandler$0是MyService中的invocationHandler方法 var10000.invoke(this, CGLIB$invocationHandler$0, new Object[0]); } catch (Error | RuntimeException var1) { throw var1; } catch (Throwable var2) { throw new UndeclaredThrowableException(var2); } }
FixedValue
public final void fixedValue() { // 獲取綁定的回調(diào)對(duì)象 FixedValue var10000 = this.CGLIB$CALLBACK_4; if (var10000 == null) { // 如果還未綁定 CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_4; } // 每次調(diào)用都會(huì)調(diào)用回調(diào)對(duì)象的loadObject方法 var10000.loadObject(); }
Dispatcher
public final void dispatcher() { // 獲取綁定的回調(diào)對(duì)象 Dispatcher var10000 = this.CGLIB$CALLBACK_5; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_5; } // 調(diào)用回調(diào)對(duì)象的loadObject方法,將返回的結(jié)果去調(diào)用dispatcher方法 ((MyService)var10000.loadObject()).dispatcher(); }
[Cglib生成的代理類]
package com.zzhua.cglib.service; import java.lang.reflect.Method; import net.sf.cglib.core.ReflectUtils; import net.sf.cglib.core.Signature; import net.sf.cglib.proxy.Callback; import net.sf.cglib.proxy.Dispatcher; import net.sf.cglib.proxy.Factory; import net.sf.cglib.proxy.FixedValue; import net.sf.cglib.proxy.InvocationHandler; import net.sf.cglib.proxy.LazyLoader; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import net.sf.cglib.proxy.NoOp; import net.sf.cglib.proxy.UndeclaredThrowableException; public class MyService$$EnhancerByCGLIB$$91e58a41 extends MyService implements Factory { private boolean CGLIB$BOUND; private static final ThreadLocal CGLIB$THREAD_CALLBACKS; private static final Callback[] CGLIB$STATIC_CALLBACKS; private NoOp CGLIB$CALLBACK_0; private MethodInterceptor CGLIB$CALLBACK_1; private LazyLoader CGLIB$CALLBACK_2; private InvocationHandler CGLIB$CALLBACK_3; private FixedValue CGLIB$CALLBACK_4; private Dispatcher CGLIB$CALLBACK_5; private static final Method CGLIB$methodInterceptor$1$Method; private static final MethodProxy CGLIB$methodInterceptor$1$Proxy; private static final Object[] CGLIB$emptyArgs; private Object CGLIB$LAZY_LOADER_2; private static final Method CGLIB$invocationHandler$0; static void CGLIB$STATICHOOK1() { CGLIB$THREAD_CALLBACKS = new ThreadLocal(); CGLIB$emptyArgs = new Object[0]; Class var0 = Class.forName("com.zzhua.cglib.service.MyService$$EnhancerByCGLIB$$91e58a41"); Class var1; CGLIB$methodInterceptor$1$Method = ReflectUtils.findMethods(new String[]{"methodInterceptor", "()V"}, (var1 = Class.forName("com.zzhua.cglib.service.MyService")).getDeclaredMethods())[0]; CGLIB$methodInterceptor$1$Proxy = MethodProxy.create(var1, var0, "()V", "methodInterceptor", "CGLIB$methodInterceptor$1"); CGLIB$invocationHandler$0 = Class.forName("com.zzhua.cglib.service.MyService").getDeclaredMethod("invocationHandler"); } final void CGLIB$methodInterceptor$1() { super.methodInterceptor(); } public final void methodInterceptor() { MethodInterceptor var10000 = this.CGLIB$CALLBACK_1; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_1; } if (var10000 != null) { var10000.intercept(this, CGLIB$methodInterceptor$1$Method, CGLIB$emptyArgs, CGLIB$methodInterceptor$1$Proxy); } else { super.methodInterceptor(); } } public static MethodProxy CGLIB$findMethodProxy(Signature var0) { String var10000 = var0.toString(); switch(var10000.hashCode()) { case -1368021391: if (var10000.equals("methodInterceptor()V")) { return CGLIB$methodInterceptor$1$Proxy; } } return null; } public final void lazyLoader() { ((MyService)this.CGLIB$LOAD_PRIVATE_2()).lazyLoader(); } private final synchronized Object CGLIB$LOAD_PRIVATE_2() { Object var10000 = this.CGLIB$LAZY_LOADER_2; if (var10000 == null) { LazyLoader var10001 = this.CGLIB$CALLBACK_2; if (var10001 == null) { CGLIB$BIND_CALLBACKS(this); var10001 = this.CGLIB$CALLBACK_2; } var10000 = this.CGLIB$LAZY_LOADER_2 = var10001.loadObject(); } return var10000; } public final void invocationHandler() { try { InvocationHandler var10000 = this.CGLIB$CALLBACK_3; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_3; } var10000.invoke(this, CGLIB$invocationHandler$0, new Object[0]); } catch (Error | RuntimeException var1) { throw var1; } catch (Throwable var2) { throw new UndeclaredThrowableException(var2); } } public final void fixedValue() { FixedValue var10000 = this.CGLIB$CALLBACK_4; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_4; } var10000.loadObject(); } public final void dispatcher() { Dispatcher var10000 = this.CGLIB$CALLBACK_5; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_5; } ((MyService)var10000.loadObject()).dispatcher(); } public MyService$$EnhancerByCGLIB$$91e58a41() { CGLIB$BIND_CALLBACKS(this); } public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) { CGLIB$THREAD_CALLBACKS.set(var0); } public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) { CGLIB$STATIC_CALLBACKS = var0; } private static final void CGLIB$BIND_CALLBACKS(Object var0) { MyService$$EnhancerByCGLIB$$91e58a41 var1 = (MyService$$EnhancerByCGLIB$$91e58a41)var0; if (!var1.CGLIB$BOUND) { var1.CGLIB$BOUND = true; Object var10000 = CGLIB$THREAD_CALLBACKS.get(); if (var10000 == null) { var10000 = CGLIB$STATIC_CALLBACKS; if (var10000 == null) { return; } } Callback[] var10001 = (Callback[])var10000; var1.CGLIB$CALLBACK_5 = (Dispatcher)((Callback[])var10000)[5]; var1.CGLIB$CALLBACK_4 = (FixedValue)var10001[4]; var1.CGLIB$CALLBACK_3 = (InvocationHandler)var10001[3]; var1.CGLIB$CALLBACK_2 = (LazyLoader)var10001[2]; var1.CGLIB$CALLBACK_1 = (MethodInterceptor)var10001[1]; var1.CGLIB$CALLBACK_0 = (NoOp)var10001[0]; } } public Object newInstance(Callback[] var1) { CGLIB$SET_THREAD_CALLBACKS(var1); MyService$$EnhancerByCGLIB$$91e58a41 var10000 = new MyService$$EnhancerByCGLIB$$91e58a41(); CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; } public Object newInstance(Callback var1) { throw new IllegalStateException("More than one callback object required"); } public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) { CGLIB$SET_THREAD_CALLBACKS(var3); MyService$$EnhancerByCGLIB$$91e58a41 var10000 = new MyService$$EnhancerByCGLIB$$91e58a41; switch(var1.length) { case 0: var10000.<init>(); CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; default: throw new IllegalArgumentException("Constructor not found"); } } public Callback getCallback(int var1) { CGLIB$BIND_CALLBACKS(this); Object var10000; switch(var1) { case 0: var10000 = this.CGLIB$CALLBACK_0; break; case 1: var10000 = this.CGLIB$CALLBACK_1; break; case 2: var10000 = this.CGLIB$CALLBACK_2; break; case 3: var10000 = this.CGLIB$CALLBACK_3; break; case 4: var10000 = this.CGLIB$CALLBACK_4; break; case 5: var10000 = this.CGLIB$CALLBACK_5; break; default: var10000 = null; } return (Callback)var10000; } public void setCallback(int var1, Callback var2) { switch(var1) { case 0: this.CGLIB$CALLBACK_0 = (NoOp)var2; break; case 1: this.CGLIB$CALLBACK_1 = (MethodInterceptor)var2; break; case 2: this.CGLIB$CALLBACK_2 = (LazyLoader)var2; break; case 3: this.CGLIB$CALLBACK_3 = (InvocationHandler)var2; break; case 4: this.CGLIB$CALLBACK_4 = (FixedValue)var2; break; case 5: this.CGLIB$CALLBACK_5 = (Dispatcher)var2; } } public Callback[] getCallbacks() { CGLIB$BIND_CALLBACKS(this); return new Callback[]{this.CGLIB$CALLBACK_0, this.CGLIB$CALLBACK_1, this.CGLIB$CALLBACK_2, this.CGLIB$CALLBACK_3, this.CGLIB$CALLBACK_4, this.CGLIB$CALLBACK_5}; } public void setCallbacks(Callback[] var1) { this.CGLIB$CALLBACK_0 = (NoOp)var1[0]; this.CGLIB$CALLBACK_1 = (MethodInterceptor)var1[1]; this.CGLIB$CALLBACK_2 = (LazyLoader)var1[2]; this.CGLIB$CALLBACK_3 = (InvocationHandler)var1[3]; this.CGLIB$CALLBACK_4 = (FixedValue)var1[4]; this.CGLIB$CALLBACK_5 = (Dispatcher)var1[5]; } static { CGLIB$STATICHOOK1(); } }
到此這篇關(guān)于Java中Cglib代理類重寫邏輯詳解的文章就介紹到這了,更多相關(guān)Cglib代理類重寫邏輯內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java如何將int型數(shù)組轉(zhuǎn)為String型數(shù)組
這篇文章主要介紹了Java如何將int型數(shù)組轉(zhuǎn)為String型數(shù)組,本文給大家分享具體實(shí)現(xiàn)思路結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-03-03struts2單個(gè)文件上傳的兩種實(shí)現(xiàn)方式
這篇文章主要介紹了struts2單個(gè)文件上傳的兩種實(shí)現(xiàn)方式,有需要的朋友可以參考一下2014-01-01Java實(shí)現(xiàn)FTP服務(wù)器功能實(shí)例代碼
FTP(File Transfer Protocol 文件傳輸協(xié)議)是Internet 上用來(lái)傳送文件的協(xié)議,本文給大家分享Java實(shí)現(xiàn)FTP服務(wù)器功能實(shí)例代碼,對(duì)java實(shí)現(xiàn)ftp服務(wù)器相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧2015-12-12Java VisualVM監(jiān)控遠(yuǎn)程JVM(詳解)
下面小編就為大家?guī)?lái)一篇Java VisualVM監(jiān)控遠(yuǎn)程JVM(詳解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10使用MyBatis進(jìn)行數(shù)據(jù)庫(kù)映射的方式
這篇文章主要介紹了使用MyBatis進(jìn)行數(shù)據(jù)庫(kù)映射的方式,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-10-10Java實(shí)現(xiàn)迅雷地址轉(zhuǎn)成普通地址實(shí)例代碼
本篇文章主要介紹了Java實(shí)現(xiàn)迅雷地址轉(zhuǎn)成普通地址實(shí)例代碼,非常具有實(shí)用價(jià)值,有興趣的可以了解一下。2017-03-03Spring Bean的實(shí)例化之屬性注入源碼剖析過(guò)程
本篇文章主要就是分析Spring源碼剖析-Bean的實(shí)例化-屬性注入的相關(guān)知識(shí),通過(guò)本文學(xué)習(xí)AbstractAutowireCapableBeanFactory#populateBean 方法的主要功能就是屬性填充,感興趣的朋友跟隨小編一起看看吧2021-06-06