老僧长谈设计模式-7-代理模式2

来源:互联网 发布:vb里头mid函数查找 编辑:程序博客网 时间:2024/05/23 20:17

说明;

对前一篇 老僧长谈设计模式-7-代理模式 的补充

1.静态代理模式


讲一个说话和唱歌的故事,

你有一个接口ITalk,接口中有一个方法talk(),然后你还有一个Real Request类实现了ITalk接口。

但是光是说话满足不了全部人的要求,有的人还喜欢唱歌。

怎么办?难道在接口中再增加sing()方法吗?不可能的,那样的话所有该接口的实现类都不得不实现该方法啦。

此时一个聪明的办法是写一个代理类TalkProxy,其中不光有talk(),而且还有sing();

Proxy类

/** * 代理主题角色:内部包含对真实主题的引用,并且提供和真实主题角色相同的接口。 *  * @author yanbin *  */public class TalkProxy implements ITalk {    private ITalk talker;    public TalkProxy(ITalk talker) {        // super();        this.talker = talker;    }    public void talk(String msg) {        talker.talk(msg);    }        /**     * good,重载方法巧妙调用sing()     * @param msg     * @param singname     */    public void talk(String msg, String singname) {        talker.talk(msg);        sing(singname);    }    private void sing(String singname) {        System.out.println("唱歌:" + singname);    }}


从这段代码可以看出来,代理模式其实就是AOP的雏形。 上端代码中talk(String msg, String singname)是一个切面。在代理类中的sing(singname)方法是个后置处理方法。

这样就实现了,其他的辅助方法和业务方法的解耦。业务不需要专门去调用,而是走到talk方法,顺理成章的调用sing方法

测试类

/** * 代理测试类,使用代理 * * @author yanbin *  */public class ProxyPattern {    public static void main(String[] args) {        // 不需要执行额外方法的。        ITalk people = new PeopleTalk("AOP", "18");        people.talk("No ProXY Test");        System.out.println("-----------------------------");        // 需要执行额外方法的(切面)        ITalk talker = new new TalkProxy(people);        talker.talk("ProXY Test", "千里之外");    }}



2.动态代理模式InvocationHandler

jdk1.5中提供,利用反射。实现java.lang.reflect.InvocationHandler接口

①必须要有一个业务接口

/** * @author          * @version        V1.0   * @Date            * @Email * @Description:   抽象主题角色 Subject */public interface ITalk {public void talk(String msg);}


②接口实现类

/** * @author          * @version        V1.0   * @Date             * @Email * @Description:   Real Request */public class PeopleTalk implements ITalk {private String username;private String age;public PeopleTalk() {this("James", "30");}public PeopleTalk(String username, String age) {this.username = username;this.age = age;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getAge() {return age;}public void setAge(String age) {this.age = age;}@Overridepublic void talk(String msg) {// TODO Auto-generated method stubSystem.out.println(msg + "!你好,我是" + this.getUsername() + ",年龄" + this.getAge());}}


③动态代理类

/** * @author          * @version        V1.0   * @Date            * @Email * @Description:   动态代理  */public class DynamicProxy implements InvocationHandler {/*需要代理的目标类*/private Object target;/** * 绑定委托对象并返回一个代理类 * @param target * @return */public Object bind(Object target) {// TODO Auto-generated method stubthis.target = target;/** * 返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序 * @param loader - 定义代理类的类加载器 * @param interfaces - 代理类要实现的接口列表 * @param h - 指派方法调用的调用处理程序 InvocationHandler类invoke()方法 */return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);}/** * @param Object proxy 被代理的对象 * @param Method method 要调用的方法 * @param Object[] args 方法调用时需要的参数  */@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// TODO Auto-generated method stubObject result = null;//切面之前执行System.out.println("切面之前执行.");//执行业务result = method.invoke(target, args);//切面之后执行System.out.println("切面之后执行.");return result;}}

④测试类

/** * @author          * @version        V1.0   * @Date             * @Email * @Description:   代理测试类 */public class ProxyTest {public static void main(String[] args) {ITalk talk = (ITalk) new DynamicProxy().bind(new PeopleTalk());talk.talk("业务说明");}}


3.动态代理Cglib

CGLIB是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强。采用的是继承的方式。

使用范围:对于不适用接口的业务类,无法使用JDK动态代理
原理:CGlib采用非常底层的字节码技术,可以为一个类创建子类,解决无接口类的代理类问题。

①业务类,不实现任何的接口

/**  * 该业务类没有实现任何接口  * @author dell  *  */  public class Cat {        public void run(){          System.out.println("猫可以跑步。。。捉老鼠");      }  }  

②动态代理类

import java.lang.reflect.InvocationHandler;  import java.lang.reflect.Method;  import java.lang.reflect.Proxy;    import net.sf.cglib.proxy.Enhancer;  import net.sf.cglib.proxy.MethodInterceptor;  import net.sf.cglib.proxy.MethodProxy;    import org.junit.Test;    public class ProxyTest {            @Test      public void demo2(){          // cglib 动态代理  在目标业务类没有实现接口的情况下                    // 1、创建真实业务对象的引用          Cat cat = new Cat();          // 2、创建真实业务类的子类          Enhancer enhancer = new Enhancer();          enhancer.setSuperclass(cat.getClass());                    // 3、设置回调函数          enhancer.setCallback(new MethodInterceptor() {                            @Override              public Object intercept(Object proxy, Method method, Object[] args,                      MethodProxy methodProxy) throws Throwable {                  if(method.getName().equals("run")){                      System.out.println("cat的run方法被拦截了。。。。");                      Object invoke = method.invoke(proxy, args);                      System.out.println("真实方法拦截之后。。。。");                      return invoke;                  }                                    // 不拦截                  return method.invoke(proxy, args);              }          });          Cat proxy = (Cat) enhancer.create();                    proxy.run();      }  } 


----------------------------------------------------------------------------

来源参考

http://blog.csdn.net/mrzhoug/article/details/51336833
设计模式(1)--理解AOP(代理模式)
http://blog.csdn.net/judyfun/article/details/45974223
Spring AOP的代理模式详解

原创粉丝点击