CGLib動態代理 使用JDK創建代理有一個限制,即它只能為介面創建代理實例,這一點可以從Proxy的介面方法newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler handler)中看得很清楚:第二個入參in ...
CGLib動態代理
使用JDK創建代理有一個限制,即它只能為介面創建代理實例,這一點可以從Proxy的介面方法newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler handler)中看得很清楚:第二個入參interfaces就是需要代理實現的介面列表。
CGLib採用底層的位元組碼技術,可以為一個類創建子類,在子類總採用方法攔截的技術攔截所有父類方法的調用並順勢織入橫切邏輯。
簡單使用
定義一個需要代理的類
package org.aming.cglib.demo.service;
public class UserService {
public void loadUserByUserName(String username) {
System.out.println("我正在嘗試查找用戶:" + username + "的信息");
}
}
實現MethodInterceptor介面
package org.aming.cglib.demo.interceptor;
import java.lang.reflect.Method;
import java.util.Objects;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer;
public <T> T getProxy(Class<T> clazz) {
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return (T)enhancer.create();
}
public <T> T getProxy(T t) {
enhancer.setSuperclass(t.getClass());
enhancer.setCallback(this);
return (T)enhancer.create();
}
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
long begin = System.currentTimeMillis();
System.out.println(obj.getClass().getName() + "." + method.getName());
Object result = proxy.invokeSuper(obj, args);
long end = System.currentTimeMillis();
System.out.println("執行了" + (end - begin) + "毫秒");
return result;
}
public CglibProxy() {
super();
this.enhancer = new Enhancer();
}
}
測試
package org.aming.cglib.demo.test;
import org.aming.cglib.demo.interceptor.CglibProxy;
import org.aming.cglib.demo.service.UserService;
public class TestMain {
public static void main(String[] args) {
CglibProxy proxy = new CglibProxy();
UserService userService = proxy.getProxy(UserService.class);
userService.loadUserByUserName("大明二代");
}
}
小結
由於CGLib採用動態創建子類的方式生成代理對象,所以不能對目標類中的final或private方法進行代理。