file-type

Java静态代理与动态代理实例解析及源码

下载需积分: 10 | 16KB | 更新于2025-07-10 | 132 浏览量 | 33 下载量 举报 1 收藏
download 立即下载
在Java编程语言中,代理模式是一种重要的设计模式,它允许我们创建一个代理类来代表另一个对象执行操作。代理类在客户端和目标对象之间起到中介作用。按照代理的创建时机和方式,可以分为静态代理和动态代理。以下是从给定文件信息中提取出的相关知识点。 ### 静态代理 静态代理是指在编译期就确定了代理类,并且在代码中明确地定义了代理类,它与目标类都实现同一个接口或继承同一个父类。静态代理的主要优点是易于理解、易于实现,同时也易于调试。但是它的缺点也很明显,当需要代理的类非常多时,就会产生大量的代理类,导致代码冗余,不易维护。 **静态代理的实现步骤通常包括:** 1. **定义一个共同的接口:** 所有的目标类和代理类都遵循这个接口,以确保它们拥有相同的方法签名。 2. **创建目标类:** 实现共同的接口,并提供业务逻辑实现。 3. **创建代理类:** 也实现共同的接口,并在实现接口方法的同时,在内部调用目标类的相关方法。 4. **客户端使用:** 客户端通过代理类来调用目标类的方法。 **静态代理示例代码分析:** 假设有一个共同接口`UserService`,一个目标类`UserServiceImpl`和一个代理类`UserProxy`,客户端代码如下: ```java // 共同接口 public interface UserService { void addUser(); } // 目标类实现共同接口 public class UserServiceImpl implements UserService { @Override public void addUser() { // 实际的业务逻辑 } } // 代理类也实现共同接口 public class UserProxy implements UserService { private UserService userService; // 持有目标类的引用 public UserProxy(UserService userService) { this.userService = userService; } @Override public void addUser() { // 在调用目标类方法前可以做一些预处理 System.out.println("Before add user"); userService.addUser(); // 调用目标类的方法 // 在调用目标类方法后可以做一些后续处理 System.out.println("After add user"); } } // 客户端代码 public class Client { public static void main(String[] args) { UserService userService = new UserServiceImpl(); UserProxy proxy = new UserProxy(userService); proxy.addUser(); } } ``` ### 动态代理 动态代理是指在运行期动态地生成代理类,与静态代理相比,动态代理不需要为每一个目标类编写一个代理类。动态代理通常有两种实现方式:基于接口的动态代理和基于类的动态代理。基于接口的动态代理由Java内置的`java.lang.reflect.Proxy`类实现,基于类的动态代理由`java.lang.reflect.InvocationHandler`接口和`java.lang.reflect.Proxy`类共同实现。 **动态代理的优点:** 1. **减少代码量:** 不需要为每一个目标类编写代理类,从而减少重复代码。 2. **灵活性高:** 动态生成的代理类可以灵活地应用到各种不同的目标类中。 **动态代理的实现步骤通常包括:** 1. **实现`InvocationHandler`接口:** 实现`invoke`方法,定义了代理对象的业务逻辑。 2. **使用`Proxy.newProxyInstance`方法:** 通过目标类的类加载器、实现的接口类型以及`InvocationHandler`实例生成代理对象。 3. **客户端使用代理对象:** 客户端通过得到的代理对象调用目标方法。 **动态代理示例代码分析:** ```java // 目标类 public class RealService implements HelloService { @Override public void sayHello(String name) { System.out.println("Hello, " + name); } } // 定义接口 public interface HelloService { void sayHello(String name); } // 实现InvocationHandler接口 public class MyInvocationHandler implements InvocationHandler { private Object target; // 目标对象 public MyInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before method"); Object result = method.invoke(target, args); // 调用目标对象方法 System.out.println("After method"); return result; } } // 客户端代码 public class Client { public static void main(String[] args) { HelloService realService = new RealService(); InvocationHandler handler = new MyInvocationHandler(realService); // 生成动态代理对象 HelloService proxyService = (HelloService) Proxy.newProxyInstance( HelloService.class.getClassLoader(), new Class[]{HelloService.class}, handler); proxyService.sayHello("World"); } } ``` 在上述代码中,我们首先定义了一个`HelloService`接口以及它的实现类`RealService`,然后创建了`MyInvocationHandler`类实现`InvocationHandler`接口。在客户端代码中,我们通过`Proxy.newProxyInstance`方法创建了一个动态代理类的实例,并通过代理实例调用目标方法。 通过以上示例代码,我们可以看到静态代理和动态代理的实现方式及其各自的特点和使用场景。静态代理由于需要编写具体的代理类,虽然直观但会增加代码量和维护成本;而动态代理则减少了这些开销,能够提供更灵活和高效的代理解决方案。在实际应用中,应根据具体的需求来选择合适的代理模式。

相关推荐