代理模式
1.1 静态代理
什么是静态代理?
如若代理类在程序运行之前就已经存在,那么这种代理方式被称为静态代理。这种情况下的代理类通常都是我们在Java代码中定义的。
通常情况下静态代理类和目标类通常都会实现同一个接口或者派生自同一父类
静态代理角色分析
抽象角色 : 一般使用接口或者抽象类来实现
真实角色 : 被代理的角色(被代理类)
代理角色 : 代理真实角色 ; 代理真实角色后 , 一般会做一些附属的操作 (代理类).
客户 : 使用代理角色来进行一些操作 .
具体实现:
1.创建接口,一般为抽象角色(被代理类与代理类共同实现的接口)
package com.chen.demo1;
//抽象角色:表示出租房子这件事,一般是接口或者抽象
public interface Rent {
//表示出租的房子
void rentHouse();
}
2.创建真实角色和代理角色同时实现相同的接口
package com.chen.demo1;
//房东:真实角色 要被代理的角色
public class Host implements Rent {
//表示房东出租房子
public void rentHouse() {
System.out.println("房东要出租房子");
}
}
package com.chen.demo1;
//代理角色:去代理真实角色
public class Proxy implements Rent{
//代理角色首先要和房东接触,要得到真实对象
private Host host;
public Proxy() {
}
//得到具体的真实对象
public Proxy(Host host) {
this.host = host;
}
public void seeHouse(){
System.out.println("首先看看房子");
}
public void rentHouse() {
seeHouse();
host.rentHouse();
}
}
3.测试
package com.chen.demo1;
//租房子的客户 :访问代理对象的人
public class Client {
public static void main(String[] args) {
//具体的房东:真实角色
Host host=new Host();
//代理角色:去代理的真实角色
Proxy proxy = new Proxy(host);
//不用去找房东,直接去找中介就可以完成租房
proxy.rentHouse();
}
}
静态代理的好处:
可以使得我们的真实角色更加纯粹,不再去关注一些公共的事情
公共的业务由代理来完成,实现了业务的分工
公共业务发生扩展时变得更加集中和方便
缺点 :
随着我们的被代理对象的增多 , 代理类变多 , 工作量变大了 . 开发效率降低 .
我们想要静态代理的好处,又不想要静态代理的缺点,所以 , 就有了动态代理 !
1.2 动态代理
-
动态代理的角色和静态代理的一样 .
-
动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的
-
动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
基于接口的动态代理----JDK动态代理 基于类的动态代理--cglib 现在用的比较多的是 javasist 来生成动态代理 . 百度一下javasist
JDK的动态代理需要了解两个类
核心 : InvocationHandler和Proxy
【InvocationHandler:调用处理程序】
【Proxy : 代理】
具体实现
1.创建接口,一般为抽象角色
package com.chen.demo3;
//抽象角色:表示出租房子这件事,一般是接口或者抽象
public interface Rent2 {
//表示出租的房子
void rentHouse();
}
2.创建真实角色,去实现接口
package com.chen.demo3;
//房东:真实角色 要被代理的角色
public class Host2 implements Rent2 {
//表示房东出租房子
public void rentHouse() {
System.out.println("房东要出租房子");
}
}
3.创建动态代理类ProxyInvocationHandler 实现InvocationHandler 接口
package com.chen.Demo3;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//代理类
public class ProxyInvocationHandler implements InvocationHandler {
//实现的接口 真实对象
private Object target;
public void setTarget(Object target) {
this.target = target;
System.out.println("没生成代理对象的class对象:"+this.target.getClass());
}
/*newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
loader - 定义代理类的类加载器 interfaces 代理类要实现的接口列表 h - 指派方法调用的调用处理程序
返回结果:一个带有代理类的指定调用处理程序的代理对象
*/
//返回动态代理对象
public Object getProxy(){
//通过 Proxy.newProxyInstance 创建的代理对象是在jvm运行时动态生成的一个对象
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}
/**
*
* @param proxy:我们所代理的那个真实对象的代理对象
* @param method:我们所要调用真实对象的某个方法的Method对象
* @param args
* @return 从代理实例的方法调用返回的值
* @throws Throwable
*/
//处理代理实例 返回结果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Method:" + method.getName());
System.out.println("生成代理对象的class对象:"+proxy.getClass());
//当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
Object result = method.invoke(target);
return result;
}
}
4.测试
package com.chen.Demo3;
//租房子的客户 :访问代理对象的人
public class Client {
public static void main(String[] args) {
//具体的房东:真实对象
Rent2 host=new Host2();
//此时还没有代理对象
ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
proxyInvocationHandler.setTarget(host);
//获取代理对象
Rent2 proxy = (Rent2) proxyInvocationHandler.getProxy();
//当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
proxy.rentHouse();
}
}
核心:一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个类,代理的是接口!
动态代理的好处:
静态代理有的它都有,静态代理没有的,它也有!
可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .
公共的业务由代理来完成 . 实现了业务的分工 ,
公共业务发生扩展时变得更加集中和方便 .
一个动态代理 , 一般代理某一类业务
一个动态代理可以代理多个类,代理的是接口!