软件编程
位置:首页>> 软件编程>> java编程>> Java实例讲解 *

Java实例讲解 *

作者:大梦谁先觉i  发布时间:2023-03-21 22:56:45 

标签:Java, ,

JDK * :利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

CGlib * :利用ASM(开源的Java字节码编辑库,操作字节码)开源包,将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

区别:JDK代理只能对实现接口的类生成代理;CGlib是针对类实现代理,对指定的类生成一个子类,并覆盖其中的方法,这种通过继承类的实现方式,不能代理final修饰的类。

强制使用CGlib

<!-- proxy-target-class="false"默认使用JDK * -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
<aop-config proxy-target-class="true">

具体代码示例:

/**
* 目标接口类
*/
public interface UserManager {    
   public void addUser(String id, String password);    
   public void delUser(String id);    
}
/**
* 接口实现类
*/
public class UserManagerImpl implements UserManager {    
   @Override
   public void addUser(String id, String password) {    
       System.out.println("调用了UserManagerImpl.addUser()方法!");
   }    
   @Override
   public void delUser(String id) {    
       System.out.println("调用了UserManagerImpl.delUser()方法!");
   }    
}
/**
* JDK * 类
*/
public class JDKProxy implements InvocationHandler {    
   // 需要代理的目标对象
   private Object targetObject;    
   public Object newProxy(Object targetObject) {
       // 将目标对象传入进行代理    
       this.targetObject = targetObject;
       // 返回代理对象
       return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);
   }    
   // invoke方法
   @Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       // 进行逻辑处理的函数
       checkPopedom();
       Object ret = null;
       // 调用invoke方法
       ret = method.invoke(targetObject, args);
       return ret;
   }    
   private void checkPopedom() {
       // 模拟检查权限  
       System.out.println("检查权限:checkPopedom()!");    
   }    
}
/**
* CGlib * 类
*/
public class CGLibProxy implements MethodInterceptor {    
   // CGlib需要代理的目标对象
   private Object targetObject;
   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;
   }
   @Override
   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()!");
   }
}
/**
* 测试类
*/
public class ProxyTest {
   public static void main(String[] args) {
       UserManager userManager = (UserManager)new CGLibProxy().createProxyObject(new UserManagerImpl());
       System.out.println("CGLibProxy:");
       userManager.addUser("tom", "root");
       System.out.println("JDKProxy:");
       JDKProxy jdkProxy = new JDKProxy();
       UserManager userManagerJDK = (UserManager)jdkProxy.newProxy(new UserManagerImpl());
       userManagerJDK.addUser("tom", "root");
   }
}

// 运行结果
CGLibProxy:
检查权限checkPopedom()!
调用了UserManagerImpl.addUser()方法!
JDKProxy:
检查权限checkPopedom()!
掉用了UserManagerImpl.addUser()方法!

总结:

  • JDK代理使用的是反射机制实现aop的 * ,CGLIB代理使用字节码处理框架asm,通过修改字节码生成子类。所以jdk * 的方式创建代理对象效率较高,执行效率较低,cglib创建效率较低,执行效率高;

  • JDK * 机制是委托机制,具体说动态实现接口类,在动态生成的实现类里面委托hanlder去调用原始实现类方法,CGLIB则使用的继承机制,具体说被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,如果被代理类有接口,那么代理类也可以赋值给接口。

来源:https://blog.csdn.net/qq_45228323/article/details/124998500

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com