目录
一、使用场景
通过代理,控制对类/对象的访问。
我们用一个代理对象把真实对象包装起来,真实对象的所有动作都通过代理对象去做,代理对象可以决定是否以及何时由真实类去做,何时由代理类去做。 (其实它跟适配器模式一模一样!)
比如,一个明星(如刘德华),在接到一个演出合同的时候,需要做一系列的事情。 面谈,签合同,收预付款,订机票,演出,收尾款等。但是这些事情中的一些其实繁琐又低价值,可以交给他的经济人或者秘书来处理,他只要负责演出的部分就可以了。这就是静态代理的作用,在做重要的事情之前做一些前置工作或者之后做一些后续处理。
一些应用场景:
- 安全代理: 屏蔽对真实角色的直接访问
- 远程代理: 通过代理类处理远程方法调用(RMI)
- 延迟加载:先加载轻量级的代理真正需要的时候再加载真实对象。
二、静态代理
实现要点:
1. Star接口, 规定明星有哪些工作
2. RealStar类, implements Star接口,实现真实的明星的职能。
3.ProxyStar类, 明星的代理类, 其中包含一个RealStar类的对象,同样implements Star接口,在各个方法中决定哪些由代理做,哪些必须由明星本人去做。
代码实现:
1. Star接口,声明有哪些工作。
public interface Star {
public void meet();
public void signContract();
public void bookTicket();
public void show();
public void getMoney();
}
2. RealStar类 实现真实的明星的职能。
public class RealStar implements Star {
@Override
public void meet() {
System.out.println("明星去面谈");
}
@Override
public void signContract() {
System.out.println("明星去签合同");
}
@Override
public void bookTicket() {
System.out.println("明星去订机票");
}
@Override
public void show() {
System.out.println("明星去演出");
}
@Override
public void getMoney() {
System.out.println("明星去收尾款");
}
}
3. ProxyStar类 明星的代理类
public class ProxyStar implements Star {
private Star star;
public ProxyStar(Star star) {
this.star = star;
}
@Override
public void meet() {
System.out.println("代理去面谈");
}
@Override
public void signContract() {
System.out.println("代理去签合同");
}
@Override
public void bookTicket() {
System.out.println("代理去订机票");
}
@Override
public void show() {
star.show(); //这个功能必须由realStar去完成
}
@Override
public void getMoney() {
System.out.println("代理去收尾款");
}
}
4. 测试类
public class ClientTest {
public static void main(String[] args) {
ProxyStar proxyStar = new ProxyStar(new RealStar());
proxyStar.meet();
proxyStar.signContract();
proxyStar.bookTicket();
proxyStar.show();
proxyStar.getMoney();
}
}
测试结果
演出是由明星去做的,在演出之前和之后的其他工作都是由代理去做的。
三、 动态代理
代理需要由自己去写的话,可能会比较麻烦。比如,要写一个日志代理,打印正在调用的方法及参数,可能就要在不同的方法中添加大量重复的代码。
而实际上,我们可以使用动态代理模式,让其在调用的过程中动态改变参数和信息,一处添加,处处使用。
Star接口
public interface Star {
public void communicate();
public void signContract();
public void orderTickets();
public void show();
public void collectMoney();
}
RealStar实现
public class RealStar implements Star {
@Override
public void communicate() {
System.out.println("真明星去谈业务.");
}
@Override
public void signContract() {
System.out.println("真明星去签合同.");
}
@Override
public void orderTickets() {
System.out.println("真明星去订票.");
}
@Override
public void show() {
System.out.println("真明星去演出.");
}
@Override
public void collectMoney() {
System.out.println("真明星去收款.");
}
}
StarProxy类,在其内部生成动态代理类
public class StarProxy {
private Star star;
public StarProxy(Star star) {
this.star = star;
}
private class StarHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//打印日志
System.out.println("invoking method " + method.getName());
//执行前可以加入一些动作,比如AOP中的方法
Object result = null;
if("show" == method.getName()){
result = method.invoke(star, args); //只有show方法才由原类去执行
}
//AOP中的方法也可以加在执行后
return result;
}
}
//公开的方法对外提供动态生成的代理类
public Star getProxy(){
ClassLoader loader = ClassLoader.getSystemClassLoader();
Class[] clz = new Class[]{Star.class};
InvocationHandler handler = new StarHandler();
return (Star) Proxy.newProxyInstance(loader, clz, handler);
}
public static void main(String[] args) {
Star star = new RealStar();
Star proxy = new StarProxy(star).getProxy();
proxy.communicate();
proxy.signContract();
proxy.orderTickets();
proxy.show();
proxy.collectMoney();
}
}
执行结果
可以看出动态生成的代理类也可以执行前面的代码,而且在invoke方法添加的功能可以在所有方法中执行。