大家好,欢迎来到IT知识分享网。
代理模式
当访问对象不适合或者不能直接引用目标对象时,需要给访问对象提供一个代理以控制对该对象的访问,代理对象作为访问对象和目标对象之间的中介。
代理模式的主要优点有:
- 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
- 代理对象可以扩展目标对象的功能;
- 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度;
其主要缺点是:
- 在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢;
- 增加了系统的复杂度;
代理模式分为静态代理和动态代理,这里我们只对动态代理进行论述
动态代理:
- 动态代理的代理类是动态生成的,不是我们直接写好的
- 动态代理分为两大类:基于接口的动态代理和基于类的动态代理
- 基于接口:JDK动态代理
- 基于类:CGLIB
- Java字节码实现:Javasist
动态代理的好处:
- 可以使真实角色操作更加纯粹,不用去关注一些公众的事务
- 公共事务交给代理角色,实现了业务的分工
- 公共业务扩展时,方便集中管理
- 一个动态代理类代理的是一个接口,一般就是对应一类的业务
- 一个动态代理类可以代理多个类,只要是实现了同一个接口即可
JDK动态代理
Spring JDK 动态代理需要实现 InvocationHandler 接口,重写 invoke 方法,客户端使用 Java.lang.reflect.Proxy 类产生动态代理类的对象。
下面使用IDEA演示JDK动态代理过程
示例为客户通过中介向房东租房子演示:
如图所示创建客户类(Client)、房东(Host)、业务增强(MyAspect)、代理类(ProxyInvocationHandler)、接口(Rent).
接口(Rent)代码如下:
//租房子的接口
public interface Rent {
public void rent();
}
房东(Host)代码如下:
//房东代码实现接口,实现租出房子
public class Host implements Rent {
public void rent(){
System.out.println("租出房子");
}
}
业务增强(MyAspect)代码如下:
//在代理中,代理类不仅可以实现必须要实现的业务,同时还可以扩展目标对象的功能
//MyAspect 类在切面中定义了两个增强的方法,分别为 myBefore 和 myAfter。
public class MyAspect {
public void myBefore() {
System.out.println("方法执行之前");
}
public void myAfter() {
System.out.println("方法执行之后");
}
}
代理类(ProxyInvocationHandler)代码如下:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//实现InvocationHandler接口生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
MyAspect myAspect = new MyAspect();
//被代理的接口
private Rent rent;
public void setRent(Rent rent) {
this.rent = rent;
}
//定义获取代理对象方法
public Object getProxy(){
// JDK动态代理只能代理实现了接口的类
return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(),this);
}
//处理代理实例,并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//动态代理的实质,就是反射机制的实现
myAspect.myBefore();
Object result = method.invoke(rent,args);
myAspect.myAfter();
return result;
}
}
客户代码如下:
public class Client {
public static void main(String[] args) {
//真实角色
Rent rent= new Host();
//代理角色
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//通过调用程序处理角色来处理我们要调用的接口对象
pih.setRent(rent);
//获取代理对象
Rent proxy = (Rent) pih.getProxy();
//由代理对象执行方法
proxy.rent();
}
}
运行结果:
小Tip:编写代理类时,只需实现InvocationHandler接口中的方法
- 获取代理对象getProxy()方法:JDK动态代理只能代理实现了接口的类,只需修改相应的接口即可
- 处理代理实例invoke()方法:除了实现接口中的功能外,还可以扩展目标对象的功能。
这样客户通过代理对象来实现接口中的方法,而不是直接通过房东实现,降低了系统的耦合度,同时扩展了目标对象的功能
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/25368.html