代理模式
静态代理
抽象角色:一般使用接口或者抽象类来实现
真实角色:被代理的角色
代理角色:代理真实角色;代理真实角色后,一般会做一些附属的操作
客户:使用代理角色来进行一些操作
接口
/**
* 抽象角色
*/
public interface Rent {
public void rent();
}
实体
/**
*真实角色:房东
**/
public class Host implements Rent {
public void rent() {
System.out.println("房屋出租");
}
}
/**
*代理对象:Proxy
**/
public class Proxy implements Rent {
private Host host;
public Proxy(){
}
/**
*设置一个代理对象
* @param host(传入要出租房的人)
* @return
*/
public Proxy(Host host){
this.host = host;
}
/**
* 代理内容
*/
public void rent(){
seeHouse();
host.rent();
fare();
}
/**
* 中介添加的内容(看房)
*/
public void seeHouse(){
System.out.println("带房客看房");
}
/**
* 中介添加的内容(收中介费用)
*/
public void fare(){
System.out.println("收取中介费");
}
}
/**
*真实角色:客户
**/
public class client {
public static void main(String[] args) {
//获取房东对象
Host host = new Host();
//给代理对象传入房东.目的确定信息
Proxy proxy = new Proxy(host);
//通过中介租房
proxy.rent();
}
}
备注
重点理解让真实角色专注于自己业务的实现,其他业务交给代理角色
动态代理
-
动态代理的角色和静态代理的一样 .
-
动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的
-
动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
-
- 基于接口的动态代理----JDK动态代理
- 基于类的动态代理–cglib
- 现在用的比较多的是 javasist 来生成动态代理 . 百度一下javasist
- 我们这里使用JDK的原生代码来实现,其余的道理都是一样的!、
JDK的动态代理需要了解两个类
核心
InvocationHandler 和 Proxy , 打开JDK帮助文档看看
InvocationHandler:调用处理程序
接口
/**
* 抽象角色
*/
public interface Rent {
public void rent();
}
实体
/**
* 真实角色:房东,房东要出租房子
*/
public class Host implements Rent {
public void rent() {
System.out.println("房屋出租");
}
}
/**
*代理角色
**/
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口对象
private Rent rent;
public void setRent(Rent rent){
this.rent = rent;
}
/*
Proxy提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。
Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class<?>[] { Foo.class },
handler);
参数:this.getClass().getClassLoader() 代理类的类加载器,
rent.getClass().getInterfaces() 被代理类的接口,
this 代理类的实例
*/
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/*核心:本质利用反射实现
*method.invoke(rent,args);利用反射调用类里面的实际方法
*Object result 方法的返回值,如果没有,返回为null
*/
Object result = method.invoke(rent,args);
return result;
}
/**
* 看房
*/
public void seeHouse(){
System.out.println("带房客看房");
}
/**
* 收中介费
*/
public void fare(){
System.out.println("收中介费");
}
}
public class Client {
public static void main(String[] args) {
//真实角色
Host host = new Host();
//代理实例的调用处理程序
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//将真实角色放置进去!
pih.setRent(host);
//动态生成对应的代理类!
Rent proxy = (Rent)pih.getProxy();
proxy.rent();
}
}
重点理解:一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个类,代理的是接口!、
初浅理解:
动态实际上就是实现InvocationHandler接口,一切交给程序处理
初步需要理解(这些就足够了):
/*参数:this.getClass().getClassLoader() 代理类的类加载器,
rent.getClass().getInterfaces() 代理类的类加载器,
this 代理类的实例
*/
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/*核心:本质利用反射实现
*method.invoke(rent,args);利用反射调用类里面的实际方法
*Object result 方法的返回值,如果没有,返回为null
*/
Object result = method.invoke(rent,args);
return result;
}
通用的动态代理实现的类
所有的代理对象设置为Object即可
public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
public void setTarget(Object target){
this.target = target;
}
/*
Proxy提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。
Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class<?>[] { Foo.class },
handler);
*/
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//核心:本质利用反射实现
Object result = method.invoke(target,args);
return result;
}
}
动态代理相比静态减少了代码量,静态代理要一个类就就要配置一个代理类,而动态代理则可以代理多个类