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. android NDK jni下的c文件 Unresolved inclusion

    原因是在eclipse编辑环境中没有找到对应的include中的文件.解决方法是将包含该文件的include目录作为新的linked folder加入工程中.具体方法如下:1. 右击工程->Ne ...

  2. poj3673---双重for循环

    #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 15 int main ...

  3. 适合入门自学服装裁剪滴书(更新ing)

    [♣]适合入门自学服装裁剪滴书(更新ing) [♣]适合入门自学服装裁剪滴书(更新ing) 适合入门自学服装裁剪滴书(更新ing) 来自: 裁缝阿普(不为良匠,便为良医.) 2014-04-06 23 ...

  4. javascript第七课js函数

    function add() { } 上面就是js中的方法,js中的方法与c#中的方法不同的是不需要写返回值类型 function  add(num1,num2) { return num1+num2 ...

  5. ios模拟器安装.app

    相对于xcode的run,然后再在安装到模拟器上测试,如果是个人开发的话,那还好. 要是是团队开发,那每次其他的童鞋就都需要update最新的文件下来再编译运行了. 而且,一些测试的童鞋也不会打开xc ...

  6. UITabBarController 笔记(一)AppDelegate中加UITabBarController 为 rootViewController

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launc ...

  7. JavaScript 工作必知(九)function 说起 闭包问题

    大纲 Function Caller 返回函数调用者 Callee 调用自身 作用域 闭包 function 函数格式 function getPrototyNames(o,/*optional*/ ...

  8. linux下的进程、网络、性能监控命令

    进程监控 端口   1)netstat -anp | grep xxx   2)lsof  -i:<port> 句柄    lsof  -n | grep xxxx 线程栈   1)gst ...

  9. .net通用权限框架B/S (五)--WEB(3)组织机构

    .net通用权限框架B/S 首先我们看导航菜单中,对组织机构的设置 我们设置了组织机构名称,链接(对应的mvc控制器名/orga),图标是个小钥匙,菜单的操作权限设置的是"添加,编辑,删除& ...

  10. AngularJs 常用函数

    /** * [intersect 取两个数组的交集] var firstArray = [1,3,5]; var secondArray = [2,5,8]; var result */ .filte ...