动态代理其实现主要通过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源码。
作者:像少年啦飞驰
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.