欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 创投人物 > java中的动态代理(面试热点)

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

2024/10/24 23:21:08 来源:https://blog.csdn.net/qa3629723/article/details/140746182  浏览:    关键词:java中的动态代理(面试热点)

在Java中,动态代理是一种在运行时动态创建代理类及其对象的技术。与静态代理不同,动态代理的代理类并不是在编译时创建的,而是在运行时根据需要动态生成。这种技术提供了更高的灵活性和可扩展性,因为它允许开发者在运行时根据需要添加或修改代理的行为。

动态代理的实现方式

在Java中,动态代理主要有两种实现方式:基于JDK的动态代理和基于CGLib的动态代理。

1. 基于JDK的动态代理

JDK动态代理主要依赖于`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口。`Proxy`类提供了创建动态代理类和实例的静态方法,而`InvocationHandler`接口则需要用户实现,以定义代理对象的行为。

JDK动态代理主要适用于实现了接口的类。

示例代码

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;// 定义一个接口
interface Subject {void doSomething();
}// 实现接口的类
class RealSubject implements Subject {@Overridepublic void doSomething() {System.out.println("RealSubject.doSomething()");}
}// 实现InvocationHandler接口
class DynamicProxyHandler implements InvocationHandler {private Object target; // 真实对象public DynamicProxyHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 在方法执行前可以做一些处理System.out.println("Before method: " + method.getName());// 调用真实对象的方法Object result = method.invoke(target, args);// 在方法执行后可以做一些处理System.out.println("After method: " + method.getName());return result;}// 获取动态代理的实例@SuppressWarnings("unchecked")public static <T> T getProxyInstance(T target, Class<T> interfaceType) {return (T) Proxy.newProxyInstance(interfaceType.getClassLoader(), // 类加载器new Class<?>[]{interfaceType}, // 代理类需要实现的接口列表new DynamicProxyHandler(target) // 调用处理器);}
}public class DynamicProxyExample {public static void main(String[] args) {// 创建真实对象RealSubject realSubject = new RealSubject();// 获取动态代理对象Subject proxySubject = DynamicProxyHandler.getProxyInstance(realSubject, Subject.class);// 通过代理对象调用方法proxySubject.doSomething();}
}


 

当运行上面的代码时,输出将是:


Before method: doSomething
RealSubject.doSomething()
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动态代理的示例:

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;// 定义一个没有实现接口的类
class RealSubject {public void doSomething() {System.out.println("RealSubject.doSomething()");}
}// 实现MethodInterceptor接口
class CglibProxyInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {// 在方法执行前可以做一些处理System.out.println("Before method: " + method.getName());// 调用真实对象的方法Object result = proxy.invokeSuper(obj, args); // 调用父类的方法// 在方法执行后可以做一些处理System.out.println("After method: " + method.getName());return result;}
}public class CglibDynamicProxyExample {public static void main(String[] args) {// 创建真实对象RealSubject realSubject = new RealSubject();// 使用CGLib创建动态代理对象Enhancer enhancer = Enhancer.create(); // 创建Enhancer实例enhancer.setSuperclass(RealSubject.class); // 设置代理类的父类为RealSubject类enhancer.setCallback(new CglibProxyInterceptor()); // 设置回调,即我们要实现的逻辑RealSubject proxy = (RealSubject) enhancer.create(); // 创建代理对象并返回// 通过代理对象调用方法proxy.doSomething();}
}



当运行上面的代码时,输出结果将是:
 

Before method: doSomething
RealSubject.doSomething()
After method: doSomething



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

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com