small-rpc 框架(八)-spring集成

small-rpc 框架(八)-spring集成

前言

回顾之前定义的注解,@URpcService用于服务发现,@URpcAutowired用于客户端RPC服务注入

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface URpcService {

}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface URpcAutowired {

}

流程:

  • 扫描自定义注解,将其纳入spring ioc容器
  • 通过 BeanPostProcessor 后置处理器,进行服务注册和自动注入

扫描类

指定扫描包路径

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(URpcScannerRegistrar.class)
public @interface URpcServiceScan {

    /**
     * @return
     */
    String basePackage();
}
CustomScanner

过滤扫描注解类型

public class CustomScanner extends ClassPathBeanDefinitionScanner {

    public CustomScanner(BeanDefinitionRegistry registry, Class<? extends Annotation> annoType) {
        super(registry);
        super.addIncludeFilter(new AnnotationTypeFilter(annoType));
        super.addExcludeFilter(new AnnotationTypeFilter(Configuration.class));
    }

    @Override
    public int scan(String... basePackages) {
        return super.scan(basePackages);
    }
}
URpcScannerRegistrar

将rpc服务纳入spring ioc容器

@Slf4j
public class URpcScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
    private static final String BASE_PACKAGE_ATTRIBUTE_NAME = "basePackage";
    private ResourceLoader resourceLoader;

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        //get the attributes and values ​​of RpcScan annotation
        AnnotationAttributes rpcScanAnnotationAttributes = AnnotationAttributes.fromMap(annotationMetadata.getAnnotationAttributes(URpcServiceScan.class.getName()));
        String[] rpcScanBasePackages = new String[0];
        if (rpcScanAnnotationAttributes != null) {
            // get the value of the basePackage property
            rpcScanBasePackages = rpcScanAnnotationAttributes.getStringArray(BASE_PACKAGE_ATTRIBUTE_NAME);
        }
        if (rpcScanBasePackages.length == 0) {
            rpcScanBasePackages = new String[]{((StandardAnnotationMetadata) annotationMetadata).getIntrospectedClass().getPackage().getName()};
        }
        // Scan the RpcService annotation
        CustomScanner rpcServiceScanner = new CustomScanner(beanDefinitionRegistry, URpcService.class);
        // Scan the Component annotation
        CustomScanner springBeanScanner = new CustomScanner(beanDefinitionRegistry, Component.class);
        if (resourceLoader != null) {
            rpcServiceScanner.setResourceLoader(resourceLoader);
            springBeanScanner.setResourceLoader(resourceLoader);
        }

        int rpcServiceCount = rpcServiceScanner.scan(rpcScanBasePackages);
        log.info("rpc Scanner扫描的数量 [{}]", rpcServiceCount);
        // 非必须
        int scan = springBeanScanner.scan(rpcScanBasePackages);
        log.info("spring component Scanner扫描的数量 [{}]", scan);
    }

}
UrpcBeanPostProcessor

实现rpc服务注册和依赖注入

@Slf4j
public class UrpcBeanPostProcessor implements BeanPostProcessor, Ordered {

    private ClientProxy clientProxy;

    public UrpcBeanPostProcessor(ClientProxy clientProxy) {
        this.clientProxy = clientProxy;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        //rpc 服务注入
        Field[] declaredFields = bean.getClass().getDeclaredFields();
        for (Field declaredField : declaredFields) {
            URpcAutowired annotation = declaredField.getAnnotation(URpcAutowired.class);
            if (Objects.isNull(annotation)){
                continue;
            }
            declaredField.setAccessible(true);
            //创建接口的代理对象
            Object value = clientProxy.getProxy(declaredField.getType());
            try {
                declaredField.set(bean,value);
            } catch (IllegalAccessException e) {
                log.info("postProcessAfterInitialization URpcAutowired inject error: {}-{}", beanName, declaredField.getName());
                throw new RuntimeException(e);
            }
        }
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
UrpcServerBeanPostProcessor
@Slf4j
public class UrpcServerBeanPostProcessor implements BeanPostProcessor, Ordered {

    private NettyRpcServer server;

    public UrpcServerBeanPostProcessor(NettyRpcServer server) {
        this.server = server;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean.getClass().isAnnotationPresent(URpcService.class)){
            //服务注册

            log.info("register service: {}", beanName);
            server.registerService(bean);
        }
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }


    @Override
    public int getOrder() {
        return 1;
    }
}

为什么分开呢,主要是为了区别自动装配,客户端和服务端分别配置

RpcServerLifeCycle

将nettyServer启动交给spring 容器管理

public class RpcServerLifeCycle implements SmartLifecycle {

