如何利用动态代理技术构建一个通用的,获取代理类的简单框架?
2014-10-09 23:12
1061 查看
如果需要为许多方法添加额外的操作,就如数据库的事务日志,你需要对数据库的每一项操作都做个记录,
那么多的方法,如果手工编写的话,不仅费时,而且臃肿不堪。这时候java代理技术就起作用了,通过java的动态代理可以非常方便的为一个类的多种方法添加额外的操作。
在java中有一个类是 java.lang.reflect.Proxy;他的一个方法可以非常方便的创建代理对象
Objectjava.lang.reflect.Proxy.newProxyInstance(ClassLoader
loader, Class<?>[] interfaces,InvocationHandler
h) throwsIllegalArgumentException
它接收三个参数:
1.loader 代理目标类用哪个加载器加载,
2.interfaces 需要为目标类的哪些方法添加操作,通过传入目标类所实现的接口而获取
3.InvocationHandler 这是一个抽象类,你需要实现它的invoke() 方法用来添加额外的操作
在添加额外的操作时可以通过传入通告对象,执行通告对象的方法来实现。
有了这三样东西,就可以动态构建一个为目标类生产的代理对象了。
那么,为了将这些操作构建为一个框架,我们需要下面2个元素:
1. 代理目标:要为哪个类构建代理 (什么来加载器,接口,都可以通过反射反射该类得到)
2. 通告对象:所有的额外操作都可以通过调用该对象的方法实现
现在这些元素写在一个配置文件中,以便于更改 如下
-----------------------------
config.propertice
className=java.util.ArrayList
class.Advice=MyAdvice
----------------------------
还可以直接指定目标类,和通告对象
-----------------------------
setTarget(Object target)
setAdvice(Object advice)
-------------------------------
有了这些元素,就可以开始编写代理类了
类结构上图
其中的方法getProxy()内部就是调用的newProxyInstance
=============分割线,下面是源代码=============================================
那么多的方法,如果手工编写的话,不仅费时,而且臃肿不堪。这时候java代理技术就起作用了,通过java的动态代理可以非常方便的为一个类的多种方法添加额外的操作。
在java中有一个类是 java.lang.reflect.Proxy;他的一个方法可以非常方便的创建代理对象
Objectjava.lang.reflect.Proxy.newProxyInstance(ClassLoader
loader, Class<?>[] interfaces,InvocationHandler
h) throwsIllegalArgumentException
它接收三个参数:
1.loader 代理目标类用哪个加载器加载,
2.interfaces 需要为目标类的哪些方法添加操作,通过传入目标类所实现的接口而获取
3.InvocationHandler 这是一个抽象类,你需要实现它的invoke() 方法用来添加额外的操作
在添加额外的操作时可以通过传入通告对象,执行通告对象的方法来实现。
有了这三样东西,就可以动态构建一个为目标类生产的代理对象了。
那么,为了将这些操作构建为一个框架,我们需要下面2个元素:
1. 代理目标:要为哪个类构建代理 (什么来加载器,接口,都可以通过反射反射该类得到)
2. 通告对象:所有的额外操作都可以通过调用该对象的方法实现
现在这些元素写在一个配置文件中,以便于更改 如下
-----------------------------
config.propertice
className=java.util.ArrayList
class.Advice=MyAdvice
----------------------------
还可以直接指定目标类,和通告对象
-----------------------------
setTarget(Object target)
setAdvice(Object advice)
-------------------------------
有了这些元素,就可以开始编写代理类了
类结构上图
其中的方法getProxy()内部就是调用的newProxyInstance
=============分割线,下面是源代码=============================================
package zhangweiocng.autoProxy; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Properties; import java.util.ArrayList; /** * * 要想获得一个代理类,必须先传入一个配置好的文件,或者指定目标类和通告类 * @author weicong * */ public class AutoProxy { private Object target; private Advice advice; private Properties properties; public Object getProxy(){ Object clazz = Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler(){ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { advice.beforeMethod(method); Object returnValue =method.invoke(target, args); System.out.println("--executeMethod--"+method.getName()); advice.afterMethod(method); return returnValue; } } ); return clazz; } public void setProperties(InputStream inStream){ this.properties=new Properties(); try { properties.load(inStream); target=getTarget(); advice=getAdvice(); } catch (IOException e) { System.out.println("未成功加载配置文件"); e.printStackTrace(); } } public Object getTarget() { String targetName = properties.getProperty("className.target"); Object target = null; try { Class clazz = Class.forName(targetName); target = clazz.newInstance(); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { System.out.println("target类加载出错"); e.printStackTrace(); } return target; } public void setTarget(Object target) { this.target = target; } public Advice getAdvice() { String adviceName = properties.getProperty("className.advice"); Advice advice = null; try { Class clazz = Class.forName(adviceName); advice = (Advice)clazz.newInstance(); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { System.out.println("advice类加载出错"); e.printStackTrace(); } return advice; } public void setAdvice(Advice advice) { this.advice = advice; } } -----------------文件分割标记----------------------------------------------------------- package zhangweiocng.autoProxy; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; public class AutoProxyTest { public static void main(String[] args) { AutoProxy autoProxy=new AutoProxy(); Advice advice=new MyAdvice(); ArrayList arrayList=new ArrayList(); InputStream inStream=null; Collection proxy=null; /* * 通过配置文件指定目标类和通告类 * try{ inStream=new FileInputStream("config.properties"); autoProxy.setProperties(inStream); proxy=( Collection )autoProxy.getProxy(); proxy.add("123"); proxy.add("456"); System.out.println(arrayList.toString()); System.out.println(arrayList.size()); }catch(IOException e){ System.out.println("文件不存在"); e.printStackTrace(); }*/ /*显式指定目标类和通告类*/ autoProxy.setTarget(arrayList); autoProxy.setAdvice(advice); proxy=(Collection )autoProxy.getProxy(); proxy.add("123"); proxy.add("456"); System.out.println(arrayList.toString()); System.out.println(arrayList.size()); } }
相关文章推荐
- 【远程调用框架】如何实现一个简单的RPC框架(三)优化一:利用动态代理改变用户服务调用方式
- 如何写一个RPC框架(二):利用Bean容器和动态代理简化客户端代码
- 如何构建一个较为通用的业务技术架构
- 如何利用VC++构建一个游戏框架
- 如何构建一个较为通用的业务技术架构
- 创业之初的技术题:如何构建一个较为通用的业务技术架构
- 利用Python的Flask框架来构建一个简单的数字商品支付解决方案
- 如何用phototype框架实现一个简单的ajax验证
- 利用反射技术动态执行方法时如何取引用类参数的值
- 利用反射技术动态获取任意Java类实例的属性值
- 利用反射技术动态获取任意Java类实例的属性值
- 用UDP实现可靠文件传输,如何利用UDX创建一个简单的WIN32程序
- iBATIS框架技术----一个简单的应用
- 一个非常简单的分页技术MYSQL+JSP 利用了mysql的LIMIT参数
- 一个简单的动态加载控件并保存控件信息的框架
- 快速构建一个简单的个人框架系列
- 如何使用Maven 3.0, Flex Mojos 4.0和Flex 4.5构建一个简单的SWF程序
- 用代理技术实现简单的AOP框架
- 服务器端获取客户端动态添加的表格行数据的一个简单示例
- 利用.NET Remoting基础架构中的真实代理/透明代理技术实现了不针对具体类型、具体方法的通用方法调用拦截机制