CGLIB 簡介
-
為沒有實現接口的類提供代理
-
更好的性能
CGLIB 原理
-
原理:動態生成需要代理的子類,子類重寫代理類的非final方法。子類中采用方法攔截的奇數攔截所有父類的方法的調用,順勢織入橫切邏輯。
-
底層:使用ASM字節碼處理框架。
-
缺點:無法代理fianl方法。
CGLIB 應用
-
Spring AOP
CGLIB API
-
: 底層字節碼處理類,他們大部分與ASM有關系。 -
net.sf.cglib.transform: 編譯期或運行期類和類文件的轉換
-
net.sf.cglib.proxy: 實現創建代理和方法攔截器的類
-
net.sf.cglib.reflect: 實現快速反射和C#風格代理的類
-
net.sf.cglib.util: 集合排序等工具類
-
net.sf.cglib.beans: JAVABean相關的工具類
Code Example
Basic
package com.cclu.cglibproxy;
import java.util.HashMap;
import java.util.Map;
/**
* @author ChangCheng Lu
* @date 2023/8/20 15:59
*/
public class UserService {
private static final Map<String, String> nameMap;
private static final Map<String, String> addressMap;
static {
nameMap = new HashMap<>(3);
nameMap.put("1001", "木子");
nameMap.put("1002", "小一");
nameMap.put("1003", "阿同");
addressMap = new HashMap<>(3);
addressMap.put("1001", "漣水");
addressMap.put("1002", "淮安");
addressMap.put("1003", "上海");
}
public String getUserNameById(String userId) {
return nameMap.get(userId);
}
public String getAddressById(String userId) {
return addressMap.get(userId);
}
}
package com.cclu.cglibproxy;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @author ChangCheng Lu
* @date 2023/8/20 16:04
*/
public class LogInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("方法調用前...");
Object res = methodProxy.invokeSuper(o, objects);
System.out.println("方法調用后:"+res);
return res;
}
}
package com.cclu.cglibproxy;
import net.sf.cglib.proxy.Enhancer;
/**
* @author ChangCheng Lu
* @date 2023/8/20 16:10
*/
public class Client {
public static void mAIn(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class);
enhancer.setCallback(new LogInterceptor());
UserService userService = (UserService) enhancer.create();
userService.getUserNameById("1001");
userService.getAddressById("1003");
}
}
Filter、FixedValue
package com.cclu.cglibproxy;
import java.util.HashMap;
import java.util.Map;
/**
* @author ChangCheng Lu
* @date 2023/8/20 15:59
*/
public class UserService {
private static final Map<String, String> nameMap;
private static final Map<String, String> addressMap;
static {
nameMap = new HashMap<>(3);
nameMap.put("1001", "木子");
nameMap.put("1002", "小一");
nameMap.put("1003", "阿同");
addressMap = new HashMap<>(3);
addressMap.put("1001", "蘇州");
addressMap.put("1002", "淮安");
addressMap.put("1003", "上海");
}
public String getUserNameById(String userId) {
return nameMap.get(userId);
}
public String getAddressById(String userId) {
return addressMap.get(userId);
}
}
package com.cclu.cglibproxy;
import net.sf.cglib.proxy.CallbackFilter;
import java.lang.reflect.Method;
/**
* @author ChangCheng Lu
* @date 2023/8/20 16:35
*/
public class LogInterceptorFilter implements CallbackFilter {
@Override
public int accept(Method method) {
if (method.getName().equals("getUserNameById")) {
System.out.println("是不是木子?");
return 1;
} else if (method.getName().equals("getAddressById")) {
System.out.println("是不是阿同?");
return 2;
}
return 0;
}
}
package com.cclu.cglibproxy;
import net.sf.cglib.proxy.FixedValue;
/**
* @author ChangCheng Lu
* @date 2023/8/20 17:44
*/
public class TargetResultFixed implements FixedValue {
@Override
public Object loadObject() throws Exception {
System.out.println("鎖定結果");
Object obj = "蘇州";
return obj;
}
}
package com.cclu.cglibproxy;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.NoOp;
import org.junit.Test;
/**
* @author ChangCheng Lu
* @date 2023/8/20 17:32
*/
public class ProxyTest {
@Test
public void filterTest() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class);
enhancer.setCallbackFilter(new LogInterceptorFilter());
enhancer.setCallbacks(new Callback[]{NoOp.INSTANCE, new LogInterceptor(), new TargetResultFixed()});
UserService userService = (UserService) enhancer.create();
System.out.println(userService);
System.out.println(userService.getUserNameById("1001"));
System.out.println(userService.getAddressById("1003"));
}
}
參考文檔
-
https://www.runoob.com/w3cnote/cglibcode-generation-library-intro.html