java中的动态代理(口试热点)

打印 上一主题 下一主题

主题 1749|帖子 1749|积分 5247

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
在Java中,动态代理是一种在运行时动态创建代理类及其对象的技能。与静态代理不同,动态代理的代理类并不是在编译时创建的,而是在运行时根据需要动态生成。这种技能提供了更高的灵活性和可扩展性,因为它允许开发者在运行时根据需要添加或修改代理的举动。
动态代理的实现方式
在Java中,动态代理主要有两种实现方式:基于JDK的动态代理和基于CGLib的动态代理。
1. 基于JDK的动态代理
JDK动态代理主要依赖于`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口。`Proxy`类提供了创建动态代理类和实例的静态方法,而`InvocationHandler`接口则需要用户实现,以定义代理对象的举动。
JDK动态代理主要适用于实现了接口的类。
示例代码

  1. import java.lang.reflect.InvocationHandler;
  2. import java.lang.reflect.Method;
  3. import java.lang.reflect.Proxy;
  4. // 定义一个接口
  5. interface Subject {
  6.     void doSomething();
  7. }
  8. // 实现接口的类
  9. class RealSubject implements Subject {
  10.     @Override
  11.     public void doSomething() {
  12.         System.out.println("RealSubject.doSomething()");
  13.     }
  14. }
  15. // 实现InvocationHandler接口
  16. class DynamicProxyHandler implements InvocationHandler {
  17.     private Object target; // 真实对象
  18.     public DynamicProxyHandler(Object target) {
  19.         this.target = target;
  20.     }
  21.     @Override
  22.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  23.         // 在方法执行前可以做一些处理
  24.         System.out.println("Before method: " + method.getName());
  25.         // 调用真实对象的方法
  26.         Object result = method.invoke(target, args);
  27.         // 在方法执行后可以做一些处理
  28.         System.out.println("After method: " + method.getName());
  29.         return result;
  30.     }
  31.     // 获取动态代理的实例
  32.     @SuppressWarnings("unchecked")
  33.     public static <T> T getProxyInstance(T target, Class<T> interfaceType) {
  34.         return (T) Proxy.newProxyInstance(
  35.                 interfaceType.getClassLoader(), // 类加载器
  36.                 new Class<?>[]{interfaceType}, // 代理类需要实现的接口列表
  37.                 new DynamicProxyHandler(target) // 调用处理器
  38.         );
  39.     }
  40. }
  41. public class DynamicProxyExample {
  42.     public static void main(String[] args) {
  43.         // 创建真实对象
  44.         RealSubject realSubject = new RealSubject();
  45.         // 获取动态代理对象
  46.         Subject proxySubject = DynamicProxyHandler.getProxyInstance(realSubject, Subject.class);
  47.         // 通过代理对象调用方法
  48.         proxySubject.doSomething();
  49.     }
  50. }
复制代码

 
当运行上面的代码时,输出将是:
  1. Before method: doSomething
  2. RealSubject.doSomething()
  3. After method: doSomething
复制代码

 
在这个例子中,`DynamicProxyHandler`类实现了`InvocationHandler`接口,并在其`invoke`方法中定义了代理的举动。`getProxyInstance`静态方法用于获取动态代理的实例。留意,这个方法的返回范例是泛型,这允许我们创建任何实现了特定接口的代理对象。
2. 基于CGLib的动态代理
CGLib(Code Generation Library)是一个强大的、高性能的、高质量的Code生成类库,它可以在运行时扩展Java类和实现接口。CGLib通过继承的方式动态地创建目标类的子类,从而实现对目标类方法的拦截。
由于CGLib是通过继承的方式实现动态代理的,因此它不仅可以代理实现了接口的类,还可以代理没有实现任何接口的类。但是,由于Java的单继承限制,CGLib动态代理不能代理final类或者final方法。
 示例代码
要使用CGLib,你起首需要将CGLib的jar包添加到你的项目中。以下是一个简单的CGLib动态代理的示例:

  1. import net.sf.cglib.proxy.Enhancer;
  2. import net.sf.cglib.proxy.MethodInterceptor;
  3. import net.sf.cglib.proxy.MethodProxy;
  4. // 定义一个没有实现接口的类
  5. class RealSubject {
  6.     public void doSomething() {
  7.         System.out.println("RealSubject.doSomething()");
  8.     }
  9. }
  10. // 实现MethodInterceptor接口
  11. class CglibProxyInterceptor implements MethodInterceptor {
  12.     @Override
  13.     public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
  14.         // 在方法执行前可以做一些处理
  15.         System.out.println("Before method: " + method.getName());
  16.         // 调用真实对象的方法
  17.         Object result = proxy.invokeSuper(obj, args); // 调用父类的方法
  18.         // 在方法执行后可以做一些处理
  19.         System.out.println("After method: " + method.getName());
  20.         return result;
  21.     }
  22. }
  23. public class CglibDynamicProxyExample {
  24.     public static void main(String[] args) {
  25.         // 创建真实对象
  26.         RealSubject realSubject = new RealSubject();
  27.         
  28.         // 使用CGLib创建动态代理对象
  29.         Enhancer enhancer = Enhancer.create(); // 创建Enhancer实例
  30.         enhancer.setSuperclass(RealSubject.class); // 设置代理类的父类为RealSubject类
  31.         enhancer.setCallback(new CglibProxyInterceptor()); // 设置回调,即我们要实现的逻辑
  32.         RealSubject proxy = (RealSubject) enhancer.create(); // 创建代理对象并返回
  33.         
  34.         // 通过代理对象调用方法
  35.         proxy.doSomething();
  36.     }
  37. }
复制代码


当运行上面的代码时,输出结果将是:
 
  1. Before method: doSomething
  2. RealSubject.doSomething()
  3. After method: doSomething
复制代码


在这个例子中,我们使用CGLib库中的`Enhancer`类来创建动态代理。我们起首通过`setSuperclass`方法设置代理类的父类为`RealSubject`。然后通过`setCallback`方法设置回调,即我们实现的逻辑。在这个例子中,我们实现了`CglibProxyInterceptor`来定义代理对象的举动。这个类实现了`MethodInterceptor`接口,它有两个主要的方法:`intercept`和`getProxy』。`intercept`方法负责在目标方法的调用前后添加额外的逻辑。在这个例子中,我们在目标方法执行前后打印出日志信息。末了我们通过调用`create`方法来创建代理对象。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

半亩花草

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表