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. linux下安装配置svn独立服务器

    subversion(以下简称svn)是近年来崛起的版本管理工具,是cvs的接班人. svn服务器有2种运行方式:独立服务器和借助apache.2种方式各有利弊. file:/// 直接版本库访问(本 ...

  2. 全国计算机等级考试二级教程-C语言程序设计_第16章_文件

    写入一段文本到文件 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> main() { ...

  3. svo:一个半直接单目视觉里程计(长期更新)

    源码:https://github.com/uzh-rpg/rpg_svo/tree/master/svo 视频:https://www.youtube.com/watch?v=2YnIMfw6bJY ...

  4. iSlider手机平台JS滑动组件

    iSlider手机平台JS滑动组件,无任何插件依赖.它能够处理任何元素,例如图片或者DOM元素.它有如下特性:能够自定义动画,自带的动画包括default, rotate, flip 和 depth你 ...

  5. chartControl 饼状图小Demo

    Short Description     The Pie Chart is represented by the Pie3DSeriesView object, which belongs to P ...

  6. android入门——BroadCast(2)

    自定义广播 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android=&q ...

  7. jboss清楚缓存

    在服务器上部署或更新时,常常会忘记删除JBOSS的缓存.忘记删除缓存的后果,经常就是改好了代码却还是原来的错误,然后查找半天,浪费时间.所以在重新部署JBOSS,在启动JBOSS前一定要删除JBOSS ...

  8. c++中的const参数,const变量,const指针,const对象,以及const成员函数

    const 是constant 的缩写,“恒定不变”的意思.被const 修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性.所以很多C++程序设计书籍建议:“Use const whe ...

  9. CSS3 Gradient-CSS3渐变

    CSS3 Gradient分为linear-gradient(线性渐变)和radial-gradient(径向渐变).而我们今天主要是针对线性渐变来剖析其具体的用法.为了更好的应用CSS3 Gradi ...

  10. Flink资料(6) -- 如何添加一个新的Operator

    false false false false EN-US ZH-CN X-NONE /* Style Definitions */ table.MsoNormalTable {mso-style-n ...