java中动态编程用到的技术有:反射(动态代理),javassist和ASM,这几种动态编程方法相比较,在性能上Javassist高于反射,但低于ASM,因为Javassist增加了一层抽象。在实现成本上Javassist和反射都很低,而ASM由于直接操作字节码,相比Javassist源码级别的api实现成本高很多。几个方法有自己的应用场景,比如Kryo使用的是ASM,追求性能的最大化。而NBeanCopyUtil采用的是Javassist,在对象拷贝的性能上也已经明显高于其他的库,并保持高易用性。实际项目中推荐先用Javassist实现原型,若在性能测试中发现Javassist成为了性能瓶颈,再考虑使用其他字节码操作方法做优化。

下面以代码的方式实现一个动态代理。

目标:

在调用持久层UserDAO将业务数据写入数据库的前后加入日志的功能。代码结构如下图所示:

User:

package dynamicproxy.model;

public class User {
public User(String name, int age) {
super();
this.name = name;
this.age = age;
}
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}

IUserDAO:

package dynamicproxy.dao;

import dynamicproxy.model.User;

public interface IUserDAO {

    String addUser(User user);

    String updateUser(User user);
}

UserDAO:

package dynamicproxy.dao;

import dynamicproxy.model.User;

public class UserDAO implements IUserDAO {
public String addUser(User user) {
System.out.println("开始向数据库中写入数据...");
return String.format("添加用户[%s]成功", user.getName());
} public String updateUser(User user) {
System.out.println("开始向数据库中写入数据...");
return String.format("修改用户[%s]成功", user.getName());
}
}

关键的InvocationHandler类LogInterceptor:

package dynamicproxy.interceptor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; public class LogInterceptor implements InvocationHandler {
private Object target; /*
* 在执行指定方法之前调用
*/
private void beforeMethod(Method method) {
System.out.println(String.format("日志:用户开始执行[%s]方法...", method.getName()));
} /*
* 在执行指定方法之后调用
*/
private void afterMethod(Method method) {
System.out.println(String.format("日志:用户执行[%s]方法完成.", method.getName()));
} public LogInterceptor(Object target) {
this.target = target;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
beforeMethod(method);// 加入日志处理逻辑
Object result = method.invoke(target, args);// 调用被代理对象的指定method方法
afterMethod(method);// 加入日志处理逻辑
return result;
} }

测试代码:

package dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import org.junit.Test;
import dynamicproxy.dao.IUserDAO;
import dynamicproxy.dao.UserDAO;
import dynamicproxy.interceptor.LogInterceptor;
import dynamicproxy.model.User; public class UserDAOTest { @Test
public void test() {
IUserDAO dao = new UserDAO();
InvocationHandler logInterceptor = new LogInterceptor(dao);// InvocationHandler
dao = (IUserDAO) Proxy.newProxyInstance(dao.getClass().getClassLoader(), dao.getClass().getInterfaces(),
logInterceptor);
System.out.println(dao.addUser(new User("franson", 21)));
System.out.println(System.lineSeparator());
System.out.println(dao.updateUser(new User("franson", 21)));
} }

运行JUnit测试结果如下:

日志:用户开始执行[addUser]方法...
开始向数据库中写入数据...
日志:用户执行[addUser]方法完成.
添加用户[franson]成功 日志:用户开始执行[updateUser]方法...
开始向数据库中写入数据...
日志:用户执行[updateUser]方法完成.
修改用户[franson]成功

这样就达到了我们在不修改原有业务逻辑代码的情况下实现添加日志的功能。

最新文章

  1. 谈谈redis主从复制的重点
  2. javascript图片切换
  3. iOS之UIAlertView的使用
  4. Linux常用命令收集
  5. TurnipBit:和孩子一起动手DIY“滚动”的生日礼物
  6. angular-dragon-drop.js 双向数据绑定拖拽的功能
  7. 在linux ubuntu下搭建深度学习/机器学习开发环境
  8. composer的安装以及具体使用
  9. P2P平台介绍
  10. 在linux上安装Scala详细步骤
  11. Hystrix系列-5-Hystrix的资源隔离策略
  12. 小学四则运算APP 第一个冲刺阶段 第六天
  13. WireGuard协议介绍
  14. NodeJs异步的执行过程
  15. docker探索-Win10 Docker 安装使用(一)
  16. Jenkins RestAPI调用出现Error 403 No valid crumb was included in the request
  17. Java字节码指令
  18. Delphi MessageBox
  19. python 和 C# DES加密
  20. Luogu P1377 [TJOI2011]树的序:离线nlogn建二叉搜索树

热门文章

  1. 量身定制顺美男女西服、衬衫、大衣、T恤等 - 北京58同城
  2. Android Notivation的使用
  3. 黑马程序员_高新技术之javaBean,注解,类加载器
  4. oj 小黑华丽的逆袭机会
  5. UITabBarController 笔记(一)AppDelegate中加UITabBarController 为 rootViewController
  6. setter设置器 gutter访问器
  7. .net通用权限框架B/S (四)--DAL数据层以及数据接口
  8. 深入理解CSS3 Animation 帧动画(转)
  9. C#中的线程(一)入门 转
  10. FAQ:win7和win8 64位注册ocx控件方法