一、CGLib jar包下載
百度網盤:
鏈接:https://pan.baidu.com/s/1O_5o_vtPWEZ3Hy0CHlZDug
提取碼:5wf6
CGLib要使用還需要額外的asm.jar
鏈接:https://pan.baidu.com/s/1874lFlpOLsdzPUs7O9Ol-g
提取碼:wf68
二、CGLib應用案例
package demo.knowledgepoints.cglib; public class BaseDemo { private String Name; public String getName() { return Name; } public void setName(String name) { Name = name; } @Override public String toString() { return "BaseDemo{" + "Name='" + Name + '\'' + '}'; } }
package demo.knowledgepoints.cglib; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class MyMethodInterceptor implements MethodInterceptor { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("=============執行自己想要的內容start================"); System.out.println("method.getName():" + method.getName()); Object object = methodProxy.invokeSuper(o,objects); System.out.println("=============執行自己想要的內容end================"); return object; } }
package demo.knowledgepoints.cglib; import net.sf.cglib.core.DebuggingClassWriter; import net.sf.cglib.proxy.Enhancer; public class CGLibTest { public static void main(String[] args) { System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "src\\demo\\knowledgepoints\\cglib"); /** * 該類為CGLib設置動態代理的核心,你設置一個怎么樣的動態代理 */ Enhancer enhancer = new Enhancer(); /*******設置需要被代理的類**************/ enhancer.setSuperclass(BaseDemo.class); /*******設置代理類**************/ enhancer.setCallback(new MyMethodInterceptor()); /*******創建代理類**************/ BaseDemo proxyBaseDemo = (BaseDemo)enhancer.create(); proxyBaseDemo.setName("李磊"); } }
運行結果:
這里會出現一個比較有意思的情況,如果是dubug運行會出現如下打印信息
簡單解釋一下:因為IDEA duebug下,你會需要查詢信息,而這些信息其實就是IDEA默認在調用你對象的toString方法。IDEA執行的toString當然也被代理了。
三、CGLib動態代理原理
CGLib動態代理原理和JDK動態原理本質區別很大。
CGLib動態代理原理:是通過子類繼承來實現動態代理的。上面的應用程序我們已經將CGLib的代理類生成到本地:
我們可以看看反編譯后里面的代碼。
public class BaseDemo$$EnhancerByCGLIB$$3c73e677 extends BaseDemo implements Factory{ final String CGLIB$toString$0() { return super.toString(); } public final String toString() { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (this.CGLIB$CALLBACK_0 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$0$Method, CGLIB$emptyArgs, CGLIB$toString$0$Proxy) : super.toString(); } final String CGLIB$getName$1() { return super.getName(); } public final String getName() { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (this.CGLIB$CALLBACK_0 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } return var10000 != null ? (String)var10000.intercept(this, CGLIB$getName$1$Method, CGLIB$emptyArgs, CGLIB$getName$1$Proxy) : super.getName(); } final void CGLIB$setName$2(String var1) { super.setName(var1); } public final void setName(String var1) { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (this.CGLIB$CALLBACK_0 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } if (var10000 != null) { var10000.intercept(this, CGLIB$setName$2$Method, new Object[]{var1}, CGLIB$setName$2$Proxy); } else { super.setName(var1); } } }
上述代碼是我取了其中比較重要的信息,真實代理類,還會多一些代碼。
從上面的文件內容可以看出:
1. 繼承了BaseDemo
2. 實現Factory 接口,該接口可以創建對象等功能。
3. 重寫了父類方法,並且還是會調用原父類方法。
更多使用方法見CGLib API :http://devdoc.net/javamisc/cglib-3.2.5/