网站首页 > java教程 正文
在Java编程中,代理模式是一种非常重要的设计模式。代理模式可以分为静态代理和动态代理。今天我们主要来聊聊动态代理。动态代理在很多框架中都有广泛的应用,比如Spring AOP、MyBatis等。本文将详细介绍Java动态代理的原理、使用场景,并通过代码示例帮助大家更好地理解。
什么是动态代理?
动态代理是指在程序运行时创建代理类,而不是在编译时确定代理类。动态代理可以在不修改目标对象的情况下,为目标对象添加额外的功能。
动态代理的实现方式
Java中主要有两种方式实现动态代理:
1. JDK动态代理
2. CGLIB动态代理
JDK动态代理
JDK动态代理是基于接口的代理。它要求目标对象必须实现一个或多个接口。
实现步骤
1. 定义接口和实现类
2. 创建InvocationHandler接口的实现类
3. 使用Proxy类生成代理对象
代码示例
package com.dhzx.code.jdkDynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 1、定义接口
*/
interface HelloService {
void sayHello();
}
/**
* 2、实现接口
*/
class HelloServiceImpl implements HelloService {
@Override
public void sayHello() {
System.out.println("Hello World!");
}
}
/**
* 3、创建 InvocationHandler实现类
*/
class HelloServiceInvocationHandler implements InvocationHandler {
private Object targert;
public HelloServiceInvocationHandler(Object targert) {
this.targert = targert;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("方法调用前");
Object obj = method.invoke(targert, args);
System.out.println("方法调用后");
return obj;
}
}
/**
* JDK 动态代理示例
*/
class JDKDynamicProxyDemo {
public static void main(String[] args) {
// 4、创建目标方法
HelloService helloService = new HelloServiceImpl();
// 5、创建代理对象
HelloService proxy = (HelloService) Proxy.newProxyInstance(helloService.getClass().getClassLoader(), helloService.getClass().getInterfaces(), new HelloServiceInvocationHandler(helloService));
// 6、调用代理对象的方法
proxy.sayHello();
}
}
输出结果:
方法调用前
Hello World!
方法调用后
在上面的示例中,我们定义了一个HelloService接口及其实现类HelloServiceImpl。然后,我们创建了一个HelloServiceInvocationHandler类,实现了InvocationHandler接口。在invoke方法中,我们可以在方法调用前后添加自定义逻辑。最后,我们使用Proxy.newProxyInstance方法创建了代理对象,并调用了代理对象的方法。
CGLIB动态代理
CGLIB动态代理是基于继承的代理,它不需要目标对象实现接口。CGLIB通过生成目标类的子类来实现代理。
实现步骤
1. 引入CGLIB库
2. 创建MethodInterceptor接口的实现类
3. 使用Enhancer类生成代理对象
代码示例
<!-- 引入CGLIB库 -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
package com.dhzx.code.cglibDynamicProxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* 1、创建目标类
*/
class HelloService {
void sayHello() {
System.out.println("Hello World!");
}
}
/**
* 2、创建 MethodInterceptor 实现类
*/
class HelloServiceInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("方法调用前");
Object obj = methodProxy.invokeSuper(o, objects);
System.out.println("方法调用后");
return obj;
}
}
class CGLIBDynamicProxyDemo {
public static void main(String[] args) {
// 3、创建Enhancer对象(字节码增强器)
Enhancer enhancer = new Enhancer();
// 4、告诉cglib要继承哪个类
enhancer.setSuperclass(HelloService.class);
// 5、设置回调接口
enhancer.setCallback(new HelloServiceInterceptor());
// 6、创建代理对象(生成源码,编译class,加载到JVM)
HelloService helloService = (HelloService) enhancer.create();
helloService.sayHello();
}
}
输出结果:
方法调用前
Hello World!
方法调用后
在上面的示例中,我们创建了一个目标类HelloService,然后创建了一个HelloServiceInterceptor类,实现了MethodInterceptor接口。在intercept方法中,我们可以在方法调用前后添加自定义逻辑。最后,我们使用Enhancer类生成了代理对象,并调用了代理对象的方法。
动态代理的应用场景
动态代理在实际开发中有很多应用场景,比如:
1. AOP(面向切面编程):动态代理是AOP的核心技术之一。通过动态代理,可以在不修改目标对象的情况下,为目标对象添加额外的功能,比如日志记录、权限校验、事务管理等。
2. 远程方法调用(RMI):动态代理可以用于实现远程方法调用,使得客户端可以像调用本地方法一样调用远程方法。
3. Mock测试:在单元测试中,动态代理可以用于创建Mock对象,模拟依赖对象的行为。
总结
Java动态代理是一种非常强大的技术,可以在不修改目标对象的情况下,为目标对象添加额外的功能。本文详细介绍了JDK动态代理和CGLIB动态代理的实现方式,并通过代码示例帮助大家更好地理解动态代理的原理和应用场景。希望这篇文章能对你有所帮助!
猜你喜欢
- 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)
本文暂时没有评论,来添加一个吧(●'◡'●)