Java动态编程---动态代理
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动态编程---动态代理的更多相关文章
- java 动态代理 和动态编程
概述 代理分两种技术,一种是jdk代理(机制就是反射,只对接口操作),一种就是字节码操作技术.前者不能算技术,后者算是新的技术.未来将有大的动作或者较为广泛的应用和变革,它可以实现代码自我的编码(人工 ...
- 【java编程-Javassist】秒懂Java动态编程(Javassist研究)
作者:ShuSheng007 来源:CSDN 原文:https://blog.csdn.net/ShuSheng0007/article/details/81269295 版权声明:本文为博主原创文章 ...
- 【java高级编程】JDK和CGLIB动态代理区别
转载:https://blog.csdn.net/yhl_jxy/article/details/80635012 前言 JDK动态代理实现原理(jdk8):https://blog.csdn.net ...
- Java动态编程初探——Javassist
最近需要通过配置生成代码,减少重复编码和维护成本.用到了一些动态的特性,和大家分享下心得. 我们常用到的动态特性主要是反射,在运行时查找对象属性.方法,修改作用域,通过方法名称调用方法等.在线的应用不 ...
- 使用Java中的动态代理实现数据库连接池
2002 年 12 月 05 日 作者通过使用JAVA中的动态代理实现数据库连接池,使使用者可以以普通的jdbc连接的使用习惯来使用连接池. 数据库连接池在编写应用服务是经常需要用到的模块,太过频繁的 ...
- java 笔记(3) —— 动态代理,静态代理,cglib代理
0.代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口. 代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等. 代理类与委托类之间通常会存 ...
- 黑马程序员:Java基础总结----静态代理模式&动态代理
黑马程序员:Java基础总结 静态代理模式&动态代理 ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 静态代理模式 public class Ts { ...
- Java学习笔记--动态代理
动态代理 1.JDK动态代理 JDK1.3之后,Java提供了动态代理的技术,允许开发者在运行期创建接口的代理实例.JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy ...
- Java的三种代理模式(Spring动态代理对象)
Java的三种代理模式 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩 ...
随机推荐
- ArcGIS学习推荐基础教程摘录
###########-------------------摘录一--------------------------########### ***************************** ...
- 线性表A-B
1.顺序存储 #include<stdio.h> /* 设有两个顺序表A和B,且都递增有序,试写一算法,从A中删除与B中相同的那些元素,即求A-B */ #define getArrayL ...
- Guava缓存器源码分析——删除消息
Guava缓存器的删除消息机制 测试代码—— LoadingCache<String, Integer> cache = CacheBuilder.newBuild ...
- QT函数
1 move 移动 2 resize 改变窗口大小 3 setNum 设置数字 4 setText 设置文本 5 setWindowTitle 设置窗口文本 6 show 弹出窗口 7 text 获取 ...
- js正则验证两位小数 验证数字最简单正则表达式大全
<h3>输入完按回车后即可验证!(自认为最简单!)</h3> 正整数: <input type="text" size="20&quo ...
- SQLServer与Oracle的对照
近期去铁科院面试,项目组长问了我这样一下问题:SQLServer与Oracle的差别是什么?从进入软件行业.从開始CS的编码到BS的编码过程中使用的都是SQLServer.在半年前開始敲DRP ...
- 【Problem】Count and Say
问题分析 题目理解:给定一个整数,如果相邻的几个数位数字是相同的,则输出重复出现的次数加上该数字本身:继续向后查找直到所有的数位处理完. 按照上述思路,则: input output 1 11 11 ...
- SqlServer2008 数据库同步的两种方式(Sql JOB)
尊重原著作:本文转载自http://www.cnblogs.com/tyb1222/archive/2011/05/27/2060075.html 数据库同步是一种比较常用的功能.下面介绍的就是数据库 ...
- NOIP第二次模拟赛 stage1【划分数列(seq.pas/c/cpp)
7划分数列(seq.pas/c/cpp) [题目描述] 给你一个有n个元素的数列,要求把它划分成k段,使每段元素和的最大值最小 [输入格式] 第一行两个正整数n,k 第二行为此数列ai [输出格式] ...
- 解决eclipse创建Maven项目后无法生成src/main/java资源文件夹的方法
在项目上右键选择properties,然后点击java build path,在Librarys下,编辑JRE System Library,选择workspace default jre.