JDK
package designpattern.proxy.v3;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* jdk反射生成代理必须面向接口,这是由Proxy的内部实现决定的
*/
public class DynamicMain {
public static void main(String[] args) {
Tank tank = new Tank();
Movable m = (Movable) Proxy.newProxyInstance(
Tank.class.getClassLoader(),//一般是被代理类的类加载器
new Class[]{Movable.class}, //通过接口知道哪些方法需要代理
new TimeProxy(tank));//具体的代理
m.move();
}
}
interface Movable {
void move();
}
class Tank implements Movable {
@Override
public void move() {
System.out.println("Tank moving...");
}
}
class TimeProxy implements InvocationHandler {
Movable m;
public TimeProxy(Movable m) {
this.m = m;
}
public void before() {
System.out.println("method start..");
}
public void after() {
System.out.println("method stop..");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object o = method.invoke(m, args);
after();
return o;
}
}
CGLIB
需要引入依赖
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
package designpattern.proxy.cglib;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* CGLIB实现动态代理不需要接口
* Code Generation Library
*
* @Auther: IceBear
* @Date: 2022/2/14 21:46
* @Description:
*/
public class CglibMain {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Tank.class);
enhancer.setCallback(new TimeMethodInterceptor());
Tank tank = (Tank) enhancer.create();
tank.move();
}
}
class Tank {
public void move() {
System.out.println("tank moving...");
}
}
class TimeMethodInterceptor implements MethodInterceptor {
public void before() {
System.out.println("before");
}
public void after() {
System.out.println("after");
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
Object result = null;
result = methodProxy.invokeSuper(o, objects);
after();
return result;
}
}
JDK 动态代理和 CGLIB 动态代理对比
JDK 动态代理只能代理实现了接口的类或者直接代理接口,而 CGLIB 可以代理未实现任何接口的类。 另外, CGLIB 动态代理是通过生成一个被代理类的子类来拦截被代理类的方法调用,因此不能代理声明为 final 类型的类和方法。