java使用动态代理来实现AOP(日志记录)的实例代码
下面是一个aop实现的简单例子:
首先定义一些业务方法:
/**
* created with intellij idea.
* author: wangjie email:tiantian.china.2@gmail.com
* date: 13-9-23
* time: 下午3:49
*/
public interface bussinessservice {
public string login(string username, string password);
public string find();
}
public class bussinessserviceimpl implements bussinessservice {
private logger logger = logger.getlogger(this.getclass().getsimplename());
@override
public string login(string username, string password) {
return "login success";
}
@override
public string find() {
return "find success";
}
}
/**
* created with intellij idea.
* author: wangjie email:tiantian.china.2@gmail.com
* date: 13-9-24
* time: 上午10:27
*/
public interface workservice {
public string work();
public string sleep();
}
public class workserviceimpl implements workservice{
@override
public string work() {
return "work success";
}
@override
public string sleep() {
return "sleep success";
}
}
实现invocationhandler接口,使用map来存储不同的invocationhandler对象,避免生成过多。
package com.wangjie.aoptest2.invohandler;
import java.lang.reflect.invocationhandler;
import java.lang.reflect.method;
import java.lang.reflect.proxy;
import java.util.arrays;
import java.util.hashmap;
import java.util.logging.logger;
/**
* created with intellij idea.
* author: wangjie email:tiantian.china.2@gmail.com
* date: 13-9-23
* time: 下午3:47
*/
public class loginvohandler implements invocationhandler{
private logger logger = logger.getlogger(this.getclass().getsimplename());
private object target; // 代理目标
private object proxy; // 代理对象
private static hashmap<class<?>, loginvohandler> invohandlers = new hashmap<class<?>, loginvohandler>();
private loginvohandler() {
}
/**
* 通过class来生成动态代理对象proxy
* @param clazz
* @return
*/
public synchronized static<t> t getproxyinstance(class<t> clazz){
loginvohandler invohandler = invohandlers.get(clazz);
if(null == invohandler){
invohandler = new loginvohandler();
try {
t tar = clazz.newinstance();
invohandler.settarget(tar);
invohandler.setproxy(proxy.newproxyinstance(tar.getclass().getclassloader(),
tar.getclass().getinterfaces(), invohandler));
} catch (exception e) {
e.printstacktrace();
}
invohandlers.put(clazz, invohandler);
}
return (t)invohandler.getproxy();
}
@override
public object invoke(object proxy, method method, object[] args) throws throwable {
object result = method.invoke(target, args); // 执行业务处理
// 打印日志
logger.info("____invoke method: " + method.getname()
+ "; args: " + (null == args ? "null" : arrays.aslist(args).tostring())
+ "; return: " + result);
return result;
}
public object gettarget() {
return target;
}
public void settarget(object target) {
this.target = target;
}
public object getproxy() {
return proxy;
}
public void setproxy(object proxy) {
this.proxy = proxy;
}
}
然后编写一个test类测试:
/**
* created with intellij idea.
* author: wangjie email:tiantian.china.2@gmail.com
* date: 13-9-24
* time: 上午9:54
*/
public class test {
public static logger logger = logger.getlogger(test.class.getsimplename());
public static void main(string[] args) {
bussinessservice bs = loginvohandler.getproxyinstance(bussinessserviceimpl.class);
bs.login("zhangsan", "123456");
bs.find();
logger.info("--------------------------------------");
workservice ws = loginvohandler.getproxyinstance(workserviceimpl.class);
ws.work();
ws.sleep();
logger.info("--------------------------------------");
bussinessservice bss = loginvohandler.getproxyinstance(bussinessserviceimpl.class);
bss.login("lisi", "654321");
bss.find();
}
}
以后需要添加新的业务逻辑xxxservice,只需要调用
xxxservice xs = loginvohandler.getproxyinstance(xxxserviceimpl.class);
即可。
也可以模仿spring等框架的配置,把bean的类名配置在xml文件中,如:
<bean id="bussinessservice" class="com.wangjie.aoptest2.service.impl.bussinessserviceimpl">
然后在java代码中解析xml,通过class.forname("com.wangjie.aoptest2.service.impl.bussinessserviceimpl");获得class对象
然后通过loginvohandler.getproxyinstance(class.forname("com.wangjie.aoptest2.service.impl.bussinessserviceimpl"));获得代理对象proxy
再使用反射去调用代理对象的方法。
运行结果如下:
九月 24, 2013 11:08:03 上午 com.wangjie.aoptest2.invohandler.loginvohandler invoke
info: ____invoke method: login; args: [zhangsan, 123456]; return: login success
九月 24, 2013 11:08:03 上午 com.wangjie.aoptest2.invohandler.loginvohandler invoke
info: ____invoke method: find; args: null; return: find success
九月 24, 2013 11:08:03 上午 com.wangjie.aoptest2.test main
info: --------------------------------------
九月 24, 2013 11:08:03 上午 com.wangjie.aoptest2.invohandler.loginvohandler invoke
info: ____invoke method: work; args: null; return: work success
九月 24, 2013 11:08:03 上午 com.wangjie.aoptest2.invohandler.loginvohandler invoke
info: ____invoke method: sleep; args: null; return: sleep success
九月 24, 2013 11:08:03 上午 com.wangjie.aoptest2.test main
info: --------------------------------------
九月 24, 2013 11:08:03 上午 com.wangjie.aoptest2.invohandler.loginvohandler invoke
info: ____invoke method: login; args: [lisi, 654321]; return: login success
九月 24, 2013 11:08:03 上午 com.wangjie.aoptest2.invohandler.loginvohandler invoke
info: ____invoke method: find; args: null; return: find success