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
可見(jiàn),代理類中生成了目標(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è)方法沒(méi)有參數(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
可見(jiàn),代理類中生成了目標(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-03
struts2單個(gè)文件上傳的兩種實(shí)現(xiàn)方式
這篇文章主要介紹了struts2單個(gè)文件上傳的兩種實(shí)現(xiàn)方式,有需要的朋友可以參考一下2014-01-01
Java實(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-12
Java VisualVM監(jiān)控遠(yuǎn)程JVM(詳解)
下面小編就為大家?guī)?lái)一篇Java VisualVM監(jiān)控遠(yuǎn)程JVM(詳解)。小編覺(jué)得挺不錯(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-10
Java實(shí)現(xiàn)迅雷地址轉(zhuǎn)成普通地址實(shí)例代碼
本篇文章主要介紹了Java實(shí)現(xiàn)迅雷地址轉(zhuǎn)成普通地址實(shí)例代碼,非常具有實(shí)用價(jià)值,有興趣的可以了解一下。2017-03-03
Spring Bean的實(shí)例化之屬性注入源碼剖析過(guò)程
本篇文章主要就是分析Spring源碼剖析-Bean的實(shí)例化-屬性注入的相關(guān)知識(shí),通過(guò)本文學(xué)習(xí)AbstractAutowireCapableBeanFactory#populateBean 方法的主要功能就是屬性填充,感興趣的朋友跟隨小編一起看看吧2021-06-06
詳解springboot解決第三方依賴jar包的問(wèn)題
本篇文章主要介紹了詳解springboot解決第三方依賴jar包的問(wèn)題,解決了第三方依賴jar包的問(wèn)題,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09

