`

动态代理-实现操作对象和业务对象解耦

阅读更多
在业务对象执行某个方法时,在业务方法前和方法后均让操作者执行相应操作(切面编程), 操作者和业务者均面向接口编程,并在代理类中
实现解耦。即操作方法和业务方法的执行能够最大限度独立。

1. 先定义日志等级:

package boke.javamode.log;
/**
 * 日志等级
 * 
 * @since jdk1.6
 * @author 毛正吉
 * @version 1.0
 * @date  2010.07.10
 * 
 */
public enum Level {
	INFO,WARN,DEBUG;
}


2. 日志类-可扩展

package boke.javamode.log;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 日志
 * 
 * @since jdk1.6
 * @author 毛正吉
 * @version 1.0
 * @date 2010.07.10
 * 
 */
public class Logger {
	public static void log(Level level, String logInfo) {
		if (level.equals(Level.INFO)) {
			System.out.println("Logger INFO : "
					+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
							.format(new Date()) + " " + logInfo);
		} else if (level.equals(Level.WARN)) {
			System.out.println("Logger WARN : "
					+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
							.format(new Date()) + " " + logInfo);
		} else if (level.equals(Level.DEBUG)) {
			System.out.println("Logger DEBUG : "
					+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
							.format(new Date()) + " " + logInfo);
		}
	}
}

3. 业务接口

package boke.javamode;
/**
 * 业务接口
 * 
 * @since jdk1.6
 * @author 毛正吉
 * @version 1.0
 * @date 2010.07.10
 * 
 */
public interface ISay {
	void sayHello(String name);

	void sayGoodBye(String name);
}

4. 业务对象

package boke.javamode;
/**
 * 业务对象
 * 
 * @since jdk1.6
 * @author 毛正吉
 * @version 1.0
 * @date 2010.07.10
 * 
 */
public class Say implements ISay {

	public void sayGoodBye(String name) {
		System.out.println("GoodBye " + name);

	}

	public void sayHello(String name) {
		System.out.println("Hello " + name);

	}

}

5. 操作者接口

package boke.javamode;

import java.lang.reflect.Method;

/**
 * 操作者接口
 * 
 * @since jdk1.6
 * @author 毛正吉
 * @version 1.0
 * @date  2010.07.10
 * 
 */
public interface IOperationExecutor {
	/**
	 * 方法执行之前的操作
	 * 
	 * @param method
	 */
	void start(Method method);

	/**
	 * 方法执行之前的操作
	 * 
	 * @param method
	 */
	void end(Method method);
}


6. 操作者实现

package boke.javamode;

import java.lang.reflect.Method;

import boke.javamode.log.Level;
import boke.javamode.log.Logger;

/**
 * 操作者实现
 * 
 * @since jdk1.6
 * @author 毛正吉
 * @version 1.0
 * @date 2010.07.10
 * 
 */

public class LoggerOperation implements IOperationExecutor {

	public void end(Method method) {
		Logger.log(Level.INFO, method.getName() + " method end...");
	}

	public void start(Method method) {
		Logger.log(Level.INFO, method.getName() + " method start...");
	}

}

7. 动态代理实现 - JDk提供的动态代理实现机制

package boke.javamode;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import boke.javamode.log.Level;
import boke.javamode.log.Logger;

/**
 * 动态代理
 * 
 * @since jdk1.6
 * @author 毛正吉
 * @version 1.0
 * @date  2010.07.10
 * 
 */
public class DynamicProxySay implements InvocationHandler {
	private Object proxyOperation; // 操作者对象
	private Object proxyLogic; // 业务逻辑对象

	/**
	 * 获得代理对象(业务逻辑)
	 * 
	 * @param proxyOperation
	 * @param proxyLogic
	 * @return
	 */
	public Object getProxyObj(Object proxyOperation, Object proxyLogic) {
		this.proxyOperation = proxyOperation;
		this.proxyLogic = proxyLogic;
		return Proxy.newProxyInstance(this.proxyLogic.getClass()
				.getClassLoader(), this.proxyLogic.getClass().getInterfaces(),
				this);
	}

	/**
	 * JVM动态调用
	 */
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object resultObj = null;

		try {
			Class operCls = this.proxyOperation.getClass();
			Method start = operCls.getMethod("start",
					new Class[] { Method.class });
			// 反射执行start方法
			start.invoke(proxyOperation, new Object[] { method });

			// 执行业务逻辑对象
			resultObj = method.invoke(proxyLogic, args);

			Method end = operCls.getMethod("end", new Class[] { Method.class });
			// 反射执行end方法
			end.invoke(proxyOperation, new Object[] { method });

		} catch (Exception e) {
			e.printStackTrace();
		}

		return resultObj;
	}

}

8. 客户端

package boke.javamode;

/**
 * 客户端
 * 
 * @since jdk1.6
 * @author 毛正吉
 * @version 1.0
 * @date 2010.07.10
 * 
 */
public class Client {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		IOperationExecutor operExe = new LoggerOperation();
		ISay say = new Say();
		ISay proxySay = (ISay) new DynamicProxySay().getProxyObj(operExe, say);
		proxySay.sayHello("Alice");
		System.out.println();
		proxySay.sayGoodBye("Bob");
	}

}

// 输出:
Logger INFO : 2010-07-10 18:27:35 sayHello method start...
Hello Alice
Logger INFO : 2010-07-10 18:27:35 sayHello method end...

Logger INFO : 2010-07-10 18:27:35 sayGoodBye method start...
GoodBye Bob
Logger INFO : 2010-07-10 18:27:35 sayGoodBye method end...

分享到:
评论
9 楼 select*from爱 2010-07-13  
8 楼 maozj 2010-07-13  
jackhorner 写道
javaeye 编辑的水平下降了啊 这都能骗到首页上去啊


????????????????
7 楼 jackhorner 2010-07-12  
javaeye 编辑的水平下降了啊 这都能骗到首页上去啊
6 楼 qiaoqinqie 2010-07-12  
稍微看了一下  呵呵
5 楼 mercyblitz 2010-07-12  
这个实现限制太大了,before和after动作不能利用参数/
4 楼 lcfred 2010-07-12  
受教了,很好
3 楼 甄子丹 2010-07-12  
教科书上都用log、cache、事务来做示例
2 楼 Frery 2010-07-12  
何以见得它解耦了?
1 楼 家有老屋 2010-07-12  
掌握java反射和动态代理,对开源框架实现原理的理解很有帮助

相关推荐

Global site tag (gtag.js) - Google Analytics