最近在公司看到了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. java中实现定时功能

    网上资料: 我们可以使用Timer和TimerTask类在java中实现定时任务,详细说明如下: 1.基础知识java.util.Timer一种线程设施,用于安排以后在后台线程中执行的任务.可安排任务 ...

  2. [20140722] forwarded和forwarding记录

    背景: 今天被人文集forwarded和forwarding记录的事情. 简单介绍: 当堆表跟新某一个列的时候发现,不够放了,那么就在那行记录上标记forwarding,并把数据放到另外一个page, ...

  3. spring定时器(一)

    使用的是spring的quartz功能,需导入com.springsource.org.quartz.jar包. 此定时器无法重置定时时间,需要的话可查看:spring定时器(二) spring的be ...

  4. 中科院分词ICTCLAS导入用户词典后分词结果一样?

    package ICTCLAS.I3S.Test; import java.io.UnsupportedEncodingException; import ICTCLAS.I3S.AC.ICTCLAS ...

  5. eclipse 启动报错\workspace\.metadata\.log

    eclipse启动报错,让查看.metadata\.log日志 eclipse启动不了,让查看.metadata\.log日志,上面为日志中的错误提示. 解决办法:删除 .metadata\.plug ...

  6. hadoop2.6---windows下开发环境搭建

    一.准备插件 1.自己编译 1.1 安装Ant 官网下载Ant,apache-ant-1.9.6-bin.zip 配置环境变量,新建ANT_HOME,值是E:\apache-ant-1.9.6:PAT ...

  7. UEFI安装Kali Linux 1.1.0记录

    现在使用Kali Linux 1.1.0, UEFI启动,使用Fcitx的拼音输入法,词库实在不爽,将就写一写. 本文地址: http://www.cnblogs.com/go2bed/p/42954 ...

  8. CURL使用方法详解

    php采集神器CURL使用方法详解 作者:佚名  更新时间:2016-10-21   对于做过数据采集的人来说,cURL一定不会陌生.虽然在PHP中有file_get_contents函数可以获取远程 ...

  9. 如何用ZBrush做人体造型雕刻

    之前我们用ZBrush®中的Curves和Insert笔刷快速创建模型的躯干.四肢以及手指.经过老师耐心的讲解我们也收获了很多,知道了创建模型的流程和雕刻技巧.今天的ZBrush教程将结合一些新的雕刻 ...

  10. 模版(template)

    模版(template) 在c++Template中很多地方都用到了typename与class这两个关键字,而且好像可以替换,是不是这两个关键字完全一样呢? 相信学习C++的人对class这个关键字 ...