Java中的动态代理和AOP有什么关系?
本篇将带你了解Java中的动态代理使用方法,以及动态代理和AOP到底有什么关系
动态代理
Java 中的动态代理是一种设计模式,允许在运行时动态地创建代理对象,而不需要为每个代理类写一个单独的实现,动态代理主要用于拦截方法调用,在调用目标方法之前或之后添加通用的逻辑,比如日志记录、权限校验、事务管理等
也就是说,当我们想要扩展某一个方法时,但是又不想对原本的代码进行修改,这个时候就可以为这个方法创建一个代理对象,让代理对象在调用原本方法的基础上做一些横向扩展,即不用破坏原本代码的完整性,又可以在原有基础上做更多的事情
假如我们此时有一个业务:
public class ServiceImpl implements Service{
@Override
public String doService() throws InterruptedException {
System.out.println("正在执行业务...");
Thread.sleep(10);
return "OK";
}
}
为了演示执行业务的效果,我将线程休眠了10毫秒,方便后续观察
此时我们希望统计该业务的耗时情况,我们可以在业务开始和结束各记录一次时间,用结束时间减去开始时间就是业务耗时:
public class ServiceImpl implements Service{
@Override
public String doService() throws InterruptedException {
// 记录开始时间
long begin = System.currentTimeMillis();
// 执行业务
System.out.println("正在执行业务...");
Thread.sleep(10);
// 记录结束时间
long end = System.currentTimeMillis();
System.out.println("方法执行耗时:" + (end - begin) + "毫秒");
return "OK";
}
}
但是通常情况下,我们并不希望更改原本的代码
此时就可以使用动态代理技术,创建一个代理对象来帮我们扩展原有功能:
创建一个ProxyUtil
类,编写一个静态方法createProxy
用来获取代理对象,利用JDK提供的newProxyInstance
方法,传入一个InvocationHandler
接口的匿名内部类对象完成动态代理生成
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyUtil {
public static Service createProxy(ServiceImpl serviceImpl){
Service proxy = (Service) Proxy.newProxyInstance(
ProxyUtil.class.getClassLoader(), // 参数1:指定类加载器加载代理对象字节码文件
new Class[]{Service.class}, // 参数2:指定要代理的方法接口
new InvocationHandler() { // 参数3:指定代理对象要扩展的方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/*
参数1:要生成的代理对象
参数2:代理的方法
参数3:形参列表
*/
// 记录开始时间
long begin = System.currentTimeMillis();
// 执行原方法
Object result = method.invoke(serviceImpl);
// 记录结束时间
long end = System.currentTimeMillis();
System.out.println("方法执行耗时:" + (end - begin) + "毫秒");
return result;
}
});
return proxy;
}
}
最后我们创建一个测试类,来调用代理对象执行方法:
public class Test {
public static void main(String[] args) throws InterruptedException {
// 创建原对象
ServiceImpl service = new ServiceImpl();
// 创建代理对象
Service proxy = ProxyUtil.createProxy(service);
// 调用代理对象执行代理方法
System.out.println(proxy.doService());
}
}
AOP
聪明的你已经发现,这与我们在Spring
中学习的AOP
十分相似,没错,动态代理确实是AOP(面向切面编程)的核心实现方式之一,尤其是在 Java 的 Spring
框架中,动态代理被广泛用于实现 AOP 功能
对比项 | 动态代理 | AOP |
---|---|---|
定义 | 动态生成代理对象,在运行时增强目标方法。 | 一种编程思想,解耦横切关注点与业务逻辑。 |
范围 | 是技术实现手段。 | 是概念,包含动态代理和其他实现方式。 |
应用场景 | 拦截方法调用,加入通用逻辑。 | 实现日志、事务、权限、缓存等功能。 |
实现方式 | JDK动态代理、CGLIB、Javassist等。 | 通过动态代理、编译期或类加载期增强。 |
Spring支持 | 是Spring AOP的底层实现之一。 | Spring AOP提供切面声明和增强注入。 |