网站首页 > java教程 正文
一、什么是动态代理
打个比方,如果系统中有2个类,A和B,以前是A依赖B,即A直接调用B的某个方法,表示为A->B;
现在调用链路变成A->B->C,即A先调用B,B再调用C,不过B在调用C前后会加些逻辑,这时候B相当于一个代理人的角色,并且B的拦截是在程序运行过程中动态产生的,这种情况我们叫动态代理。
二、为什么需要动态代理
动态代理主要有以下几个作用:
1、提高系统的扩展性
像上面的情况,以前的调用链是A->B,现在要在B的基础上加些逻辑,如B是一个订单服务,这个B是的代码我们拿不到,只有Jar包,我们想在保存订单后发个邮件,当然我们可以在调用方去做,不过每个调用方都做这个事情,相同的逻辑就会分散在不同的地方,不便于后续的维护,这个时候就可以通过动态代理来增强系统的功能,并且不用修改B的代码。
2、精简代码,将逻辑收拢
这个什么意思呢,通过动态代理我们可以让使用者非常简单的使用,不用关注一些实现的细节,如Mybatis中只要写个接口,然后在Xml中写Sql语句,不用写如何读取Sql,怎么与JDBC打交道的代码,就可以轻松的访问数据库了。
其它还有Fein,也只要定义接口就可以了,如何执行Url请求,怎么解析响应的代码都不用我们写,让访问Rest服务变得非常简单。
三、Java中动态代理使用
主要有2种方式:
1、JDK代理
其代理对象必须实现接口InvocationHandler,它的实现方式是在运行期间创建一个接口的实现类来完成目标对象的代理。
使用步骤如下:
1)、实现InvocationHandler接口;
2)、调用Proxy.newProxyInstance生成代理对象
先实现接口InvocationHandler
public class JDKProxy implements InvocationHandler{
Object target; //被代理的对象
public JDKProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDKProxy before");
Object result = method.invoke(target, args);
System.out.println("JDKProxy after");
return result;
}
}
编写测试代码:
public void testJDKProxy(){
UserServiceImpl userServiceImpl = new UserServiceImpl();
ClassLoader classLoader = userServiceImpl.getClass().getClassLoader();
Class[] interfaces = userServiceImpl.getClass().getInterfaces();
InvocationHandler logHandler = new JDKProxy(userServiceImpl);
UserService proxy = (UserService) Proxy.newProxyInstance(classLoader, interfaces, logHandler);
proxy.select();
}
UserServiceImpl代码如下:
public class UserServiceImpl implements UserService {
public void select() {
System.out.println("select被调用");
}
UserSerivice接口定义如下:
public interface UserService {
void select();
}
2、CGLIB代理
它的实现是通过ASM(开源的Java字节码编辑类库)操作字节码,性能比JDK代理的强。
使用步骤如下:
1)、实现接口MethodInterceptor
2)、生成Enhancer类实例,调用setCallback方法绑定代理对象
先实现接口MethodInterceptor
public class CglibProxy implements MethodInterceptor{
@Override
public Object intercept(Object object, Method method, Object[] objects, net.sf.cglib.proxy.MethodProxy methodProxy){
Object result=null;
System.out.println("CglibProxy before");
try {
result = methodProxy.invokeSuper(object, objects);
}catch (java.lang.Throwable ex){
System.out.println(ex.getMessage());
}
System.out.println("CglibProxy after");
return result;
}
}
编写测试代码
public void testCglibProxy(){
CglibProxy proxy = new CglibProxy();
Enhancer enhancer = new Enhancer();
//设置超类,注意是接口不是实现类
enhancer.setSuperclass(UserService.class);
//绑定代理对象
enhancer.setCallback(proxy);
UserService dao = (UserService)enhancer.create();
dao.update();
dao.select();
}
猜你喜欢
- 2024-10-04 java:jdk动态代理(jdk动态代理实现aop)
- 2024-10-04 Java中代理的理解及其实现方式(1)- 静态代理
- 2024-10-04 Java三种代理模式:静态代理、动态代理和cglib代理
- 2024-10-04 Java 学习笔记--反射与代理机制(静态、动态)
- 2024-10-04 Java的动态代理如何实现?#程序员(java动态代理有什么用)
- 2024-10-04 Java动态代理与静态代理以及它能为我们做什么
- 2024-10-04 Java - 动态代理实现原理以及ASM技术
- 2024-10-04 深入理解Java反射和动态代理(jdk动态代理和反射)
- 2024-10-04 java手把手教你写动态代理和静态代理的实现
- 2024-10-04 Java动态代理简单介绍(java动态代理的两种方式)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)