Java动态代理(JDK与CGLIB)详细解析
什么是动态代理
代理模式是一种非常常见的设计模式,其核心思想是为其他对象提供一个代理对象来控制对这个对象的访问。静态代理必须手动编写代理类,而动态代理则是在运行期动态生成代理类。
JDK动态代理
JDK动态代理是Java官方提供的动态代理实现方式,它是基于反射机制实现的。JDK动态代理需要实现InvocationHandler接口,具体步骤如下:
- 定义委托类和接口
假设有一个接口Shape,和一个具体实现类Circle,我们要实现一个动态代理代理这个实现类。
public interface Shape {
void draw();
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Circle is drawn.");
}
}
- 定义代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ShapeProxy implements InvocationHandler {
private Object target;
public ShapeProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
System.out.println("Before method " + method.getName() + " is invoked.");
result = method.invoke(target, args);
System.out.println("After method " + method.getName() + " is invoked.");
return result;
}
}
代理类实现InvocationHandler接口,并持有委托类对象。在invoke方法中,我们可以在委托类方法调用前后做一些额外处理。
- 调用
Shape circle1 = new Circle();
Shape circle2 = (Shape) Proxy.newProxyInstance(
circle1.getClass().getClassLoader(),
circle1.getClass().getInterfaces(),
new ShapeProxy(circle1));
circle2.draw();
在调用Proxy.newProxyInstance方法时,需要传入委托类的ClassLoader和interface。JVM将根据这些信息动态创建一个代理类的字节码,然后创建实例并返回。
CGLIB动态代理
JDK动态代理只能代理实现了接口的类,如果要代理没有实现接口的类,就需要使用CGLIB动态代理。CGLIB动态代理使用字节码生成技术在运行时动态生成代理类,不需要委托类实现接口。
使用CGLIB需要引入cglib的依赖:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
CGLIB代理步骤如下:
- 定义委托类
public class Rectangle {
public void draw() {
System.out.println("Rectangle is drawn.");
}
}
- 定义代理类
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class RectangleProxy implements MethodInterceptor {
private Rectangle target;
public RectangleProxy(Rectangle target) {
this.target = target;
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Object result = null;
System.out.println("Before method " + method.getName() + " is invoked.");
result = method.invoke(target, args);
System.out.println("After method " + method.getName() + " is invoked.");
return result;
}
public Object getProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Rectangle.class);
enhancer.setCallback(this);
return enhancer.create();
}
}
CGLIB代理类也需要实现一个接口,此处实现的是MethodInterceptor。在intercept方法中,可以对委托类的方法进行增强。
getProxy方法中使用Enhancer.create()方法创建代理类实例。
- 调用
Rectangle rectangle1 = new Rectangle();
Rectangle rectangle2 = (Rectangle) new RectangleProxy(rectangle1).getProxy();
rectangle2.draw();
以上就是JDK动态代理和CGLIB动态代理的详细说明,这两种动态代理技术都有各自的特点和使用场景,需要根据实际情况进行选择。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java动态代理(jdk与cglib)详细解析 - Python技术站