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!