简体   繁体   English

如何在 Spring-Boot 中注入静态类?

[英]How to inject static class in Spring-Boot?

This question was asked a lot of times.这个问题被问了很多次。 I am bit confused and hope your ideas.我有点困惑,希望你的想法。

I am integrating Google Cloud Storage in Spring-Boot.我正在 Spring-Boot 中集成 Google Cloud Storage。

I have config class.我有配置类。

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

    private String serviceAccountId;

    //...
}

Storage factory which implements singleton pattern.实现单例模式的存储工厂。

@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();
    }
}

And I use StorageFactory in the service like that.我在这样的service使用 StorageFactory。

Storage client = StorageFactory.getService()

I have read that Autowired doesn't inject static members.我读过Autowired不会注入静态成员。 Is there another way to implement it?有没有另一种方法来实现它? Maybe here Spring-Boot's features which create singleton easily.也许这里 Spring-Boot 的功能可以轻松创建单例。

What should I read?我应该读什么? Could you give me links?你能给我链接吗? Can you guide me in the right direction?你能指导我正确的方向吗?

Link for the GCS examples . GCS 示例的链接。

I would recommend not using static methods for this purpose.我建议不要为此使用静态方法。 If you are using Spring Boot it would be better to use a configuration class to inject a singleton scoped Storage instance:如果您使用 Spring Boot,最好使用配置类来注入单例范围的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(...) ...;
  }
}

Depending upon what you're doing with GCSConfig you could just inject the property values or the Spring Boot Environment into the StorageServiceConfiguration class, and skip the intermediate object.根据您使用GCSConfig执行的操作,您可以将属性值或 Spring Boot Environment注入StorageServiceConfiguration类,并跳过中间对象。

You do not need to inject static classes.您不需要注入静态类。 Injection implies that an instance has been created.注入意味着已经创建了一个实例。 Your referencing class just has to use the import static ...您的引用类只需要使用import static ...

You can perform this operation as following way and it could best fit in your usecase您可以按以下方式执行此操作,它最适合您的用例

Step 1: create new class that will able to return instance of bean class第 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;
    }
}

Step 2: create your own configuration class where your config properties are bind第 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;
    }
}

Finally now whenever you need configuration class instance just invoke CloudConfig.getInstance() method and access all the required data using gettter and setter of that class最后,每当您需要配置类实例时,只需调用CloudConfig.getInstance()方法并使用该类的 gettter 和 setter 访问所有必需的数据

get more detail about bean injection click here get more detail about bean injection 请单击此处

I hope it will help you out.我希望它能帮助你。 Thanks.谢谢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM