Kotlin代理模式
1、CGLib实现代理
1.1 与JDK代理区别
1.1.1 JDK动态代理和CGLIB字节码生成的区别?
(1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类
(2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法;因为是继承,所以该类或方法最好不要声明成final
1.2 对比
JDK代理是不需要依赖第三方的库,只要JDK环境就可以进行代理,它有几个要求:
- 实现InvocationHandler
- 使用Proxy.newProxyInstance产生代理对象
- 被代理的对象必须要实现接口
- 使用JDK动态代理,目标类必须实现的某个接口,如果某个类没有实现接口则不能生成代理对象。
- CGLib 必须依赖于CGLib的类库,Cglib原理是针对目标类生成一个子类,覆盖其中的所有方法,所以目标类和方法不能声明为final类型。
针对接口编程的环境下推荐使用JDK的代理。从执行效率上看,Cglib动态代理效率较高。
在Hibernate中的拦截器其实现考虑到不需要其他接口的条件Hibernate中的相关代理采用的是CGLib来执行。
1.3 CGLib实例
实例:
/**
• CGLibProxy动态代理类的实例
•
•
*/
public class CGLibProxy implements MethodInterceptor {
private Object targetObject;// CGLib需要代理的目标对象
public Object createProxyObject(Object obj) {
this.targetObject = obj;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(obj.getClass());
enhancer.setCallback(this);
Object proxyObj = enhancer.create();
return proxyObj;// 返回代理对象
}
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
Object obj = null;
if ("addUser".equals(method.getName())) {// 过滤方法
checkPopedom();// 检查权限
}
obj = method.invoke(targetObject, args);
return obj;
}
private void checkPopedom() {
System.out.println(".:检查权限 checkPopedom()!");
}
}
// 调用
UserManager userManager = (UserManager) new CGLibProxy().createProxyObject(new UserManagerImpl());