我可以自动连接适配器 Class 吗?

Can I Autowire an Adapter Class?

我创建了一个单例 class,它用作我们的 Influx 数据库的适配器。它基本上看起来像:

public class InfluxDBAdapter {
    // some private static final query Strings       

    private static InfluxDBAdapter adapter = null;
    private static InfluxDB influxDB;

    private InfluxDBAdapter() {}

    public static InfluxDBAdapter getInstance() {
        if (adapter == null) {
            adapter = new InfluxDBAdapter();
            influxDB = InfluxDBFactory.connect(URL, USERNAME, PWD);
            influxDB.query(new Query(CREATE_DB, DB_NAME));
            influxDB.setLogLevel(InfluxDB.LogLevel.BASIC);
            influxDB.setDatabase(DB_NAME);
        }
        return adapter;
    }

    // some more methods to utilize the database
}

然后在另一个 class 中,我这样使用它:

@Service
public class SomeService {
    private InfluxDBAdapter adapter;

    public SomeService() {}

    @PostConstruct
    public void init() {
        adapter = InfluxDBAdapter.getInstance();
    }
}

所以这行得通,但我正在重构我的代码,我想知道是否可以简单地自动装配我的 InfluxDBAdapter class 与我目前正在做的事情相比,仍然可以实现结果相同?

是的,这应该有效。 Spring 可以调用私有构造函数,所以应该没有任何问题。

但是你为什么要这样做呢?单例模式违背了依赖注入的基本原则。如果您想要一个单例 InfluxDBAdapter bean,只需将其设为单例 bean。

我建议添加一个配置 class,它看起来像

@Configuration
public class InfluxDBConfig {
    // constants omitted...

    @Bean
    public InfluxDB influxDB() {
        final InfluxDB influxDB = InfluxDB(URL, USERNAME, PWD);
        influxDB.query(new Query(CREATE_DB, DB_NAME));
        influxDB.setLogLevel(InfluxDB.LogLevel.BASIC);
        influxDB.setDatabase(DB_NAME);
        return influxDB;
    }
}

然后您可以用 @Component 注释 InfluxDBAdapter 因为可以注入 InfluxDB 实例。当然,相应地修改 InfluxDBInfluxDBAdapter classes 的构造函数。

其中一些常量可能可以通过配置属性提供,这样您的配置逻辑就不会与您的业务逻辑混淆。

创建一个 @Configuration class 来构造 InfluxDB 以及您的适配器。有了这个,您甚至可以使用 Spring 引导属性支持。

@Configuration
public class InfluxDBConfiguration {

  @Bean
  public InfluxDB influxDB() {
    InfluxDB influxDB = InfluxDBFactory.connect(URL, USERNAME, PWD);
    influxDB.query(new Query(CREATE_DB, DB_NAME));
    influxDB.setLogLevel(InfluxDB.LogLevel.BASIC);
    influxDB.setDatabase(DB_NAME);
    return influxDB;
  }

  @Bean
  public InfluxDBAdapter influxDBAdapter(InfluxDB influxDB) {
    return new InfluxDBAdapter(influxDB);
  }
}

现在您的 InfluxDBAdapter 需要一个构造函数(用于依赖注入)来检索 InfluxDB

public class InfluxDBAdapter {
    // some private static final query Strings       

    private InfluxDB influxDB;

    InfluxDBAdapter(InfluxDB influxDB) {
      this.influxDB=influxDB;
    }

    // some more methods to utilize the database
}

确保 InfluXDBConfigurationInfluxDBAdapter 在同一个包中,以便可以调用默认可见构造函数(默认可见以防止,简单,外部实例化)。

InflxuDBConfiguration 中,您可以删除包含硬编码用户名等的 static 字段,并将其替换为访问 Environment 或使用带注释的 @ConfigurationProperties class 与 type safe properties 一起工作。

@ConfigurationProperties(prefix="influxdb")
@Component
public class InfluxDBProperties {

    private String url = "default-url";
    private String dbName = "default-dbname";
    private String username = "default-user";
    private String password = "default-pwd";
    // Other properties of your liking;
    // getters & setters
}

现在有了这个 InfluxDBProperties,您可以将 influx.url=http://whatever 添加到您的 application.properties 或个人资料特定的 externally configurable。您可以将其注入 influxDB 方法以从中检索属性。

  @Bean
  public InfluxDB influxDB(InfluxDBProperties props) {
    InfluxDB influxDB = InfluxDBFactory.connect(props.getUrl(), props.getUsername(), props.getPassword());
    influxDB.query(new Query(CREATE_DB, props.getDbName()));
    influxDB.setLogLevel(InfluxDB.LogLevel.BASIC);
    influxDB.setDatabase(props.getDbName());
    return influxDB;
  }

不再需要静态变量,可针对每个环境进行配置。