代理模式小述
代理模式属于结构型模式,指一个对象本身不做实际的操作,而是通过其他代理对象来得到自己想要的结果。
意义: 目标对象只需要关注自己的实现细节,通过代理对象来实现功能的增强,可以扩展目标对象的功能。
动态代理
从JVM的角度来说,动态代理是在运行时动态生成类字节码,并加载到JVM中的。
相比于静态代理来说,动态代理更加灵活。我们不需要针对每个目标类都单独创建一个代理类,并且也不需要我们必须实现接口,我们可以直接代理实现类( CGLIB 动态代理机制)。
JDK动态代理
JDK动态代理的实现依赖与两个核心,一个是Proxy类中的静态newProxyInstance()方法,使用这个方法可以创建一个代理对象。二是上述创建方法中必须的参数「InvocationHandler h」我们的代理对象必须实现InvocationHandler接口并重写其中的invoke方法。
使用JDK动态代理的原理可以概括如下:
- 通过Proxy类的newProxyInstance()创建代理对象。
- 上述创建代理对象中必须传入实现InvocationHandler接口invoke方法的类。
- 通过代理对象调用具体方法时,会进入创建的代理对象中传入的实现了invoke方法的参数中。在invoke方法中对原方法进行增强。在invoke中调用原方法主要是通过反射机制实现的。
JDK动态代理示例
创建接口并创建接口实现类:
创建MyProxy类,这个类实现了InvocationHandler接口并重新invoke方法,并且其中有一个方法getProxy()用于获取代理对象:
package jdkProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Author wt
* @Description 实现InvocationHandler接口,并重新invoke方法
* @Data 2024/12/3 下午2:41
*/
public class MyProxy implements InvocationHandler {
/**
* 代理类中的真实对象
*/
private final Object target;
public MyProxy(Object target){
this.target = target;
}
/**
* proxy:动态生成的代理类
* method:与代理类对象调用的方法相对应
* args:当前method方法的参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进入代理类...");
Object invoke = method.invoke(target, args);
System.out.println("invoke : " + invoke);
System.out.println("离开代理类...");
return null;
}
public <T>T getProxy(Class<T> clazz){
/**
* ClassLoader loader,类加载器,用于加载代理对象
* Class<?>[] interfaces,被代理类实现的一些接口
* InvocationHandler h,实现了InvocationHandler接口的对象
*/
Object o = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, this);
return (T)o;
}
}
编写测试代码:
最终执行结果:
JDK动态代理的应用
在Java实现的RPC框架中,底层使用到了JDK动态代理技术,主要实现流程:
客户端创建代理对象,随后通过代理对象调用方法时,会进入invoke函数,在此函数中对调用方法进行增强:组成rpc请求参数,通过socket或netty通信发送给服务端,随后服务端接受到请求参数,并解析方法名。在服务端根据反射从代理类中真实对象中获取到对象的方法,通过反射调用对应方法,获取返回值。并组装参数返回给客户端。