设计模式-代理模式
一、代理模式
为其他对象提供一种代理以便控制对这个对象的访问。
可以详细控制访问某个类(对象)的方法,在调用这个方法前作的前置处理(统一的流程代码放到代理中处理)。调用这个方法后做后置处理。
二、代理模式分类
1.静态代理(静态定义代理类,我们自己静态定义的代理类。比如我们自己定义一个明星的经纪人类)
2.动态代理(通过程序动态生成代理类,该代理类不是我们自己定义的。而是由程序自动生成)比较重要!!
JDK自带的动态代理
javaassist字节码操作库实现
CGLIB
ASM(底层使用指令,可维护性较差)
三、静态代理
模式结构图:
静态代理模式一般会有三个角色:
抽象角色:指代理角色(经纪人)和真实角色(明星)对外提供的公共方法,一般为一个接口
真实角色:需要实现抽象角色接口,定义了真实角色所要实现的业务逻辑,以便供代理角色调用。也就是真正的业务逻辑在此。
代理角色:需要实现抽象角色接口,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
将统一的流程控制都放到代理角色中处理!
静态代理的实现模式:
首先创建一个接口(JDK代理都是面向接口的),
然后创建具体实现类来实现这个接口,
最后创建一个代理类同样实现这个接口,
不同之处在于,具体实现类的方法中需要将接口中定义的方法的业务逻辑功能实现,而代理类中的方法只要调用具体类中的对应方法即可,这样我们在需要使用接口中的某个方法的功能时直接调用代理类的方法即可,将具体的实现类隐藏在底层。
按照以上分析代码如下:
//第一步:定义总接口MyEvent.java public interface MyEvent { public void eventMethod(); }
/** * 第二步:创建具体实现类EventZhao.java * @author Administrator */ public class EventZhao implements MyEvent { public void eventMethod() { System.out.println("EventZhao中出事了"); } }
/** * 第三步:创建代理类StaticProxy.java * @author Administrator */ public class StaticProxy implements MyEvent { private EventZhao target; public StaticProxy(EventZhao target) { this.target = target; } @Override public void eventMethod() { System.out.println("如何为你去辩护。。。。。。。。。"); System.out.println("如何为你去辩护。。。。。。。。。"); System.out.println("如何为你去辩护。。。。。。。。。"); this.target.eventMethod(); System.out.println("拿钱。。。"); System.out.println("拿钱。。。"); System.out.println("拿钱。。。"); } }
测试类: public class KaiTing { public static void main(String[] args) { EventZhao ez=new EventZhao(); StaticProxy sp=new StaticProxy(ez); sp.eventMethod(); } }
测试结果:
如何为你去辩 护。。。。。。。。。 如何为你去辩护。。。。。。。。。 如何为你去辩护。。。。。。。。。 EventZhao中出事了 拿钱。。。 拿钱。。。 拿钱。。。 |
四、动态代理
动态代理的思维模式与静态模式是一样的,也是面向接口进行编码,创建代理类将具体类隐藏解耦,
不同之处在于代理类的创建时机不同,动态代理需要在运行时因需实时创建。
实现动态代理模式的方式有两种。
4.1依赖于jdk的Proxy对象下的newInstance方法
如果使用的是该方式来实现动态代理。要求必须要有事件,委托人必须要实现事件接口
代码实现:
/** * 第一步:定义总接口MyEvent.java * @author Administrator */ public interface MyEvent { public String sayHello(String msg); }
/** * 第二步:创建具体实现类MyTarget.java * @author Administrator */ public class MyTarget implements MyEvent { @Override public String sayHello(String msg) { // TODO Auto-generated method stub return "张三 say"+msg; } }
import java.lang.reflect.Proxy; /** * 创建测试类 * @author Administrator */ public class Test { public static void main(String[] args) { MyEvent e = new MyTarget(); MyProxy p = new MyProxy(e); MyEvent me = (MyEvent) Proxy.newProxyInstance(e.getClass() .getClassLoader(), e.getClass().getInterfaces(), p); String str = me.sayHello("hello world"); System.out.println(str); } }
运行结果:
张三 sayHELLO WORLD |
4.2 cglib字节码修改器
他与jdk中的实现动态代理方式不同的就是,委托人不需要实现特定的接口
如果使用cglib实现动态代理。不要忘记导入jar包。
代码实现:
import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CGLIBProxy implements MethodInterceptor { //要代理的原始对象 private Object obj; public Object createProxy(Object target) { this.obj = target; Enhancer enhancer = new Enhancer(); // 设置被代理对象目标 enhancer.setSuperclass(this.obj.getClass()); // 回调 enhancer.setCallback(this); enhancer.setClassLoader(target.getClass().getClassLoader()); return enhancer.create(); } /** * 在代理实例上处理方法调用并返回结果 * * @param proxy * 代理类 * @param method * 被代理的方法 * @param params * 该方法的参数数组 * @param methodProxy */ public Object intercept(Object proxy, Method method, Object[] params, MethodProxy methodProxy) throws Throwable { Object result = null; // 调用之前 doBefore(); // 调用原始对象的方法 result = methodProxy.invokeSuper(proxy, params); // 调用之后 doAfter(); return result; } private void doBefore() { System.out.println("before method invoke"); } private void doAfter() { System.out.println("after method invoke"); } }
public class MyTarget { public void sayHello(){ System.out.println("SayHello"); } }
测试类:
public class Test { /** * @param args */ public static void main(String[] args) { MyTarget m = new MyTarget(); CGLIBProxy proxy = new CGLIBProxy(); MyTarget mt = (MyTarget)proxy.createProxy(m); mt.sayHello(); } }
运行结果:
before method invoke SayHello after method invoke |
作 者:
Jony.K.Chen
出 处:http://www.cnblogs.com/lxcy/
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
特此声明:所有评论和私信都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是作者坚持原创和持续写作的最大动力!