锁定老帖子 主题:复习:代理模式
精华帖 (0) :: 良好帖 (2) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-10-17
最后修改:2011-10-17
代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,如图1所示。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。 图1:Proxy模式
按照代理类的创建时期,代理类可分为两种。
静态代理类的实现:
1. 定义一个IService接口 package cn.lettoo.proxy; public interface IService { void execute(); }
2. 具体的实现类: package cn.lettoo.proxy; public class PrintService implements IService { public void execute() { System.out.println("The Print Service works."); } }
3. 代理类: package cn.lettoo.proxy; public class PrintServiceProxy implements IService { IService printSerivce; public PrintServiceProxy(IService service) { this.printSerivce = service; } public void setPrintSerivce(IService printSerivce) { this.printSerivce = printSerivce; } public void execute() { this.beforePrint(); this.printSerivce.execute(); this.afterPrint(); } private void beforePrint() { System.out.println("Before print."); } private void afterPrint() { System.out.println("Before print."); } } 代理类的execute()方法只是调用了被代理的Service的execute方法,被代理的Service通过构造函数或者set的方式被注入到代理对象中。同时,代理对象也有一些自己的代理方法,如本例中在被代理类的execute()方法调用前后加上自己的方法。
4. 客户调用代码: package cn.lettoo.proxy; public class Client { public static void main(String[] args) { IService service = new PrintService(); IService proxy = new PrintServiceProxy(service); proxy.execute(); } }
执行结果
Before print.
The Print Service works. Before print.
动态代理的实现:
与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。
Proxy类提供了创建动态代理类及其实例的静态方法。 Porxy有两种方式来生成代理对象: 方法1: //创建InvocationHandler对象 InvocationHandler handler = newMyInvocationHandler(...); //创建动态代理类,IService是被代理的接口 Class proxyClass = Proxy.getProxyClass(IService.class.getClassLoader(), new Class[] { IService.class }); //创建动态代理类的实例 IService proxyService = (IService) proxyClass.getConstructor(new Class[] { invocationHandler.class }).newInstance(new Object[] { handler }); 方法2: //创建InvocationHandler对象 InvocationHandler handler = newMyInvocationHandler(...); //直接创建动态代理类的实例 IService serviceProxy = (IService) Proxy.newProxyInstance(IService.class.getClassLoader(), new Class[] { IService.class }, handler);
InvocationHandler 接口为方法调用接口,它声明了负责调用任意一个方法的invoke()方法: Object invoke(Object proxy,Method method,Object[] args) throws Throwable
代码实现: 1. 写一个ServiceFactory,用于生成代理对象 package cn.lettoo.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ServiceFactory { public static IService getServiceProxy(final IService service) { InvocationHandler handler = new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { beforePrint(); Object result = method.invoke(service, args); afterPrint(); return result; } }; return (IService) Proxy.newProxyInstance(IService.class.getClassLoader(), new Class[] { IService.class }, handler); } private static void beforePrint() { System.out.println("Before print."); } private static void afterPrint() { System.out.println("Before print."); } }
2. 客户端代码: package cn.lettoo.proxy; public class Client { public static void main(String[] args) { IService service = new PrintService(); IService proxy = ServiceFactory.getServiceProxy(service); proxy.execute(); } }
运行结果
Before print.
The Print Service works. Before print.
也许有人要问,采用动态代理有什么好处?那么我告诉你,你不需要为每个IService的实现类都去写一个Proxy类了(前提是代理方法是一样的),假如,我现在有另外一个IService的实现类如下: package cn.lettoo.proxy; public class AnotherService implements IService { public void execute() { System.out.println("I am another service."); } }
现在客户端只要这样写: public static void main(String[] args) { IService service = new AnotherService(); IService proxy = ServiceFactory.getServiceProxy(service); proxy.execute(); }
运行结果
Before print.
I am another service. Before print. 可以看到,不需要单独再为AnotherService写一个代理类了,动态代理类会帮助我们去实现的。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-10-25
常用的设计模式,复习复习。
|
|
返回顶楼 | |
发表时间:2011-10-30
不错,动态代理说的很清晰
|
|
返回顶楼 | |
发表时间:2011-10-31
lettoo 写道
代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,如图1所示。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。 图1:Proxy模式
按照代理类的创建时期,代理类可分为两种。
静态代理类的实现:
1. 定义一个IService接口 package cn.lettoo.proxy; public interface IService { void execute(); }
2. 具体的实现类: package cn.lettoo.proxy; public class PrintService implements IService { public void execute() { System.out.println("The Print Service works."); } }
3. 代理类: package cn.lettoo.proxy; public class PrintServiceProxy implements IService { IService printSerivce; public PrintServiceProxy(IService service) { this.printSerivce = service; } public void setPrintSerivce(IService printSerivce) { this.printSerivce = printSerivce; } public void execute() { this.beforePrint(); this.printSerivce.execute(); this.afterPrint(); } private void beforePrint() { System.out.println("Before print."); } private void afterPrint() { System.out.println("Before print."); } } 代理类的execute()方法只是调用了被代理的Service的execute方法,被代理的Service通过构造函数或者set的方式被注入到代理对象中。同时,代理对象也有一些自己的代理方法,如本例中在被代理类的execute()方法调用前后加上自己的方法。
4. 客户调用代码: package cn.lettoo.proxy; public class Client { public static void main(String[] args) { IService service = new PrintService(); IService proxy = new PrintServiceProxy(service); proxy.execute(); } }
执行结果
Before print.
The Print Service works. Before print.
动态代理的实现:
与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。
Proxy类提供了创建动态代理类及其实例的静态方法。 Porxy有两种方式来生成代理对象: 方法1: //创建InvocationHandler对象 InvocationHandler handler = newMyInvocationHandler(...); //创建动态代理类,IService是被代理的接口 Class proxyClass = Proxy.getProxyClass(IService.class.getClassLoader(), new Class[] { IService.class }); //创建动态代理类的实例 IService proxyService = (IService) proxyClass.getConstructor(new Class[] { invocationHandler.class }).newInstance(new Object[] { handler }); 方法2: //创建InvocationHandler对象 InvocationHandler handler = newMyInvocationHandler(...); //直接创建动态代理类的实例 IService serviceProxy = (IService) Proxy.newProxyInstance(IService.class.getClassLoader(), new Class[] { IService.class }, handler);
InvocationHandler 接口为方法调用接口,它声明了负责调用任意一个方法的invoke()方法: Object invoke(Object proxy,Method method,Object[] args) throws Throwable
代码实现: 1. 写一个ServiceFactory,用于生成代理对象 package cn.lettoo.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ServiceFactory { public static IService getServiceProxy(final IService service) { InvocationHandler handler = new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { beforePrint(); Object result = method.invoke(service, args); afterPrint(); return result; } }; return (IService) Proxy.newProxyInstance(IService.class.getClassLoader(), new Class[] { IService.class }, handler); } private static void beforePrint() { System.out.println("Before print."); } private static void afterPrint() { System.out.println("Before print."); } }
2. 客户端代码: package cn.lettoo.proxy; public class Client { public static void main(String[] args) { IService service = new PrintService(); IService proxy = ServiceFactory.getServiceProxy(service); proxy.execute(); } }
运行结果
Before print.
The Print Service works. Before print.
也许有人要问,采用动态代理有什么好处?那么我告诉你,你不需要为每个IService的实现类都去写一个Proxy类了(前提是代理方法是一样的),假如,我现在有另外一个IService的实现类如下: package cn.lettoo.proxy; public class AnotherService implements IService { public void execute() { System.out.println("I am another service."); } }
现在客户端只要这样写: public static void main(String[] args) { IService service = new AnotherService(); IService proxy = ServiceFactory.getServiceProxy(service); proxy.execute(); }
运行结果
Before print.
I am another service. Before print. 可以看到,不需要单独再为AnotherService写一个代理类了,动态代理类会帮助我们去实现的。
|
|
返回顶楼 | |
发表时间:2011-11-24
很好,将的很明了。!
|
|
返回顶楼 | |
发表时间:2011-12-02
很经典的代理模式,讲得很清楚了。
|
|
返回顶楼 | |
发表时间:2012-03-15
真的讲的很不错,顶
|
|
返回顶楼 | |
发表时间:2012-09-24
简单易懂,学习啦,顶。。。。。
|
|
返回顶楼 | |
浏览 6028 次