最近在公司看到了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的原理实现。

最新文章

  1. 用pyspider爬淘宝MM照片
  2. 李洪强iOS经典面试题155 - const,static,extern详解(面试必备)
  3. ios 开发之单例模式
  4. redis系列-redis的持久化
  5. 可视化(番外篇)——在Eclipse RCP中玩转OpenGL
  6. Android打Path的方法
  7. CSS3弹性盒模型之box-orient & box-direction
  8. 250. Count Univalue Subtrees
  9. 在word 2013中输入latex公式
  10. django 分页组件
  11. PL/SQL 查询的数据出现乱码
  12. SQLite基本操作-----IOS(如有雷同,纯属巧合)
  13. Javascript概念
  14. LightOj 1104 - Birthday Paradox(生日悖论概率)
  15. windows,phalcon工具的安装使用
  16. 【LOJ】#2127. 「HAOI2015」按位或
  17. java虚拟机类加载
  18. 【洛谷 P2764】 最小路径覆盖问题(最大流)
  19. 【lua】可变长参数
  20. OpenStack概念

热门文章

  1. 17、文案人员 - IT软件人员书籍系列文章
  2. jsoup解析HTML及简单实例
  3. [CMD]oracle数据库的导出导入
  4. android项目中配置NDK自动编译生成so文件
  5. CMPP错误码说明
  6. 数据库 SQL Server 到 MySQL 迁移方法总结
  7. mvn archetype:create报错解决办法
  8. su,exit,adduser,deluser,usermod,groups
  9. 关于JavaScript继承的那些事
  10. PhpSms 稳定可靠的php短信发送库