【问题标题】:How to inject static class in Spring-Boot?如何在 Spring-Boot 中注入静态类?
【发布时间】:2016-07-20 17:59:09
【问题描述】:

这个问题被问了很多次。我有点困惑,希望你的想法。

我正在将 Google Cloud Storage 集成到 Spring-Boot 中。

我有配置类。

@Component
@ConfigurationProperties(prefix = "gcs.credentials")
public class  GCSConfig {

    private String serviceAccountId;

    //...
}

实现单例模式的存储工厂。

@Component
public class StorageFactory {

    @Autowired
    private static GCSConfig gcsConfig;

    private static Storage instance = null;

    public static synchronized Storage getService() throws GeneralSecurityException, IOException {
        if (instance == null) {
            instance = buildService();
        }
        return instance;
    }

    private static Storage buildService() throws GeneralSecurityException, IOException {

        HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
        JsonFactory jsonFactory = new JacksonFactory();
        // ...
        // I use gcsConfig here
        // ...
        return new Storage.Builder(httpTransport, jsonFactory, credential)
        .setApplicationName("Google Cloud Storage App")
        .build();
    }
}

我像这样在service 中使用 StorageFactory。

Storage client = StorageFactory.getService()

我读到Autowired 不会注入静态成员。还有另一种实现方式吗?也许这里 Spring-Boot 的功能可以轻松创建单例。

我应该读什么?你能给我链接吗?你能指引我正确的方向吗?

GCS examples 的链接。

【问题讨论】:

  • 你知道spring beans的默认作用域是“singleton”吗?因此,在一个专门用作 Spring bean 的类中实现单例模式并没有多大意义。

标签: java spring spring-boot google-cloud-storage


【解决方案1】:

我建议不要为此使用静态方法。如果您使用的是 Spring Boot,最好使用 configuration class 来注入单例范围的 Storage 实例:

@Configuration
public class StorageServiceConfiguration {

  private GCSConfig gcsConfig;

  // I prefer using explicit setters for testing, YMMV
  @Autowired
  public void setGcsConfig(GCSConfig gcsConfig) {
    this.gcsConfig = gcsConfig;
  }

  @Bean
  public Storage getStorageService() {
     // Logic to create your Storage instance.
     return new Storage.Builder(...) ...;
  }
}

根据您对GCSConfig 所做的操作,您可以将属性值或Spring Boot Environment 注入StorageServiceConfiguration 类,然后跳过中间对象。

【讨论】:

    【解决方案2】:

    您不需要注入静态类。注入意味着已经创建了一个实例。你的引用类只需要使用import static ...

    【讨论】:

      【解决方案3】:

      您可以按照以下方式执行此操作,它最适合您的用例

      第 1 步:创建能够返回 bean 类实例的新类

      package com.xyx;
      
      import org.springframework.beans.BeansException;
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.ApplicationContextAware;
      import org.springframework.stereotype.Component;
      
      @Component
      public class ApplicationContextProvider implements ApplicationContextAware {
      
          private static ApplicationContext context;
      
          private ApplicationContextProvider(){}
      
          public static ApplicationContext getApplicationContext() {
              return context;
          }
      
          public  static <T> T getBean(String name,Class<T> aClass){
              return context.getBean(name,aClass);
          }
      
          @Override
          public void setApplicationContext(ApplicationContext ctx) throws BeansException {
              context = ctx;
          }
      }
      

      第 2 步:创建您自己的配置类,并在其中绑定您的配置属性

      @Component
      @ConfigurationProperties(prefix = "gcs.credentials")
      public class  CloudConfig {
          private static CloudConfig objectInstance=null;
      
          private String serviceAccountId;
      
          public String getServiceAccountId() {
              return serviceAccountId;
          }
      
          public void setServiceAccountId(String serviceAccountId) {
              this.serviceAccountId = serviceAccountId;
          }
      
          public static CloudConfig getInstance(){
              if(objectInstance==null){
                  objectInstance=ApplicationContextProvider.getBean("cloudConfig",CloudConfig.class);
              }
              return objectInstance;
          }
      }
      

      现在,当您需要配置类实例时,只需调用 CloudConfig.getInstance() 方法并使用该类的 gettter 和 setter 访问所有必需的数据

      get more detail about bean injectionclick here

      希望对你有所帮助。谢谢。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-05-09
        • 2014-08-20
        • 2018-09-13
        • 2018-07-28
        • 2017-07-05
        • 2018-11-11
        • 2020-02-07
        • 2011-11-07
        相关资源
        最近更新 更多