动态代理的两种模式
- jdk动态代理 //基于实现接口
- Cglib动态代理 //基于方法的继承
????????啥东西
这就不得不提到 静态代理了: 说得高大上,其实就是写一个增强类继承被增强类,
实现被增强类的同时,也可以在其中添加一些代码,增强了被增强类
但问题是:静态代理想要再增强,无非就是修改代码;或者再写一个类去增强那个增强类。
在实际开发中,这是一种很蠢的行为;跟套娃一样不说,代码冗余还越来越多。
动态代理
Spring提供了完美的动态代理,我们来看看其原理:
代码:jdk动态代理 :针对实现接口的类进行增强
public interface Subject { //公共接口
void buyHouse();
}
public class RealSubject implements Subject{
@Override
public void buyHouse() {
System.out.println("买房子");
}
}
买房接口和买家买房实现类
jdk动态代理类:
public class JDKProxyFactory { //jdk动态代理工厂
public static Object getProxyObj(Object obj){ //目标对象
/**
* ClassLoader loader, 类加载
* Class<?>[] interfaces, 目标对象实现接口
* InvocationHandler h 调用拦截器
*/
//获取类加载器
ClassLoader loader = obj.getClass().getClassLoader();
//获取目标对象实现的接口
Class<?>[] interfaces = obj.getClass().getInterfaces();
//定义调用拦截器
InvocationHandler handler = new InvocationHandler() {
//当目标对象的方法调用的时候会回调这个方法
/**
*
* @param proxy 代理对象
* @param method 目标对象的方法
* @param args 目标对象的参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("找房源....");
//调用目标对象的方法!!!!
//参数1:类的对象 参数2:方法的参数
Object invoke = method.invoke(obj, args);
System.out.println("办理手续....");
return invoke; //这里的返回值就是目标对象的返回值
}
};
Object proxyObj = Proxy.newProxyInstance(loader, interfaces, handler);
return proxyObj;
}
测试类:
public class JDKProxyTest {
@Test
public void test01(){
//创建目标对象
Subject realSubject = new RealSubject();
//realSubject.buyHouse();
//通过代理工厂创建代理对象
Subject proxyObj = (Subject) JDKProxyFactory.getProxyObj(realSubject);
//把方法传给代理类
proxyObj.buyHouse();
//通过代理类调用实际上调用的是invoke()
//代理对象和目标对象的关系? 共同实现了同一个接口(兄弟)
System.out.println(proxyObj instanceof Subject);//true
System.out.println(proxyObj instanceof RealSubject);//false
}
关键问题:为什么method就是被增强方法呢?为啥调用invoke就进行了增强呢?为什么通过代理类调用方法时会被拦截并且进入invoke()方法?
1:因为将对象交由jdk动态代理了,其通过反射可以获取到类的所有信息;通过增强的对象调用原有的方法,不会执行原有的方法,而是执行代理对象的方法。
2:而代理类调用拦截器拦截方法 InvocationHandler,将增强方法对象调用的原有方法的操作拦截下来,并进行增强。InvocationHandler 重写了invoke()所以被拦截后一定会执行invoke()方法
invoke(Object proxy, Method method, Object[] args) //这三个参数也是通过反射获取到的。
(通过反射获取的方法实例,方法接口对应的方法实例,对象方法的参数数组)
3.Object invoke = method.invoke(obj, args) (类对象的实例,方法的参数数组)
底层调用了native方法:可以看出:返回方法有三个参数
public Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException {
if (++this.numInvocations > ReflectionFactory.inflationThreshold()
&& !ReflectUtil.isVMAnonymousClass(this.method.getDeclaringClass()))
{
MethodAccessorImpl var3 = (MethodAccessorImpl)(
new MethodAccessorGenerator()).generateMethod
(this.method.getDeclaringClass(), this.method.getName(),
this.method.getParameterTypes(), this.method.getReturnType(),
this.method.getExceptionTypes(), this.method.getModifiers());
this.parent.setDelegate(var3);
}
return invoke0(this.method, var1, var2);
}
Object proxyObj = Proxy.newProxyInstance(loader, interfaces, handler)将类加载器,接口参数,拦截器(方法增强后) 一并返回给调用增强方法的类