基于Netty4手把手实现一个带注册中心和注解的Dubbo框架 (2)

把当前服务发布出去。

@GpRemoteService //表示将当前服务发布成远程服务 @Slf4j public class UserServiceImpl implements IUserService { @Override public String saveUser(String name) { log.info("begin saveUser:"+name); return "Save User Success!"; } } 修改客户端的注解驱动

客户端同样也需要通过注解的方式来引用服务,这样就能够彻底的屏蔽掉远程通信的细节内容,代码结构如图7-2所示

image-20210908180518683

图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); } } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzpjzj.html