JDK动态代理和Cglib动态代理都是Java中常用的动态代理实现方式,它们各有特点和应用场景:
-
JDK动态代理:JDK动态代理是基于接口的代理方式。它使用
java.lang.reflect.Proxy
类和java.lang.reflect.InvocationHandler
接口来创建代理对象。在这种方式下,代理类在运行时动态创建,并且必须实现一个或多个接口。使用JDK动态代理时,你需要提供一个实现了InvocationHandler
接口的类,这个类的invoke
方法将定义代理逻辑。实现步骤大致如下:
- 定义一个接口和该接口的实现类;
- 创建一个实现了
InvocationHandler
接口的处理器类; - 使用
Proxy.newProxyInstance
方法动态创建代理对象。
-
Cglib动态代理:与JDK动态代理不同,Cglib代理不需要接口,它是通过继承方式实现的。Cglib包含了一组底层字节码操作工具,能动态生成新的类。它通过继承目标类并重写其中的方法来实现代理。由于是通过继承实现,因此它不能代理声明为final的类和方法。
实现步骤大致如下:
- 创建一个实现了
MethodInterceptor
接口的类; - 使用Cglib的
Enhancer
类来创建代理对象,指定父类和回调。
- 创建一个实现了
在选择使用哪种代理方式时,如果所有目标对象都实现了接口,可以使用JDK动态代理;如果目标对象没有实现接口,或者你需要代理类的所有方法,那么可以考虑使用Cglib代理。
JDK动态代理
如何创建代理对象:使用Proxy类中的newProxyInstance方法
创建代理对象的要求:被代理类至少实现一个接口
newProxyInstance方法的参数
ClassLoader:类加载器,同于加载被代理对象字节码
Class[]:字节码数组---用于让代理对象和被代理对象拥有相同的方法
InvocationHandler:用于提供被增强的代码
/**接口类*/
public interface FindHouse2 {/*** 找房子*/void find1();/*** 找房子*/void find2();/*** 获取名字* @return*/String getName();}/**测试类
*/
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class Test {public static void main(String[] args) {//如何动态创建一个代理类对象(接口的代理类对象)//【这里代理的是FindHouse2.class类】FindHouse2 obj = (FindHouse2) (Proxy.newProxyInstance(FindHouse2.class.getClassLoader(),new Class[]{FindHouse2.class},new MyInvocationHandler()));//调用代理类对象的find1()方法obj.find1();//调用代理类对象的find2()方法obj.find2();//调用代理类对象的getName()方法System.out.println(obj.getName());}///方法调用处理器///private static class MyInvocationHandler implements InvocationHandler {//钩子函数//obj.find1() => 调用方法//在调用方法时,回调这个钩子@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("正在努力找房源...");System.out.println("ing...");System.out.println("找到了xxx的房子");//返回 null -> 相当于是void//返回 其他值 -> 相当于是对应的值的类型return "哈哈";}}}
Cglib动态代理
1. 定义类(无需接口):
public class MyCglibClass {public void doSomething() {System.out.println("Doing something...");}
}
2. 创建MethodInterceptor:
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 MyMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("Before method");Object result = proxy.invokeSuper(obj, args);System.out.println("After method");return result;}
}
3. 创建代理实例:
public class Demo {public static void main(String[] args) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(MyCglibClass.class);enhancer.setCallback(new MyMethodInterceptor());MyCglibClass proxy = (MyCglibClass) enhancer.create();proxy.doSomething();}
}