企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
> anoyi中的GrpcAutoConfiguration 1. 简述 这个方法是读取端口ip配置并执行启动grpc的核心方法 2. 查看GrpcAutoConfiguration的注解 ~~~ @Slf4j @Configuration @EnableConfigurationProperties(GrpcProperties.class) ~~~ 这三个注解,一个slf4j日志,代表可以直接调用日志对象,一个是Configuration,代表是ico的配置类,一个是EnableConfigurationProperties,会自己动注入配置的实体 3. 分析GrpcProperties类 ~~~ @Data @ConfigurationProperties(prefix = "spring.grpc") public class GrpcProperties { /** * enable server start */ private boolean enable; /** * server listen port */ private int port; /** * client config */ private List<RemoteServer> remoteServers; /** * client interceptor */ private Class clientInterceptor; /** * server interceptor */ private Class serverInterceptor; } ~~~ 这个类头部有个两个注解类,一个是Data代表该类自己生成get和set方法,一个是ConfigurationProperties,代表会去拿jvm里面的Properties的key前缀符合(prefix = "spring.grpc")的属性,并实例化GrpcProperties ,把Properties符合条件的value值注入同名的属性中。 4. 查看属性 ~~~ private final AbstractApplicationContext applicationContext; private final GrpcProperties grpcProperties; ~~~ applicationContext是全局上下文的spring context,在构造方法调用的时候回自动注入,grpcProperties是在构造方法的时候自动注入 5. 查看构造方法(这个方法交给spring实例化,具体查看Configuration这个注解,这个注解会在ico容器初始化) ~~~ public GrpcAutoConfiguration(AbstractApplicationContext applicationContext, GrpcProperties grpcProperties) { this.applicationContext = applicationContext; this.grpcProperties = grpcProperties; } ~~~ 6. 一些bean的实现 ~~~ /** * 全局 RPC 序列化/反序列化 */ @Bean @ConditionalOnMissingBean(SerializeService.class) public SerializeService serializeService() { return new SofaHessianSerializeService(); } /** * PRC 服务调用 */ @Bean public CommonService commonService(SerializeService serializeService) { return new CommonService(applicationContext, serializeService); } /** * RPC 服务端 */ @Bean @ConditionalOnMissingBean(GrpcServer.class) @ConditionalOnProperty(value = "spring.grpc.enable", havingValue = "true") public GrpcServer grpcServer(CommonService commonService) throws Exception { GrpcServer server = new GrpcServer(grpcProperties, commonService); server.start(); return server; } /** * RPC 客户端 */ @Bean @ConditionalOnMissingBean(GrpcClient.class) public GrpcClient grpcClient(SerializeService serializeService) { GrpcClient client = new GrpcClient(grpcProperties, serializeService); client.init(); return client; } ~~~ ConditionalOnMissingBean意思是相应的配置的类如果不存在就不调用注解它的方法,ConditionalOnProperty注解的意思是必须满足配置的value的相对应的Properties的value值等于havingValue 的值才能执行注解它的方法 7. 查看ExternalGrpcServiceScannerRegistrar类 ~~~ /** * 手动扫描 @GrpcService 注解的接口,生成动态代理类,注入到 Spring 容器 */ public static class ExternalGrpcServiceScannerRegistrar implements BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware { private BeanFactory beanFactory; private ResourceLoader resourceLoader; @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } @Override public void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { ClassPathBeanDefinitionScanner scanner = new ClassPathGrpcServiceScanner(registry); scanner.setResourceLoader(this.resourceLoader); scanner.addIncludeFilter(new AnnotationTypeFilter(GrpcService.class)); Set<BeanDefinition> beanDefinitions = scanPackages(importingClassMetadata, scanner); ProxyUtil.registerBeans(beanFactory, beanDefinitions); } /** * 包扫描 */ private Set<BeanDefinition> scanPackages(AnnotationMetadata importingClassMetadata, ClassPathBeanDefinitionScanner scanner) { List<String> packages = new ArrayList<>(); Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(GrpcServiceScan.class.getCanonicalName()); if (annotationAttributes != null) { String[] basePackages = (String[]) annotationAttributes.get("packages"); if (basePackages.length > 0) { packages.addAll(Arrays.asList(basePackages)); } } Set<BeanDefinition> beanDefinitions = new HashSet<>(); if (CollectionUtils.isEmpty(packages)) { return beanDefinitions; } packages.forEach(pack -> beanDefinitions.addAll(scanner.findCandidateComponents(pack))); return beanDefinitions; } } protected static class ClassPathGrpcServiceScanner extends ClassPathBeanDefinitionScanner { ClassPathGrpcServiceScanner(BeanDefinitionRegistry registry) { super(registry, false); } @Override protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent(); } } ~~~ 这个类在import注解配置中,所以会在spring启动的时候初始化该类,该类实现了 BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware这三个类, BeanFactoryAware提供bean工厂, ImportBeanDefinitionRegistrar提供扫描包时候调用的registerBeanDefinitions方法, ResourceLoaderAware提供setResourceLoader的方法 registerBeanDefinitions这个方法在spring启动时候调用, 8. 查看registerBeanDefinitions方法 ~~~ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { ClassPathBeanDefinitionScanner scanner = new ClassPathGrpcServiceScanner(registry); scanner.setResourceLoader(this.resourceLoader); scanner.addIncludeFilter(new AnnotationTypeFilter(GrpcService.class)); Set<BeanDefinition> beanDefinitions = scanPackages(importingClassMetadata, scanner); ProxyUtil.registerBeans(beanFactory, beanDefinitions); } ~~~ 这个方法有两个参数AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,importingClassMetadata这个参数可以取得import注解的父注解的参数,registry是bean注册器, ClassPathGrpcServiceScanner是继承ClassPathBeanDefinitionScanner的方法,这里new这个对象,并重构 isCandidateComponent的方法,这个是过滤类的方法,下面查看ClassPathGrpcServiceScanner类 ~~~ protected static class ClassPathGrpcServiceScanner extends ClassPathBeanDefinitionScanner { ClassPathGrpcServiceScanner(BeanDefinitionRegistry registry) { super(registry, false); } @Override protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent(); } } ~~~ 这个类很简单,然后registerBeanDefinitions这个方法会执行下面两句语句,这个只是把扫描器添加过滤器,过滤掉没有GrpcService注解的类 ~~~ scanner.setResourceLoader(this.resourceLoader); scanner.addIncludeFilter(new AnnotationTypeFilter(GrpcService.class)); ~~~ 接下来registerBeanDefinitions方法会调用 ~~~ Set<BeanDefinition> beanDefinitions = scanPackages(importingClassMetadata, scanner); ~~~ 这个scanPackages可以扫描出符合条件的BeanDefinition,具体scanPackages方法,可以看下面 ~~~ /** * 包扫描 */ private Set<BeanDefinition> scanPackages(AnnotationMetadata importingClassMetadata, ClassPathBeanDefinitionScanner scanner) { List<String> packages = new ArrayList<>(); Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(GrpcServiceScan.class.getCanonicalName()); if (annotationAttributes != null) { String[] basePackages = (String[]) annotationAttributes.get("packages"); if (basePackages.length > 0) { packages.addAll(Arrays.asList(basePackages)); } } Set<BeanDefinition> beanDefinitions = new HashSet<>(); if (CollectionUtils.isEmpty(packages)) { return beanDefinitions; } packages.forEach(pack -> beanDefinitions.addAll(scanner.findCandidateComponents(pack))); return beanDefinitions; } ~~~ 这个scanPackages方法只是扫描符合ClassPathBeanDefinitionScanner 扫描器标准的packages包底下的类,并生成 BeanDefinition,接下来registerBeanDefinitions方法会调用ProxyUtil.registerBeans(beanFactory, beanDefinitions);这是代理的方法,接下来看看这个代理类 9. 查看ProxyUtil类 ~~~ protected static class ProxyUtil { static void registerBeans(BeanFactory beanFactory, Set<BeanDefinition> beanDefinitions) { for (BeanDefinition beanDefinition : beanDefinitions) { String className = beanDefinition.getBeanClassName(); if (StringUtils.isEmpty(className)) { continue; } try { // 创建代理类 Class<?> target = Class.forName(className); Object invoker = new Object(); InvocationHandler invocationHandler = new GrpcServiceProxy<>(target, invoker); Object proxy = Proxy.newProxyInstance(GrpcService.class.getClassLoader(), new Class[]{target}, invocationHandler); // 注册到 Spring 容器 String beanName = ClassNameUtils.beanName(className); ((DefaultListableBeanFactory) beanFactory).registerSingleton(beanName, proxy); } catch (ClassNotFoundException e) { log.warn("class not found : " + className); } } } } ~~~ 这个类具体看registerBeans方法,这个方法有两个参数BeanFactory beanFactory, Set<BeanDefinition> beanDefinitions,beanFactory是bean工厂,beanDefinitions是我们上面扫描的类,看样子是要实例化bean了 接下来看看 ``` InvocationHandler invocationHandler = new GrpcServiceProxy<>(target, invoker); ``` 这个是实例化代理类,并传入被代理类invoker,也就是我们的bean,然后是执行下面的方法 ``` Object proxy = Proxy.newProxyInstance(GrpcService.class.getClassLoader(), new Class[]{target}, invocationHandler); ``` 这个是调用动态代理newProxyInstance方法,返回invoker这个实例化的类,但是这时候动态代理可能已经重写invoker这个的所有方法,实现aop了,具体怎么样我们也不知道,也就是proxy 已经不是原本的类,接下来看下一步 ``` String beanName = ClassNameUtils.beanName(className); ((DefaultListableBeanFactory) beanFactory).registerSingleton(beanName, proxy); ``` 这里把我们的代理类注册到spring bean中