最近在公司看到了mybatis与spring整合中MapperScannerConfigurer的使用,该类通过反向代理自动生成基于接口的动态代理类。

于是想起了java的动态代理,然后就有了这篇文章。

本文使用动态代理模拟处理事务的拦截器。

接口:

public interface UserService {
public void addUser();
public void removeUser();
public void searchUser();
}

实现类:

public class UserServiceImpl implements UserService {
public void addUser() {
System.out.println("add user");
}
public void removeUser() {
System.out.println("remove user");
}
public void searchUser() {
System.out.println("search user");
}
}

java动态代理的实现有2种方式

1.jdk自带的动态代理

使用jdk自带的动态代理需要了解InvocationHandler接口和Proxy类,他们都是在java.lang.reflect包下。

InvocationHandler介绍:

InvocationHandler是代理实例的调用处理程序实现的接口。

每个代理实例都具有一个关联的InvocationHandler。对代理实例调用方法时,这个方法会调用InvocationHandler的invoke方法。

Proxy介绍:

Proxy 提供静态方法用于创建动态代理类和实例。

实例(模拟AOP处理事务):

public class TransactionInterceptor implements InvocationHandler {

    private Object target;

    public void setTarget(Object target) {
this.target = target;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("start Transaction");
method.invoke(target, args);
System.out.println("end Transaction");
return null;
} }

测试代码:

public class TestDynamicProxy {

    @Test
public void testJDK() {
TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
UserService userService = new UserServiceImpl();
transactionInterceptor.setTarget(userService);
UserService userServiceProxy =
(UserService) Proxy.newProxyInstance(
userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(),
transactionInterceptor);
userServiceProxy.addUser();
} }

测试结果:

start Transaction
add user
end Transaction

很明显,我们通过userServiceProxy这个代理类进行方法调用的时候,会在方法调用前后进行事务的开启和关闭。

2. 第三方库cglib

CGLIB是一个功能强大的,高性能、高质量的代码生成库,用于在运行期扩展Java类和实现Java接口。

它与JDK的动态代理的之间最大的区别就是:

JDK动态代理是针对接口的,而cglib是针对类来实现代理的,cglib的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

实例:

public class UserServiceCallBack implements MethodInterceptor {

    @Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("start Transaction by cglib");
methodProxy.invokeSuper(o, args);
System.out.println("end Transaction by cglib");
return null;
} }

测试代码:

public class TestDynamicProxy {

    @Test
public void testCGLIB() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserServiceImpl.class);
enhancer.setCallback(new UserServiceCallBack());
UserServiceImpl proxy = (UserServiceImpl)enhancer.create();
proxy.addUser();
} }

测试结果:

start Transaction by cglib
add user
end Transaction by cglib

结束语

简单讲解了JDK和cglib这2个动态代理,之后会再写篇文章讲讲MapperScannerConfigurer的原理实现。

java动态代理浅析的更多相关文章

  1. Java动态代理简单应用

    概念 代理模式是基本的设计模式之一,它是开发者为了提供额外的或不同的操作,而插入的用来代替“实际”对象的对象.这些操作通常涉及与“实际”对象的通信,因此代理通常充当着中间人的角色. Java动态代理比 ...

  2. Cglib动态代理浅析

    原文同步发表至个人博客[夜月归途] 原文链接:http://www.guitu18.com/se/java/2018-06-29/18.html 作者:夜月归途 出处:http://www.guitu ...

  3. JDK动态代理浅析

    原文同步发表至个人博客[夜月归途] 原文链接:http://www.guitu18.com/se/java/2018-06-29/17.html 作者:夜月归途 出处:http://www.guitu ...

  4. Java 动态代理机制详解

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

  5. Java动态代理全面分析

    代理模式 解说:给某一个对象提供一个代理,并由代理对象控制对原对象的引用: 代理模式需要以下几个角色: 1  主题:规定代理类和真实对象共同对外暴露的接口: 2  代理类:专门代理真实对象的类: 3 ...

  6. JAVA动态代理模式(从现实生活角度理解代码原理)

    所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联. java动态代理主要是使用java.lang.reflect包中的两个 ...

  7. Java 动态代理作用是什么?

    Java 动态代理作用是什么?   1 条评论 分享   默认排序按时间排序 19 个回答 133赞同反对,不会显示你的姓名 Intopass 程序员,近期沉迷于动漫ING 133 人赞同 ① 首先你 ...

  8. java动态代理原理

    我们经常会用到Java的动态代理技术, 虽然会使用, 但是自己对其中的原理却不是很了解.比如代理对象是如何产生的, InvocationHandler的invoke方法是如何调用的?今天就来深究下Ja ...

  9. java 动态代理示例,带主要注释

    Java proxy是基于反射,仅仅支持基于接口的动态代理. java 动态代理是一切架构的基础,必须了解. 废话少说,先上代码获得感性认识. 示例代码有主要注释. 接口: public interf ...

