
这里推荐一篇实用的文章:《Java 读取寄存器数据的实现与应用》,作者:【喵手】。
这篇文章作者主要讲述了寄存器是 CPU 中的高速存储单元,负责临时存储处理器正在使用的数据。展示如何在 Java 中读取寄存器数据,以及在不同应用场景下的使用和优缺点分析...借此好文分享给同学们。
面向切面编程(AOP,Aspect-Oriented Programming)是一种编程范式,它通过将横切关注点(cross-cutting concerns)与业务逻辑分离,以提高代码的可维护性和可重用性。在Java开发中,AOP的实现离不开动态代理技术,其中JDK动态代理和CGLIB动态代理是两种常用的方式。本文将从背景、历史、功能点、业务场景、底层逻辑等多个维度,深度解析这两种代理方式的区别,并通过Java示例进行模拟和比较。
AOP的概念最早由Gregor Kiczales等人在1997年提出,旨在解决面向对象编程(OOP)中横切关注点(如日志记录、事务管理、安全控制等)与业务逻辑混合导致代码臃肿、难以维护的问题。AOP通过定义一个或多个切面(Aspect),将横切关注点从业务逻辑中分离出来,形成独立的模块,并通过动态代理技术在运行时将这些切面织入(Weaving)到目标对象中。
在Java中,动态代理技术是实现AOP的关键。Java的动态代理机制最早出现在JDK 1.3中,当时只支持基于接口的代理。随着Java的发展,动态代理技术也得到了不断的完善和优化。JDK 5引入了基于InvocationHandler和Proxy类的动态代理机制,使得开发者可以在运行时动态地创建代理对象,而无需手动编写代理类代码。而CGLIB(Code Generation Library)则提供了一种更为灵活的代理方式,它通过生成目标类的子类来实现代理,从而支持了对未实现接口的类的代理。
JDK动态代理是Java语言提供的一种基于接口的代理机制。它要求被代理的类必须实现至少一个接口,代理对象将实现这些接口,并将方法调用委托给目标对象。JDK动态代理主要通过java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口实现。
InvocationHandlerProxyCGLIB动态代理是一种基于类的代理机制,它通过生成目标类的子类来实现代理。与JDK动态代理不同,CGLIB不要求目标类必须实现接口,因此它适用于那些没有实现接口的类。CGLIB动态代理使用的是ASM字节码生成框架,通过修改目标类的字节码来生成代理类。
MethodInterceptorEnhancerfinal类或final方法(因为CGLIB通过继承方式创建代理类)。JDK动态代理的底层逻辑主要依赖于反射机制和InvocationHandler接口。当调用代理对象的方法时,代理类会拦截该方法调用,并通过InvocationHandler.invoke()方法执行额外的逻辑。具体步骤如下:
Proxy.newProxyInstance()方法创建代理对象。该方法需要三个参数:类加载器、目标类实现的接口列表和一个实现了InvocationHandler接口的处理器对象。InvocationHandler的invoke()方法。invoke()方法中,可以执行额外的逻辑(如日志记录、权限检查等),然后通过反射调用目标对象的方法来完成实际的业务逻辑。CGLIB动态代理的底层逻辑主要依赖于字节码生成技术和ASM框架。CGLIB通过生成目标类的子类来实现代理,并在子类中重写目标类的方法以插入额外的逻辑。具体步骤如下:
Enhancer对象:Enhancer是CGLIB中用于创建代理类的主要类。通过调用其setSuperclass()方法设置目标类的超类。Enhancer的setCallback()方法设置一个实现了MethodInterceptor接口的回调对象。该回调对象将负责拦截方法调用并执行额外的逻辑。Enhancer的create()方法生成代理类的实例。在生成代理类的过程中,CGLIB会使用ASM框架修改目标类的字节码以插入代理逻辑。intercept()方法中。在intercept()方法中,可以执行额外的逻辑(如日志记录、权限检查等),然后通过调用MethodProxy.invokeSuper()方法执行目标类的原始方法。下面是一个使用JDK动态代理的示例代码:
java复制代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 定义一个接口
interface MyService {
void serve();
}
// 实现该接口的目标类
class MyServiceImpl implements MyService {
public void serve() {
System.out.println("Serving...");
}
}
// 实现InvocationHandler接口的处理器类
class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method: " + method.getName());
Object result = method.invoke(target, args);
System.out.println("After method: " + method.getName());
return result;
}
}
// 测试类
public class JdkProxyDemo {
public static void main(String[] args) {
MyServiceImpl service = new MyServiceImpl();
MyService proxy = (MyService) Proxy.newProxyInstance(
service.getClass().getClassLoader(),
service.getClass().getInterfaces(),
new MyInvocationHandler(service)
);
proxy.serve();
}
}在这个示例中,MyService是一个接口,MyServiceImpl实现了这个接口。MyInvocationHandler实现了InvocationHandler接口,并在invoke()方法中添加了额外的逻辑(打印方法调用前后的信息)。通过Proxy.newProxyInstance()方法创建了MyService接口的代理对象proxy,并调用了其serve()方法。输出结果为:
复制代码
Before method: serve
Serving...
After method: serve下面是一个使用CGLIB动态代理的示例代码:
java复制代码
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
// 目标类,没有实现任何接口
class MyService {
public void serve() {
System.out.println("Serving...");
}
}
// 实现MethodInterceptor接口的处理器类
class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before method: " + method.getName());
Object result = proxy.invokeSuper(obj, args);
System.out.println("After method: " + method.getName());
return result;
}
}
// 测试类
public class CglibProxyDemo {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MyService.class);
enhancer.setCallback(new MyMethodInterceptor());
MyService proxy = (MyService) enhancer.create();
proxy.serve();
}
}在这个示例中,MyService类没有实现任何接口。MyMethodInterceptor实现了MethodInterceptor接口,并在intercept()方法中添加了额外的逻辑(打印方法调用前后的信息)。通过Enhancer类创建了MyService类的代理对象proxy,并调用了其serve()方法。输出结果为:
复制代码
Before method: serve
Serving...
After method: serveJDK动态代理 | CGLIB动态代理 | |
|---|---|---|
基于 | 接口 | 类 |
实现机制 | 反射机制 + InvocationHandler接口 | 字节码生成技术 + ASM框架 |
代理对象创建开销 | 较小 | 较大 |
方法调用性能 | 略慢(涉及反射调用) | 较高(通过字节码操作减少反射调用开销) |
适用场景 | 接口驱动的编程模式,频繁创建和销毁代理对象的场景 | 代理未实现接口的类,性能要求较高的场景 |
限制 | 只能代理实现了接口的类 | 不能代理final类或final方法 |
通过本文的深度解析和实战模拟,相信读者已经对JDK动态代理和CGLIB动态代理有了更深入的理解。在实际开发中,可以根据具体的业务场景和性能需求选择合适的代理方式来实现AOP。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。