代理模式
作者:互联网
动态代理
- 动态代理是动态生成的,不是我们直接写好的。
- 动态代理分为两大类:基于接口的动态代理、基于类的动态代理
- 基于接口:JDK动态代理【这章只讲这个】
- 基于类:cglib
- java字节码实现:javassist
需要了解两个类
- Proxy【代理】
- InvocationHandler【调用处理程序】
Pros:
- 包括所有静态代理的所有好处
- 一个动态代理类代理的是一个接口,一般就是对应的一类业务
- 一个动态代理类可以代理多个类,只要实现了同一个接口即可
================================== 分隔线 ===================================
https://www.cnblogs.com/daniels/p/8242592.html
代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。
举个例子来说明:假如说我现在想买一辆二手车,虽然我可以自己去找车源,做质量检测等一系列的车辆过户流程,但是这确实太浪费我得时间和精力了。我只是想买一辆车而已为什么我还要额外做这么多事呢?于是我就通过中介公司来买车,他们来给我找车源,帮我办理车辆过户流程,我只是负责选择自己喜欢的车,然后付钱就可以了。用图表示如下:
为什么要用代理模式?
- 中介隔离作用 --> 在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
- 开闭原则,增加功能 --> 代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。
分类
按照代理创建的时期来进行分类的话, 可以分为两种:静态代理、动态代理。
-
静态代理是由程序员创建或特定工具自动生成源代码,在对其编译。在程序员运行之前,代理类
.class
文件就已经被创建了。 -
动态代理是在程序运行时通过反射机制动态创建的。(在动态代理中我们不再需要再手动的创建代理类,我们只需要编写一个动态处理器就可以了。真正的代理对象由JDK再运行时为我们动态的来创建。)
静态代理
原先房东亲自出租房子
// 租房
public interface Rent {
void rent();
}
// 房东
public class Landlord implements Rent {
public void rent() {
System.out.println("房东出租房子");
}
}
// 房东亲自出租房子
public static void main(String[] args) {
Landlord landlord = new Landlord();
landlord.rent();
}
让代理出租房子
// 代理
public class Proxy implements Rent {
private final Landlord landlord;
public Proxy(Landlord landlord) {
this.landlord = landlord;
}
// 代理帮助房东租房,并且还可以在租房的基础上增强一些功能
public void rent() {
System.out.println("代理打广告推销房子");
landlord.rent();
}
}
// 让代理出租房子
public static void main(String[] args) {
Landlord landlord = new Landlord();
Proxy proxy = new Proxy(landlord);
proxy.rent();
}
Pros:
- 可以做到在不修改目标对象的功能前提下,对目标功能扩展。
- 真实角色更集中开发,不用去管一些公共业务。
- 公共业务交给代理角色,实现业务分工。
Cons:
- 代理角色要与真实角色实现一样的接口,代码量多,维护困难。
- 同时,一旦接口增加方法,目标对象与代理对象都要维护。
动态代理
例子1
public interface Rent {
void rent();
}
public class Landlord implements Rent {
public void rent() {
System.out.println("房东出租房子");
}
}
import java.lang.reflect.*;
public class ProxyLandlord implements InvocationHandler {
// 被代理的接口
private final Rent rent;
// 设置要被代理的角色
public ProxyLandlord(Rent rent) {
this.rent = rent;
}
// 生成得到代理类
public Object getProxy() {
// 第一个参数:ClassLoader
// 第二个参数:an array of interfaces implemented by this class.
// 第三个参数:调用处理程序
// loader:被代理的类的类加载器;
// interfaces:被代理类的接口数组;
// invocationHandler:调用处理器类的对象实例。
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
rent.getClass().getInterfaces(), this);
}
// proxy:被代理的类的实例;
// method:调用被代理的类的方法;
// args:该方法需要的参数。
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("帮房东打广告");
Object result = method.invoke(rent, args);
System.out.println("帮房东收费");
return result;
}
}
测试代码
public static void main(String[] args) {
Landlord landlord = new Landlord();
ProxyLandlord proxyLandlord = new ProxyLandlord(landlord);
Rent r = (Rent) proxyLandlord.getProxy();
r.rent();
}
结果
帮房东打广告
房东出租房子
帮房东收费
例子2
public interface Rent {
void rent();
}
public class Landlord implements Rent {
public void rent() {
System.out.println("房东出租房子");
}
}
public class DynamicProxy implements InvocationHandler {
private Object object;
public void setObject(Object object) {
this.object = object;
}
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
object.getClass().getInterfaces(),this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(object, args);
this.log(method.getName()); // 使用反射获取方法的名字
return result;
}
// 例如代理要添加功能
public void log(String function) {
System.out.println("房子被" + function + "了");
}
}
public static void main(String[] args) {
Landlord landlord = new Landlord();
DynamicProxy dynamicProxy = new DynamicProxy();
// 设置代理对象
dynamicProxy.setObject(landlord);
// 获取代理实例
Rent proxy = (Rent) dynamicProxy.getProxy();
// 调用实例方法
proxy.rent();
}
测试结果
房东出租房子
房子被rent了
标签:Landlord,void,代理,模式,rent,landlord,public 来源: https://www.cnblogs.com/jumpig/p/14829878.html