【诗90:10】我们一生的年日是七十岁,若是强壮可到八十岁;但其中所矜夸的不过是劳苦愁烦,转眼成空,我们便如飞而去。
背景
在第一篇「手写RPC(一)基于BIO」我们已经完成了 RPC 的实现,那么服务的发布和调用怎样交给 spring 管理呢?
这正是下面要探讨完成的事情 ?
目录
rpc-server-provider 服务端 provicer 迭代
-
改造服务端的 rpc-server-provider
在 pom.xml 文件中添加 spring 依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.23.RELEASE</version>
</dependency>
自定义Rpc注解 @RpcServiceAnno
用以向 spring 容器中注入实例的同时,对外发布接口服务
package com.ddup.rpc.spring; /** * 自定义服务发布注解: * 凡是加此注解的,都被发布成对外服务接口 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Component // 使用此注解的类,能被spring扫描 public @interface RpcServiceAnno { Class<?> value(); //定义使用此注解的服务接口名称 }
业务实现类 HelloServerImpl
添加 @RpcServiceAnno:[1]交给 spring 管理 [2]容器启动时可 动态处理此注解,对外发布接口
@RpcServiceAnno(IHelloSevice.class) public class HelloServerImpl implements IHelloSevice { @Override public String sayHello(String name) { System.out.println("reqeust in content : " + name); return "hello " + name; } @Override public void saveUser(User user) { System.out.println("request in saveUser : "+ user.toString()); }
现在 HelloServerImpl 已经 spring 容器管理了,那么接下来此服务应该怎么发布,我们应该怎样结合 spring 处理此注解呢?
【1】首先创建 RpcServerPublisher 对 IOC 容器启动时做额外处理
- 实现 ApplicationContextAware 接口重写 #setApplicationContext 处理添加了 @RpcServiceAnno 的 bean
- 实现 InitializingBean 接口 重写 #afterPropertiesSet 实现启动服务的过程
package com.ddup.rpc.spring; /** * RPC服务端 集成 spring */ public class RpcServerPublisher implements ApplicationContextAware, InitializingBean { private int port; private Map<String, Object> handlerMap = new HashMap<String, Object>(); /** * 缓存线程池 */ private ExecutorService executorService = Executors.newCachedThreadPool(); public RpcServerPublisher(int port) { this.port = port; } /** * 启动服务 */ @Override public void afterPropertiesSet() throws Exception { ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(port); while (true) { Socket socket = serverSocket.accept(); // 利用多线程处理任务 executorService.execute(new ProcessorHandler(socket, handlerMap)); } } catch (IOException e) { e.printStackTrace(); } finally { if (serverSocket != null) { try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 利用容器处理自定义的RPC注解 */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { Map<String, Object