Kotlin代理模式

1、CGLib实现代理

1.1 与JDK代理区别

1.1.1 JDK动态代理和CGLIB字节码生成的区别?

(1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类
(2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法;因为是继承,所以该类或方法最好不要声明成final

1.2 对比

JDK代理是不需要依赖第三方的库,只要JDK环境就可以进行代理,它有几个要求:

  1. 实现InvocationHandler
  2. 使用Proxy.newProxyInstance产生代理对象
  3. 被代理的对象必须要实现接口
  • 使用JDK动态代理,目标类必须实现的某个接口,如果某个类没有实现接口则不能生成代理对象。
  • CGLib 必须依赖于CGLib的类库,Cglib原理是针对目标类生成一个子类,覆盖其中的所有方法,所以目标类和方法不能声明为final类型。

针对接口编程的环境下推荐使用JDK的代理。从执行效率上看,Cglib动态代理效率较高。
在Hibernate中的拦截器其实现考虑到不需要其他接口的条件Hibernate中的相关代理采用的是CGLib来执行。

1.3 CGLib实例

实例:

  1. /**
  2. • CGLibProxy动态代理类的实例
  3. */
  4. public class CGLibProxy implements MethodInterceptor {
  5. private Object targetObject;// CGLib需要代理的目标对象
  6. public Object createProxyObject(Object obj) {
  7. this.targetObject = obj;
  8. Enhancer enhancer = new Enhancer();
  9. enhancer.setSuperclass(obj.getClass());
  10. enhancer.setCallback(this);
  11. Object proxyObj = enhancer.create();
  12. return proxyObj;// 返回代理对象
  13. }
  14. public Object intercept(Object proxy, Method method, Object[] args,
  15. MethodProxy methodProxy) throws Throwable {
  16. Object obj = null;
  17. if ("addUser".equals(method.getName())) {// 过滤方法
  18. checkPopedom();// 检查权限
  19. }
  20. obj = method.invoke(targetObject, args);
  21. return obj;
  22. }
  23. private void checkPopedom() {
  24. System.out.println(".:检查权限 checkPopedom()!");
  25. }
  26. }
// 调用
UserManager userManager = (UserManager) new CGLibProxy().createProxyObject(new UserManagerImpl());