<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                > 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中
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看