把当前服务发布出去。
@GpRemoteService //表示将当前服务发布成远程服务 @Slf4j public class UserServiceImpl implements IUserService { @Override public String saveUser(String name) { log.info("begin saveUser:"+name); return "Save User Success!"; } } 修改客户端的注解驱动客户端同样也需要通过注解的方式来引用服务,这样就能够彻底的屏蔽掉远程通信的细节内容,代码结构如图7-2所示
图7-2 增加客户端注解在netty-rpc-protocol模块的annotation目录下创建下面这个注解。
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @Autowired public @interface GpRemoteReference { } SpringRpcReferenceBean定义工厂Bean,用来构建远程通信的代理
public class SpringRpcReferenceBean implements FactoryBean<Object> { private Class<?> interfaceClass; private Object object; private String serviceAddress; private int servicePort; @Override public Object getObject() throws Exception { return object; } public void init(){ this.object= Proxy.newProxyInstance(this.interfaceClass.getClassLoader(), new Class<?>[]{this.interfaceClass}, new RpcInvokerProxy(this.serviceAddress,this.servicePort)); } @Override public Class<?> getObjectType() { return this.interfaceClass; } public void setInterfaceClass(Class<?> interfaceClass) { this.interfaceClass = interfaceClass; } public void setServiceAddress(String serviceAddress) { this.serviceAddress = serviceAddress; } public void setServicePort(int servicePort) { this.servicePort = servicePort; } } SpringRpcReferencePostProcessor用来实现远程Bean的动态代理注入:
BeanClassLoaderAware: 获取Bean的类装载器
BeanFactoryPostProcessor:在spring容器加载了bean的定义文件之后,在bean实例化之前执行
ApplicationContextAware: 获取上下文对象ApplicationContenxt
@Slf4j public class SpringRpcReferencePostProcessor implements ApplicationContextAware, BeanClassLoaderAware, BeanFactoryPostProcessor { private ApplicationContext context; private ClassLoader classLoader; private RpcClientProperties clientProperties; public SpringRpcReferencePostProcessor(RpcClientProperties clientProperties) { this.clientProperties = clientProperties; } //保存发布的引用bean信息 private final Map<String, BeanDefinition> rpcRefBeanDefinitions=new ConcurrentHashMap<>(); @Override public void setBeanClassLoader(ClassLoader classLoader) { this.classLoader=classLoader; } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.context=applicationContext; } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { for (String beanDefinitionname:beanFactory.getBeanDefinitionNames()){ //遍历bean定义,然后获取到加载的bean,遍历这些bean中的字段,是否携带GpRemoteReference注解 //如果有,则需要构建一个动态代理实现 BeanDefinition beanDefinition=beanFactory.getBeanDefinition(beanDefinitionname); String beanClassName=beanDefinition.getBeanClassName(); if(beanClassName!=null){ //和forName方法相同,内部就是直接调用的forName方法 Class<?> clazz=ClassUtils.resolveClassName(beanClassName,this.classLoader); //针对当前类中的指定字段,动态创建一个Bean ReflectionUtils.doWithFields(clazz,this::parseRpcReference); } } //将@GpRemoteReference注解的bean,构建一个动态代理对象 BeanDefinitionRegistry registry=(BeanDefinitionRegistry)beanFactory; this.rpcRefBeanDefinitions.forEach((beanName,beanDefinition)->{ if(context.containsBean(beanName)){ log.warn("SpringContext already register bean {}",beanName); return; } //把动态创建的bean注册到容器中 registry.registerBeanDefinition(beanName,beanDefinition); log.info("registered RpcReferenceBean {} success.",beanName); }); } private void parseRpcReference(Field field){ GpRemoteReference gpRemoteReference=AnnotationUtils.getAnnotation(field,GpRemoteReference.class); if(gpRemoteReference!=null) { BeanDefinitionBuilder builder=BeanDefinitionBuilder.genericBeanDefinition(SpringRpcReferenceBean.class); builder.setInitMethodName(RpcConstant.INIT_METHOD_NAME); builder.addPropertyValue("interfaceClass",field.getType()); builder.addPropertyValue("serviceAddress",clientProperties.getServiceAddress()); builder.addPropertyValue("servicePort",clientProperties.getServicePort()); BeanDefinition beanDefinition=builder.getBeanDefinition(); rpcRefBeanDefinitions.put(field.getName(),beanDefinition); } } }