动态代理其实现主要通过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 Operation { 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 proxy;//操作者 Object delegate;//要处理的对象 public Object bind(Object delegate,Object proxy){ this.delegate=delegate; this.proxy=proxy; 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; //反射得到操作者的class Class c = this.proxy.getClass(); Method start = c.getDeclaredMethod("start", new Class[]{Method.class}); //反射执行start方法 start.invoke(this.proxy, new Object[]{method}); //执行要处理对象方法 result=method.invoke(this.delegate, args); //发射执行end方法 Method end = c.getDeclaredMethod("end", new Class[]{Method.class}); end.invoke(this.proxy, new Object[]{method}); 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源码。
来源:http://www.cnblogs.com/flyoung2008/archive/2011/10/06/2199160.html