一、JDK 动态代理
特点:
- 基于接口:JDK动态代理只能代理实现了接口的类,不能代理普通的类。被代理的类必须实现一个或多个接口。
- 使用反射机制:JDK动态代理通过java.lang.reflect.Proxy类和InvocationHandler接口来实现动态代理,主要利用了Java的反射机制。
- 性能:由于使用了反射机制,在运行时会有一定的性能开销,尤其是对于大量的代理调用。
实现步骤:
- 接口定义:首先定义一个接口,被代理类必须实现该接口。
- 创建InvocationHandler:实现InvocationHandler接口,重写invoke方法,在该方法中可以定义调用代理方法前后的逻辑。
- 创建代理对象:通过Proxy.newProxyInstance()方法创建代理对象。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface MyInterface {
void doSomething();
}
class RealObject implements MyInterface {
public void doSomething() {
System.out.println("Doing something in the real object.");
}
}
class MyInvocationHandler implements InvocationHandler {
private Object realObject;
public MyInvocationHandler(Object realObject) {
this.realObject = realObject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method call");
Object result = method.invoke(realObject, args);
System.out.println("After method call");
return result;
}
}
public class Main {
public static void main(String[] args) {
MyInterface realObject = new RealObject();
MyInterface proxyObject = (MyInterface) Proxy.newProxyInstance(
realObject.getClass().getClassLoader(),
realObject.getClass().getInterfaces(),
new MyInvocationHandler(realObject));
proxyObject.doSomething();
}
}
二、CGLIB 动态代理
特点:
- 基于继承:CGLIB动态代理是基于继承的方式,因此可以代理没有实现接口的普通类。
- 使用ASM字节码生成框架:CGLIB通过ASM框架在运行时生成被代理类的子类,并通过字节码增强技术来实现动态代理。
- 不能代理声明为 final 类型的类和方法。
实现步骤:
- 普通类定义:定义一个普通类,不需要实现接口。
- 创建MethodInterceptor:实现MethodInterceptor接口,重写intercept方法,在该方法中可以定义调用代理方法前后的逻辑。
- 创建代理对象:通过Enhancer类创建代理对象。
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
class RealObject {
public void doSomething() {
System.out.println("Doing something in the real object.");
}
}
class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before method call");
Object result = proxy.invokeSuper(obj, args);
System.out.println("After method call");
return result;
}
}
public class Main {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(RealObject.class);
enhancer.setCallback(new MyMethodInterceptor());
RealObject proxyObject = (RealObject) enhancer.create();
proxyObject.doSomething();
}
}