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]成功

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

Java动态编程---动态代理的更多相关文章

  1. java 动态代理 和动态编程

    概述 代理分两种技术,一种是jdk代理(机制就是反射,只对接口操作),一种就是字节码操作技术.前者不能算技术,后者算是新的技术.未来将有大的动作或者较为广泛的应用和变革,它可以实现代码自我的编码(人工 ...

  2. 【java编程-Javassist】秒懂Java动态编程(Javassist研究)

    作者:ShuSheng007 来源:CSDN 原文:https://blog.csdn.net/ShuSheng0007/article/details/81269295 版权声明:本文为博主原创文章 ...

  3. 【java高级编程】JDK和CGLIB动态代理区别

    转载:https://blog.csdn.net/yhl_jxy/article/details/80635012 前言 JDK动态代理实现原理(jdk8):https://blog.csdn.net ...

  4. Java动态编程初探——Javassist

    最近需要通过配置生成代码,减少重复编码和维护成本.用到了一些动态的特性,和大家分享下心得. 我们常用到的动态特性主要是反射,在运行时查找对象属性.方法,修改作用域,通过方法名称调用方法等.在线的应用不 ...

  5. 使用Java中的动态代理实现数据库连接池

    2002 年 12 月 05 日 作者通过使用JAVA中的动态代理实现数据库连接池,使使用者可以以普通的jdbc连接的使用习惯来使用连接池. 数据库连接池在编写应用服务是经常需要用到的模块,太过频繁的 ...

  6. java 笔记(3) —— 动态代理,静态代理,cglib代理

    0.代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口. 代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等. 代理类与委托类之间通常会存 ...

  7. 黑马程序员:Java基础总结----静态代理模式&动态代理

    黑马程序员:Java基础总结 静态代理模式&动态代理   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 静态代理模式 public  class  Ts {   ...

  8. Java学习笔记--动态代理

    动态代理 1.JDK动态代理 JDK1.3之后,Java提供了动态代理的技术,允许开发者在运行期创建接口的代理实例.JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy ...

  9. Java的三种代理模式(Spring动态代理对象)

    Java的三种代理模式 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩 ...

随机推荐

  1. 迎接 Windows Azure 和 DNN 挑战,几分钟内快速构建网站!

    编辑人员注释:本文章由高级商务策划师兼开发平台推广者 Neeti Gupta 撰写. 曾几何时,构建一个简单的网站需要耗费好几个月的时间.在过去,.NET 开发人员和设计社区的一些成员使用 DNN(以 ...

  2. Item with the same id "98" already exist

    在magento项目中多次遇到这样一个错误: Item (Bluecom_Onefieldusername_Model_Customer) with the same id "98" ...

  3. 简单实现仿UITabBarController界面

    第一步:添加两个占位View 第二步:添加子控制器 第三步:添加按钮 #import "ViewController.h" #define SCREEN_WIDTH ([UIScr ...

  4. BZOJ 1087 互不侵犯king

    Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行,包 ...

  5. NOIP2012模拟试题 121105【奶牛排队(tahort)

    3.奶牛排队(tahort) [ 问题描述] 奶牛在熊大妈的带领下排成了一条直队. 显然,不同的奶牛身高不一定相同…… 现在,奶牛们想知道,如果找出一些连续的奶牛,要求最左边的奶牛A是最矮的,最右边的 ...

  6. VARIANT类型

    VARIANT的结构可以参考头文件VC98\Include\OAIDL.H中关于结构体tagVARIANT的定义.struct  tagVARIANT    {    union         {  ...

  7. Ubuntu下使用Vi时方向键变乱码 退格键不能使用的解决方法

    要在Ubuntu下编辑一些文件,这就涉及到了vi这个编辑器了.在Ubuntu下,初始使用vi的时候有点问题,就是在编辑模式下使用方向键的时候,并不会使光标移动,而是在命令行中出现[A [B [C [D ...

  8. C++虚函数在内存中的实现

    首先来一张图,一目了然: 然后把相应的代码贴上来: class A { int a; public: virtual void f(); virtual void g(int); virtual vo ...

  9. Linux 学习之网络故障排查

    1.ping www.baidu.com 查看高速有没有修通,如果通,但还不能上网:可能是浏览器.中毒等问题2.ping 网关(10.0.0.254),目的是排除物理链路(网线,网卡,驱动,IP设置等 ...

  10. css负边距自适应布局

    单列定宽单列自适应布局: <!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> ...