自己设计一个的轻量级的RPC框架--客户端Spring工厂Bean和动态代理
前言
上篇博客讲到实现自定义bean,其实那边注入的bean是一个工厂Bean。这篇主要就是来讲解如何定义一个bean,并且通过jdk的动态代理来实现对消费接口的代理。
为什么要用FactoryBean接口
首先这个一个消费接口
@RPCClient
public interface clientWorld {
@RPCURL(className="serverWorld2",methodName="message")
public List message(String world);
}
这个是在controller中调用
@Controller
@RequestMapping("/clientWorld")
public class clientWorldController {
@Autowired
private clientWorld clientWorld;
@RequestMapping("sendMessage")
@ResponseBody
public List sendMessage(String message){
return clientWorld.message(message);
}
}
很明显并有没clientWorld 这个接口的实现类,其实是我在上篇讲过的我这边获取到的clientWorld 对象其实是一个代理对象。那我不可能一个接口编写一个对象的代理对象,所以这里我就需要一个工厂Bean让它来帮我们完成创建。
使用FactoryBean接口
通过传人接口对象 我们通过动态代理返回一个代理对象这样就能够灵活的实现我们的需求。
public class MethodProxyFactory<T> implements FactoryBean<T>{
private Class<T> interfaceClass;//所对应的消费接口
public Class<T> getInterfaceClass() {
return interfaceClass;
}
public void setInterfaceClass(Class<T> interfaceClass) {
this.interfaceClass = interfaceClass;
}
@Override
public T getObject() throws Exception {
return (T) newInstance(interfaceClass);//通过对应的消费接口返回代理类
}
@Override
public Class<?> getObjectType() {
return interfaceClass;
}
@Override
public boolean isSingleton() {
return true;
}
@SuppressWarnings("unchecked")
public static <T> T newInstance(Class<T> methodInterface) {
final RPCProxyHandler<T> methodProxy = new RPCProxyHandler<T>();
return (T) Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class[]{methodInterface},
methodProxy);
}
}
简单介绍jdk动态代理
Proxy类
常用创建代理对象方法
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
loader: 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
interfaces: 一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
h: 一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
InvocationHandler 接口
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
proxy: 指代我们所代理的那个真实对象
method: 指代的是我们所要调用真实对象的某个方法的Method对象
args: 指代的是调用真实对象某个方法时接受的参数
那就很简单了 只要我们在invoke()方法中调用自己的业务就能满足我们的业务需求,例如我这边是需要通过netty去请求服务获取数据并返回。这里具体的业务后面再详细讲解。