Java中,代理模式是一种常见的设计模式,用于为某对象提供一种代理,以控制对该对象的访问。根据代理类的实现方式,可以分为静态代理和动态代理。以下将分别介绍这两种方式,并进行对比分析。
静态代理
静态代理是指在编译时期就已经确定了代理类的实现。代理类必要实现与目标对象相同的接口,并持有目标对象的引用,通过代理对象调用目标对象的方法。
静态代理的实现步骤
- 定义接口。
- 编写接口的实现类(目标类)。
- 编写代理类,实现接口并持有目标类的引用。
- 在代理类中,通过目标类的引用调用实际的方法。
示例代码
- // 定义接口
- public interface Hello {
- void morning(String name);
- }
- // 目标类
- public class HelloWorld implements Hello {
- @Override
- public void morning(String name) {
- System.out.println("Good morning, " + name);
- }
- }
- // 代理类
- public class HelloProxy implements Hello {
- // 内部维护一个目标代理对象的属性字段
- private Hello target;
- public HelloProxy(Hello target) {
- this.target = target;
- }
- @Override
- public void morning(String name) {
- System.out.println("Before method invoke...");
- target.morning(name); // 调用目标类方法
- System.out.println("After method invoke...");
- }
- }
- // 测试静态代理
- public class Main {
- public static void main(String[] args) {
- Hello target = new HelloWorld(); // 创建目标对象
- Hello proxy = new HelloProxy(target); // 创建代理对象
- proxy.morning("Bob"); // 调用代理方法
- }
- }
复制代码 输出:- Before method invoke...
- Good morning, Bob
- After method invoke...
复制代码 优点
- 结构简单,容易理解。
- 代理类可以扩展目标类的功能(如添加日志、权限校验等)。
缺点
- 每增长一个接口,都必要单独编写代理类,扩展性差。
- 代理类的维护工作量较大。
动态代理
动态代理是指在运行时动态生成代理类,而不必要提前定义实现类。它的实现重要依赖于Java的java.lang.reflect.Proxy和InvocationHandler。
动态代理的实现步骤
- 定义接口。
- 创建InvocationHandler接口的实现类,用来处理方法调用。
- 使用Proxy.newProxyInstance()生成动态代理对象。
示例代码
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
- // 定义接口
- public interface Hello {
- void morning(String name);
- }
- // 测试动态代理
- public class Main {
- public static void main(String[] args) {
- // 创建InvocationHandler
- InvocationHandler handler = new InvocationHandler() {
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- System.out.println("Before method invoke...");
- if (method.getName().equals("morning")) {
- System.out.println("Good morning, " + args[0]);
- }
- System.out.println("After method invoke...");
- return null;
- }
- };
- // 创建动态代理对象
- Hello hello = (Hello) Proxy.newProxyInstance(
- Hello.class.getClassLoader(), // 类加载器
- new Class[] { Hello.class }, // 需要实现的接口
- handler // 方法调用处理器
- );
- // 调用代理方法
- hello.morning("Bob");
- }
- }
复制代码 输出- Before method invoke...
- Good morning, Bob
- After method invoke...
复制代码 动态代理的核心:
- InvocationHandler接口:定义了代理逻辑的核心。
- Proxy.newProxyInstance():负责在运行时动态生成代理类并返回代理实例。
动态代理本质上是JVM在运行时生成代理类的字节码,并加载到内存中。
静态代理与动态代理的对比
特点静态代理动态代理代理类实现方式编译时定义代理类运行时动态生成代理类对接口的支持每个接口必要单独实现代理类可通用,只需实现InvocationHandler代码扩展性低,新增接口时需增长代理类高,只需更改代理逻辑即可性能开销无需反射,性能较高依赖反射调用,性能略低应用场景小型项目或接口稳定的场景大型项目、动态扩展功能的场景总结
- 静态代理实用于小型项目,或者代理类相对固定的场景。
- 动态代理实用于必要动态扩展功能或减少重复代码的场景。
- 动态代理的灵活性更强,尤其是在AOP(面向切面编程)框架中广泛使用,如Spring框架中的动态代理。
动态代理的强盛之处在于,它将代理逻辑与详细实现解耦,使得代码更加灵活、可维护,同时提供了更高的复用性。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |