原文链接:http://www.cnblogs.com/flyoung2008/archive/2011/10/06/2199160.html
动态代理其实现主要通过java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。
步骤如下:
1、 首先获取一个业务接口的实现对象
2、 获取一个InvocationHandler实现
3、创建动态代理对象
4、通过动态代理对象调用方法
业务接口
package com.flyoung; public interface HelloWorld { public void sayHello(); }
业务接口实现
package com.flyoung; public class HelloWorldIml implements HelloWorld { public void sayHelloWorld() { System.out.println("Hello World!!!"); } }
InvocationHandler实现类
package com.flyoung; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class HelloWorldHandler implements InvocationHandler { private Object proxyObj;//要代理的对象 public HelloWorldHandler(Object obj){ this.proxyObj = obj; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result; result = method.invoke(this.proxyObj, args); return result; } }
测试类
package com.flyoung; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Test { public static void main(String[] args) { HelloWorld hw = new HelloWorldIml(); InvocationHandler handler = new HelloWorldHandler(hw); HelloWorld proxy = (HelloWorld)Proxy.newProxyInstance(hw.getClass().getClassLoader(), hw.getClass().getInterfaces(), handler); proxy.sayHelloWorld(); } }
扩展阅读:Java 动态代理机制分析及扩展
感觉原文的例子有问题,改了一下
通过动态代理实现简单的AOP。
基本思路:通过读取xml配置文件获取要被处理的对象,动态创建类的实例,并使用动态代理为该实例添加日志管理。
定义日志枚举类型
package com.flyoung; public enum Level { INFO,DEBUG; }
定义日志类
package com.flyoung; import java.util.Date; public class Logger { public static void logging(Level level,String context){ if(level.equals(Level.DEBUG)){ System.out.println(new Date().toString()+""+context); } if(level.equals(Level.INFO)){ System.out.println(new Date().toString()+""+context); } } }
业务接口
package com.flyoung; public interface HelloWorld { public void sayHelloWorld(); }
业务接口实现
package com.flyoung; public class HelloWorldIml implements HelloWorld { public void sayHelloWorld() { System.out.println("Hello World!!!"); } }
定义操作者接口
package com.flyoung; import java.lang.reflect.Method; public interface Operation { public void start(Method method); public void end(Method method); }
实现操作者接口
package com.flyoung; import java.lang.reflect.Method; public interface OperationImpl { public void start(Method method){ //拦截器开始 } public void end(Method method){ //拦截器结束 } }
实现InvocationHandler
package com.flyoung; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyHelloWorld implements InvocationHandler { Object operation;//操作者 Operation delegate;//要处理的对象 public Object bind(Object delegate,Operation operation){ this.delegate=delegate; this.operation=operation; return Proxy.newProxyInstance(this.delegate.getClass().getClassLoader(), this.delegate.getClass().getInterfaces(), this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result=null; operation.start();//执行start方法 //执行要处理对象方法 result=method.invoke(this.delegate, args); operation.end();//执行end方法 return result; } }
xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <package> <action name="hello" class="com.flyoung.HelloWorldIml"></action> </package>
使用dom4j读取xml配置文件
package com.flyoung; import org.dom4j.io.SAXReader; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.Attribute; import java.util.Iterator; import java.util.List; import java.io.File; import java.util.Map; import java.util.HashMap; public class TestDom4j { /** * 获取指定xml文档的Document对象,xml文件必须在classpath中可以找到 * * @param xmlFilePath xml文件路径 * @return Document对象 */ public static Document parse2Document(String xmlFilePath){ SAXReader reader = new SAXReader(); Document doc = null; try { doc = reader.read(new File(xmlFilePath)); } catch (DocumentException e) { e.printStackTrace(); } return doc; } public static Map testParseXmlData(String xmlFilePath){ //获取xml解析器对象 //SAXReader reader = new SAXReader(); //将xml解析为Document对象 Document doc = TestDom4j.parse2Document(xmlFilePath); //获取文档的根元素 Element root = doc.getRootElement(); //定义保存xml数据的缓冲字符串 //StringBuffer sb = new StringBuffer(); //定义保存属性、值的map Map<String,String> map = new HashMap<String,String>(); for(Iterator i_action=root.elementIterator();i_action.hasNext();){ Element e_action = (Element)i_action.next(); for(Iterator a_action=e_action.attributeIterator();a_action.hasNext();){ Attribute attribute = (Attribute)a_action.next(); //sb.append(attribute.getName()+":"+attribute.getValue()); //sb.append("\n"); map.put(attribute.getName(), attribute.getValue()); } } //System.out.println(sb); return map; } public static void main(String[] args) { Map map = TestDom4j.testParseXmlData("E:/workspace/Dom4j/test.xml"); String className =(String)map.get("class"); try { Class c = Class.forName(className); HelloWorld hw =(HelloWorld) c.newInstance(); hw.sayHelloWorld(); } catch (ClassNotFoundException e) { e.printStackTrace(); }catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
测试类
package com.flyoung; import java.util.Map; public class Test { public static void main(String[] args) { Map map = TestDom4j.testParseXmlData("E:/workspace/Dom4j/test.xml"); String className =(String)map.get("class"); try { Class c = Class.forName(className); HelloWorld hw =(HelloWorld) c.newInstance(); //hw.sayHelloWorld(); HelloWorld h = (HelloWorld)new ProxyHelloWorld().bind(hw, new OperationIml()); h.sayHelloWorld(); } catch (ClassNotFoundException e) { e.printStackTrace(); }catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
测试结果
Thu Oct 06 14:14:20 CST 2011 sayHelloWorld---start--- Hello World!!! Thu Oct 06 14:14:20 CST 2011 sayHelloWorld---end---
下面要做的是回去读spring源码。
作者:
像少年啦飞驰
Blog:
http://www.flyoung.me
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.