content: package com.anoyi.grpc.config;
  
  import com.anoyi.grpc.GrpcClient;
  import com.anoyi.grpc.GrpcServer;
  import com.anoyi.grpc.annotation.GrpcService;
  import com.anoyi.grpc.annotation.GrpcServiceScan;
  import com.anoyi.grpc.binding.GrpcServiceProxy;
  import com.anoyi.grpc.service.CommonService;
  import com.anoyi.grpc.service.SerializeService;
  import com.anoyi.grpc.service.impl.SofaHessianSerializeService;
  import com.anoyi.grpc.util.ClassNameUtils;
  import lombok.extern.slf4j.Slf4j;
  import org.springframework.beans.BeansException;
  import org.springframework.beans.factory.BeanFactory;
  import org.springframework.beans.factory.BeanFactoryAware;
  import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
  import org.springframework.beans.factory.config.BeanDefinition;
  import org.springframework.beans.factory.support.BeanDefinitionRegistry;
  import org.springframework.beans.factory.support.DefaultListableBeanFactory;
  import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
  import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  import org.springframework.boot.context.properties.EnableConfigurationProperties;
  import org.springframework.cglib.proxy.InvocationHandler;
  import org.springframework.cglib.proxy.Proxy;
  import org.springframework.context.ResourceLoaderAware;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
  import org.springframework.context.support.AbstractApplicationContext;
  import org.springframework.core.io.ResourceLoader;
  import org.springframework.core.type.AnnotationMetadata;
  import org.springframework.core.type.filter.AnnotationTypeFilter;
  import org.springframework.util.CollectionUtils;
  import org.springframework.util.StringUtils;
  
  import java.util.*;
  
  @Slf4j
  @Configuration
  @EnableConfigurationProperties(GrpcProperties.class)
  public class GrpcAutoConfiguration {
  
      private final AbstractApplicationContext applicationContext;
  
      private final GrpcProperties grpcProperties;
  
      public GrpcAutoConfiguration(AbstractApplicationContext applicationContext, GrpcProperties grpcProperties) {
          this.applicationContext = applicationContext;
          this.grpcProperties = grpcProperties;
      }
  
      /**
       * 全局 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;
      }
  
      /**
       * 手动扫描 @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();
          }
  
      }
  
      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);
                  }
              }
          }
      }
  
  }