老僧长谈设计模式-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)方法是个后置处理方法。
测试类
/** * 代理测试类,使用代理 * * @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的代理模式详解
- 老僧长谈设计模式-7-代理模式2
- 老僧长谈设计模式-7-代理模式
- 老僧长谈设计模式-2-工厂模式
- 老僧长谈设计模式-1-单例模式
- 老僧长谈设计模式-3-策略模式
- 老僧长谈设计模式-4-观察者模式
- 老僧长谈设计模式-5-装饰者模式
- 老僧长谈设计模式-6-状态模式
- 老僧长谈设计模式-8-命令模式
- 老僧长谈设计模式-9-责任链模式
- 老僧长谈设计模式-10-桥接模式
- 老僧长谈设计模式-11-原型模式
- 老僧长谈设计模式-0-六大原则
- 设计模式(7) ------------代理模式
- 设计模式7:代理模式
- 设计模式:7 代理模式
- 设计模式(2)-代理模式
- 设计模式:7)代理设计模式
- 【C++】C++常见面试题汇总_持续更新中...
- ArrayList源码分析
- 基于OpenSSL颁发数字证书的一个完整实例
- rosen老师 的gitconfig配置
- python3爬虫伪装代理IP
- 老僧长谈设计模式-7-代理模式2
- 游戏中的小地图
- spring boot实战(第三篇)事件监听源码分析
- 华为打开日志方法
- LinkedList源码分析
- Hadoop之Hive
- 每天回顾linux命令(date)
- 树的遍历
- 操作系统安装