    private boolean running;

    private NettyRpcServer server;

    public RpcServerLifeCycle(NettyRpcServer server) {
        this.server = server;
    }

    @Override
    public void start() {
        server.start();
        running = true;
    }

    @Override
    public void stop() {
        server.stop();
        running = false;
    }

    @Override
    public boolean isRunning() {
        return running;
    }
}

如果直接在NettyRpcServer的 start 方法上加 @PostConstruct 注解 ,会阻塞 ioc容器启动

自动装配

客户端
@Configuration
public class RpcConfiguration {

    @Bean
    public ServiceDiscovery serviceDiscovery(){
        return new ZkServiceDiscovery("192.17.x.x:2181");
    }

    @Bean
    public RpcTransport rpcTransport(){
        return new NettyRpcClient();
    }

    @Bean
    public ClientProxy clientProxy(ServiceDiscovery serviceDiscovery){
        return new ClientProxy(rpcTransport(), serviceDiscovery);
    }

    @Bean
    public UrpcBeanPostProcessor urpcBeanPostProcessor(ClientProxy clientProxy){
        return new UrpcBeanPostProcessor(clientProxy);
    }

}
服务端
@Configuration
public class RpcServerConfiguration {

    @Bean
    public NettyRpcServer nettyRpcServer(ServerConfig serverConfig, ServiceDiscovery serviceRegistry) {
        return new NettyRpcServer(serverConfig, (ServiceRegistry) serviceRegistry);
    }

    @Bean
    public RpcServerLifeCycle rpcServerLifeCycle(NettyRpcServer server){
        return new RpcServerLifeCycle(server);
    }

    @Bean
    public UrpcServerBeanPostProcessor urpcServerBeanPostProcessor(NettyRpcServer server) {
        return new UrpcServerBeanPostProcessor(server);
    }


}

测试

客户端
@Component
public class SpringHelloClient {

    @URpcAutowired
    private HelloService helloService;

    public void hello(){
        String hello = helloService.hello(Hello.builder().description("测试").message("张三").build());
        System.out.println("response: "+ hello);
    }

    public void hello2(){
        Hello hello = helloService.hello2(Hello.builder().description("测试").message("张三").build());
        System.out.println("response: "+ JSON.toJSONString(hello));
    }
}

//指定扫描路径
@URpcServiceScan(basePackage = "org.example.urpc")
public class SpringHelloClientMain {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(SpringHelloClientMain.class,RpcConfiguration.class);
        SpringHelloClient helloClient = context.getBean(SpringHelloClient.class);
        helloClient.hello();
        helloClient.hello2();
        context.close();
    }
}

服务端
@URpcServiceScan(basePackage = "org.example.urpc")
public class SpringHelloServer {

    public static void main(String[] args) {

        new AnnotationConfigApplicationContext(SpringHelloServer.class,
                ServerConfiguration.class,
                RpcConfiguration.class,
                RpcServerConfiguration.class
        );
    }
}

@Configuration
public class ServerConfiguration {

    @Bean
    public ServerConfig serverConfig() {
        return ServerConfig.builder()
                .host(NetUtil.getLocalhostStr())
                .port(9999).appName("mic-hello").build();
    }

}

结果:

response: hello from server: 张三
response: {"description":"hello from server","message":"你好"}

good luck!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值