一、代理概念
为某个对象提供一个代理,以控制对这个对象的访问。 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理。
二.代理模式
从图中可以看出,代理接口(Subject)、代理类(ProxySubject)、委托类(RealSubject)形成一个“品”字结构。
根据代理类的生成时间不同可以将代理分为静态代理和动态代理两种。
下面以一个模拟需求说明静态代理和动态代理:委托类要处理一项耗时较长的任务,客户类需要打印出执行任务消耗的时间。解决这个问题需要记录任务执行前时间和任务执行后时间,两个时间差就是任务执行消耗的时间。
二、静态代理
由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。
接下来,我们来看看静态代理的案例
先定义一个接口类
package aop005; public interface Girl {
public void KFC(String datetime);
public void meet(String datetime);
}
然后分别定义两个类
package aop005; /*
*
*/
public class Girl1 implements Girl{ public void KFC(String datetime){ System.out.println("[核心业务逻辑]我是第一个女孩");
System.out.println("[核心业务逻辑]"+datetime+"吃肯德基");
} public void meet(String datetime){ System.out.println("[核心业务逻辑]我是第一个女孩");
System.out.println("[核心业务逻辑]"+datetime+"约会"); } }
package aop005; /*
*
*/
public class Girl2 implements Girl { public void KFC(String datetime){
System.out.println("[核心业务逻辑]我是第二个女孩");
System.out.println("[核心业务逻辑]"+datetime+"吃肯德基");
} public void meet(String datetime){
System.out.println("[核心业务逻辑]我是第二个女孩");
System.out.println("[核心业务逻辑]"+datetime+"约会");
} }
接着我们建一个静态代理类
package aop005; /*
* 本例是静态代理
* 1、经纪人和要明星,必须实现同一个接口
* 2、把明星作为一个本类的一个属性,用于调用
*/
public class GirlProxy implements Girl {
private Girl g; public GirlProxy(String name){
if ("girl1".equals(name)){
g = new Girl1();
}else if ("girl2".equals(name)){
g = new Girl2();
}
} @Override
public void KFC(String datetime) {
System.out.println("洗澡");
System.out.println("化妆");
System.out.println("穿衣服");
System.out.println("*****************"); g.KFC(datetime); System.out.println("*****************");
System.out.println("卸妆");
System.out.println("洗澡");
System.out.println("睡觉");
} @Override
public void meet(String datetime) {
System.out.println("洗澡");
System.out.println("化妆");
System.out.println("穿衣服");
System.out.println("*****************"); g.meet(datetime); System.out.println("*****************");
System.out.println("卸妆");
System.out.println("洗澡");
System.out.println("睡觉");
} }
接着我们来弄一个测试类
package aop005; /*
* 增加一个【静态代理类】,类似与明星的经纪人
* 把核心的业务逻辑的代码 和 非核心的 分离
* 把非核心的代码交给经纪人(proxy)去管理,
* 注意:经纪人和要明星,必须实现同一个接口
*
* 缺点:
* 1.每个点都需要写一次
* 2.当分离出来的非核心代码,如果一旦需要修改,那么全体都要改
*/
public class Test { public static void main(String[] args) { Girl g1 = new GirlProxy("girl1");
Girl g2 = new GirlProxy("girl2"); g1.KFC("周六");
g1.meet("周日"); g2.KFC("周六");
g2.meet("周日");
} }
测试结果如下:
通过上面的案例我们可以发现,如果我们如果我们需要改非核心的业务代码,那我们这里就要改2次。
换句话说:我们有几个非核心业务我们就要改几次。
这也就为我们后面为什么要使用动态代理做了铺垫。