https://www.jianshu.com/p/096dbda7d528
代理方式
public class RpcFactory implements InvocationHandler {@Autowiredprivate NettyClient client;Logger logger = LoggerFactory.getLogger(this.getClass());public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Request request = new Request();request.setClassName(method.getDeclaringClass().getName());request.setMethodName(method.getName());request.setParameters(args);request.setParameterTypes(method.getParameterTypes());request.setId(IdUtil.getId());Object result = client.send(request);Class<?> returnType = method.getReturnType();Response response = JSON.parseObject(result.toString(), Response.class);if (response.getCode()==1){throw new Exception(response.getError_msg());}if (returnType.isPrimitive() || String.class.isAssignableFrom(returnType)){return response.getData();}else if (Collection.class.isAssignableFrom(returnType)){return JSONArray.parseArray(response.getData().toString(),Object.class);}else if(Map.class.isAssignableFrom(returnType)){return JSON.parseObject(response.getData().toString(),Map.class);}else{Object data = response.getData();return JSONObject.parseObject(data.toString(), returnType);}}}
package com.viewscenes.netsupervisor.configurer.rpc;import org.springframework.beans.factory.FactoryBean;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.support.AbstractBeanFactory;import org.springframework.context.support.AbstractApplicationContext;import java.lang.reflect.Proxy;/*** Created by MACHENIKE on 2018-12-03.*/public class RpcFactoryBean<T> implements FactoryBean<T> {private Class<T> rpcInterface;@Autowiredprivate RpcFactory<T> factory;/*** {@link AbstractApplicationContext#registerBeanPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory)}* 会通过 rpcInterface 实例化 RpcFactoryBean* @param rpcInterface*/public RpcFactoryBean(Class<T> rpcInterface) {this.rpcInterface = rpcInterface;}/*** 把 Bean 的定义 GenericBeanDefinition 放到了容器之后,就需要初始化这些 Bean,* 而 Bean 的初始化时机有2个:* 1、在程序第一个主动调用 getBean 的时候* 2、在完成容器初始化的时候会初始化 lazy-init 配置为 false 的Bean(默认为false)* 在这里,由于 RpcFactoryBean 未设置懒加载,故初始化的时机是第二种。上面两种初始化的过程都是一样的,* 都会调用 {@link AbstractBeanFactory#doGetBean(java.lang.String, java.lang.Class, java.lang.Object[], boolean) 方法,* 里面有个方法 getObjectForBeanInstance,会判断当前的 Bean 是否实现了 {@link FactoryBean}。* 如果该 Bean 未实现 FactoryBean 接口,则直接返回该Bean实例;* 如果该 Bean 实现了 FactoryBean 接口,则会返回的实例是 getObject() 返回值。* @return* @throws Exception*/public T getObject() throws Exception {return getRpc();}public Class<?> getObjectType() {return this.rpcInterface;}public boolean isSingleton() {return true;}/*** JDK 动态代理,当调用 rpcInterface 接口的方法时,会走 factory 的 invoke 方法* @param <T>* @return*/public <T> T getRpc() {return (T) Proxy.newProxyInstance(rpcInterface.getClassLoader(), new Class[] { rpcInterface },factory);}}
// 0.容器启动1.编码是要实现FactoryBean类,getObjectType方法通过外部传入用于初始化,getObject方法返回代理对象。1.编码时需要标记哪些服务是rpc bean(dubbo:reference, sofa:reference ...)。2.spring容器启动时基于bean加载注册时某些扩展点的进行判断为rpc bean。针对rpc bean进行改造,将其BeanDefiniation的Class改为自定义的FactoryBean,并改为按type注册,也就是FactoryBean.getObjectType方法。3.BeanDefiniation实例化时(注册或者首次使用)会判断是否是FactoryBean实现类,如果是会通过FactoryBean.getObject方法来返回实例对象(代理对象)。4.代理对象在执行时实际执行时通过socket通信获取结果。并不会实际调用method.invoke,或者说这一步被推到服务端进行执行了。// 1.Clientclass XXClientImpl{@AutoWiredprivate UserService userService;public void doSomething(){userService.getUser();}}// 2. 客户端通过动态代理 + socket(netty) + 服务端通过反射// FactoryBean是springIoC提供的一项比较方便来实现动态代理类注册的功能,因为它把实现对象和注册类// 在分化开来,并在框架内给予了特殊处理。// 想想一下,如果没有FactoryBean,如何处理?也就是要把代理类作为普通bean来注册,这就需要一个地方来// 维护jar类和代理类之间的关系,或者基于约定大于配置的思想,通过名称来关联。
