Java学习笔记--Cglib动态代理
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方法进行代理。