代理模式是一种结构型设计模式,用于在客户端和目标对象间创建一个代理对象,提供中介服务并可扩展功能。 代理模式包括远程代理、虚拟代理、保护代理等类型,常用于权限控制、性能优化等场景。 ,,代理模式就是使用代理对象来代替对真实对象的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。
本文目录导读:
代理模式是一种设计模式,它为其他对象提供一种代理以控制对这个对象的访问,这种模式的主要目的是在访问对象时提供一种更简洁、更灵活的方式,在Java中,代理模式主要有两种实现方式:静态代理和动态代理,本文将详细介绍代理模式的概念、特点、应用场景以及在实际项目中的实践。
代理模式的概念
代理模式是一种结构型设计模式,它通过为其他对象提供一个代理对象来控制对原对象的访问,代理对象可以在不改变原对象的基础上,增加一些额外的功能,如访问控制、日志记录等,代理模式的主要目的是实现对原对象的封装,提高代码的复用性和可维护性。
代理模式的特点
1、代理模式可以实现对原对象的封装,隐藏原对象的实现细节,提供一个简化的接口供客户端使用。
2、代理模式可以在不改变原对象的基础上,为其添加新的功能,如访问控制、日志记录等。
3、代理模式可以实现对原对象的访问控制,例如延迟加载、缓存等。
4、代理模式可以实现对原对象的事务管理,确保数据的一致性和完整性。
5、代理模式可以实现对原对象的远程调用,提高系统的可扩展性和可用性。
代理模式的应用场景
1、数据库访问层:通过代理模式实现对数据库的访问控制,如延迟加载、缓存等。
2、API接口层:通过代理模式实现对API接口的访问控制,如权限控制、缓存等。
3、业务逻辑层:通过代理模式实现对业务逻辑的封装,提高代码的复用性和可维护性。
4、网络通信层:通过代理模式实现对网络通信的封装,提高系统的可扩展性和可用性。
代理模式的实现
在Java中,代理模式主要有两种实现方式:静态代理和动态代理。
1、静态代理:静态代理是在编译期就确定了代理类和被代理类的关系,通常使用接口作为被代理类,实现类作为代理类,Java中的Proxy类和InvocationHandler接口就是用于实现静态代理的工具类和接口。
// 定义一个接口 public interface Subject { void doSomething(); } // 实现接口的具体类 public class RealSubject implements Subject { @Override public void doSomething() { System.out.println("RealSubject do something"); } } // 实现类A,作为被代理类 public class ClassA implements InvocationHandler { private RealSubject realSubject; public ClassA(RealSubject realSubject) { this.realSubject = realSubject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before method call"); Object result = method.invoke(realSubject, args); System.out.println("After method call"); return result; } } // 实现类B,作为代理类 public class ClassB implements InvocationHandler { private ClassA classA; public ClassB(ClassA classA) { this.classA = classA; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("doSomething")) { System.out.println("Before method call in proxy"); } else { return method.invoke(classA, args); } return null; } }
2、动态代理:动态代理是在运行期动态生成代理类的字节码文件,然后通过ClassLoader加载到JVM中,Java中的CGLIB库和JDK自带的动态代理机制都实现了动态代理,以下是使用CGLIB实现动态代理的示例:
import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; import java.util.Date; public class DynamicProxyDemo { public static void main(String[] args) throws Exception { // 创建目标对象实例(真实对象)并设置属性值和方法执行行为(可选) RealSubject realSubject = new RealSubject(); realSubject.setName("张三"); realSubject.setAge(20); realSubject.printInfo(); // 先执行真实对象的方法 printInfo() 为方便查看结果输出时间戳前缀"[start]"和后缀"[end]",这里为了演示方便直接在真实对象上设置了时间戳前缀和后缀,如果不想显示时间戳可以直接删除这行代码或注释掉这行代码即可。// realSubject.setTimeStampPrefix("[" + new Date().toLocaleString() + "]");// realSubject.setTimeStampSuffix("[" + new Date().toLocaleString() + "]");// ==> [start][1646897948][end] 张三的信息如下:年龄:20岁姓名:张三日期:2022-01-01状态:正常==> [start][1646897948][end] 张三的信息如下:年龄:20岁姓名:张三日期:2022-01-01状态:正常==> [start][1646897948][end] 张三的信息如下:年龄:20岁姓名:张三日期:2022-01-01状态:正常==> [start][1646897948][end] 张三的信息如下:年龄:20岁姓名:张三日期:2022-01-01状态:正常==> [start][1646897948][end] 张三的信息如下:年龄:20岁姓名:张三日期:2022-01-01状态:正常==> [start][1646897948][end] 张三的信息如下:年龄:20岁姓名:张三日期:2022-01-01状态:正常==> [start][1646897948][end] 张三的信息如下:年龄:20岁姓名:张三日期:2022-01-01状态:正常==> [start][1646897948][end] 张三的信息如下:年龄:20岁姓名:张三日期:2022-01-01状态:正常==> [start][1646897948][end] 张三的信息如下:年龄:20岁姓名:张三日期:2022-01-01状态:正常==> [start][1646897948][end] 张三的信息如下:年龄:20岁姓名:张三日期:2022-01-01状态:正常==> [start][1646897948][end] 张三的信息如下:年龄:20岁姓名:张三日期:2022-01-01状态:正常==> [start][1646897948][end] 张三的信息如下:年龄:20岁姓名:张三日期:2022-01-01状态