随机推荐

  1. 【转发】网易邮箱前端技术分享之javascript编码规范

    网易邮箱前端技术分享之javascript编码规范 发布日期:2013-11-26 10:06 来源:网易邮箱前端技术中心 作者:网易邮箱 点击:533 网易邮箱是国内最早使用ajax技术的邮箱.早在 ...

  2. Redis简介

    Redis是一个偏重于in-memory的key-value数据库,这样讲有点儿不准确,但是很容易将Redis简单分类.更准确的讲Redis是一个数据结构的存储服务.它的value不仅仅只有strin ...

  3. Linux Buffer I/O error on device dm-4, logical block

    Linux服务器日志(Oracle Linux Server release 5.7)里面出现了一些"Buffer I/O error on device dm-4, logical blo ...

  4. R语言Data Frame数据框常用操作

    Data Frame一般被翻译为数据框,感觉就像是R中的表,由行和列组成,与Matrix不同的是,每个列可以是不同的数据类型,而Matrix是必须相同的. Data Frame每一列有列名,每一行也可 ...

  5. HBase 高性能获取数据(多线程批量式解决办法) + MySQL和HBase性能测试比较

    摘要:   在前篇博客里已经讲述了通过一个自定义 HBase Filter来获取数据的办法,在末尾指出此办法的性能是不能满足应用要求的,很显然对于如此成熟的HBase来说,高性能获取数据应该不是问题. ...

  6. ubuntu14.04下的NVIDIA Tesla K80显卡驱动的安装教程

    搞深度学习如何能够不与浑身是“核”的显卡打交道呢? 人工智能的兴起除了数据量的大量提升,算法的不断改进,计算能力的逐步提高,还离不开软件基础设施的逐步完善.当下的主流的深度学习工具软件无论是Caffe ...

  7. js 读取 cookie

    (新摘未验证)// 将document.cookie的值以名/值对组成的一个对象返回 // 假设储存cookie的值的时候是采用encodeURIComponent()函数编码的 function g ...

  8. Android 解读.apk解压后文件详细说明

    转自:http://xdang.org/post-602.html 以下原文: 反编译 — 在apk文件中能得到什么 最近在做android客户端与服务器安全通信,有一种常见的不安全因素:很多软件常常 ...

  9. Altium Designer 出现错误提示(警告)adding items to hidden net GND/VCC

    一般出现这个提示,不是错误. 可以取消net 网格标号 这样就不会报这个警告了. 还可以设置规则,不让它报告. 点击确定,但是再次打开工程时有得警告这个错误了.我想,还是取消NET标注.

  10. high三个晚上这样好么-JSON&PHP

    hi 昨晚上吃火锅去了,对,你没猜错,我就是在成都 今晚有师兄请客,明天有基友请吃火锅,本来该忙忙哒的这一周要连续high三个晚上么(单身研究生狗就是这么容易满足).所以只好不务正业写写写了(写不动了 ...