代理分为静态代理和动态代理。
动态代理分为CGLIB代理和jdk动态代理,这里主要讲jdk动态代理。
静态代理
为每个目标类设置一个代理类,实现代理类的方法和接口,同时新增其他逻辑。
静态代理类 = 目标类 + 增强方法。
缺点:为每个类都要写自己的代理类,麻烦。而且多了之后业务逻辑非常非常复杂
动态代理
因为静态代理的缺点,动态代理的目的就是,少写或者不写代理类,却能完成代理功能。
原理:
关于对象的创建过程:
1,classloader加载类文件到内容
2,执行new,申请新的内存空间
3,调用构造器,创建空白对象
4,使用父类构造器(双亲委贷机制)
5,执行构造器内容
那么可以明白,创建一个对象的关键是,得到它的class文件然后进行调用。
所以动态代理,可以通过调用class类文件,然后通过反射机制生成相对应的代理类或者代理对象。
jdk动态代理:
因为我们不写代理类,但是我们需要构造器,字段啥的,这些数据要去哪里获取呢?这里可以通过代理类和目标类实现同一个的接口来完成,这样我们就可以通过接口来获取目标类的类信息。
jdk动态代理就是基于这个思想,也就是说jdk动态代理是基于接口实现的。
实现
但是接口是不可以生成对象的,那怎么办呢?
jdk提供了两个对象,一个是invocationhandler接口和proxy类,两个类相互配合。
invocationhandler
通过实现这个接口表示生成代理类
public class RpcClientProxy implements InvocationHandler {
private String host;
private int port;
public RpcClientProxy(String host, int port) {
this.host = host;
this.port = port;
}
@SuppressWarnings("unchecked")
public <T> T getProxy(Class<T> clazz) {
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]{clazz}, this);
}
}
比如例子中rpcclientproxy就是代理类,他不需要实现目标类的东西了,只需要增强方法。
getProxy方法是用于生成代理对象的,多封装一层,方便。
实现invocationhandler接口,需要实现invoke的方法。
invoke方法用于表示代理对象的方法被调用时的动作。
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
RpcRequest rpcRequest = RpcRequest.builder()
.interfaceName(method.getDeclaringClass().getName())
.methodName(method.getName())
.parameters(args)
.paramTypes(method.getParameterTypes())
.build();
RpcClient rpcClient = new RpcClient();
return ((RpcResponse) rpcClient.sendRequest(rpcRequest, host, port)).getData();
}
相当于是增强方法。
proxy
用于生成代理对象或者代理类
getProxyClass(),生成代理类
Proxy.newProxyInstance(),生成代理实例,一般都用这个,比如类中的getProxy。