当前位置: 首页 > 知识库问答 >
问题:

如何构建基于数据库的Spring Boot环境/属性源?

段干麒
2023-03-14

目标是使用包含密钥的环境运行Spring启动应用程序

或者,更抽象的定义:虽然应该首选仅按文件进行配置(更快、更容易、更宽容、…),但有时您会发现需要基于非静态文件的配置的用例。

Spring 3.1 引入了环境,它实际上是一个属性解析器(扩展了属性解析器),并且基于对象列表属性源。这样的源是属性(文件或对象)、映射或其他内容的包装器/适配器。看起来这真的是如何得到的方式。

Properties properties = new Properties();
properties.put("mykey", "in-config");
PropertiesPropertySource propertySource = new PropertiesPropertySource("myProperties", properties);

然而,这不能在@Configuration类中完成,因为它必须在配置阶段可用。想想这样的事情

@Bean public MyService myService() {
  if ("one".equals(env.getProperty("key")) {
    return new OneService();
  } else {
    return new AnotherService();
  }
}

// alternatively via
@Value("${key}")
private String serviceKey;

此外,最近的Spring版本也支持Condition

使用一个条件,如

public class OneCondition implements Condition {
  @Override
  public boolean matches(final ConditionContext context, final AnnotatedTypeMetadata metadata) {
    return "one".equals(context.getEnvironment().getProperty("key"));
  }
}

可以这样使用

@Bean
@Conditional(OneCondition.class)
public MyService myService() {
    return new OneService();
}

我的非工作想法:

选项1: @PropertySource

相应的注释处理器仅处理文件。这很好,但不适合这个用例。

选项2:Property tySourcesPlaceholder配置者

具有自定义属性源的示例

@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() throws IOException {
  PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer();
  pspc.setIgnoreUnresolvablePlaceholders(Boolean.TRUE);

  // create a custom property source and apply into pspc
  MutablePropertySources propertySources = new MutablePropertySources();
  Properties properties = new Properties();
  properties.put("key", "myvalue");
  final PropertiesPropertySource propertySource = new PropertiesPropertySource("pspc", properties);
  propertySources.addFirst(propertySource);
  pspc.setPropertySources(propertySources);

  pspc.setLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:application.properties"));
    return pspc;
}

但是,这仅配置占位符(即< code>@Value)。任何< code > environment . getproperty()都不会获利。

这或多或少与选项1相同(少魔法,多选项)。

你知道更好的选择吗?理想情况下,解决方案将使用上下文数据源。然而,这在概念上是一个问题,因为数据源bean的创建依赖于属性本身……

共有1个答案

殷学
2023-03-14

Spring Boot为这个早期处理步骤提供了一些不同的扩展点:http://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-boot-application.html#howto-customize-the-environment-or-application-context

在内部,这些选项是通过标准SpringApplicationContextInitializer的实现实现的。

根据源的优先级,键/值将在environment.getProperty()以及属性占位符中可用。

因为这些是预配置上下文侦听器,所以没有其他bean可用,例如DataSource。因此,如果应该从数据库中读取属性,则必须手动构建数据源和连接(最终是单独的数据源连接查找)。

选项: ApplicationListener for ApplicationVironmentPreparedEvent

构建使用< code > ApplicationEnvironmentPreparedEvent 和的应用程序侦听器的实现

将其注册到META-INF/spring.factories和密钥org.springframework.context.ApplicationListener

-或者-

使用< code > SpringApplicationBuilder :

new SpringApplicationBuilder(App.class)
        .listeners(new MyListener())
        .run(args);

示例

public class MyListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
  @Override
  public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
    final ConfigurableEnvironment env = event.getEnvironment();
    final Properties props = loadPropertiesFromDatabaseOrSo();
    final PropertiesPropertySource source = new PropertiesPropertySource("myProps", props);
    environment.getPropertySources().addFirst(source);
  }
}

参考编号:http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-spring-application.html#boot-features-application-events-and-listeners

选项:SpringApplicationRunListener

除了特殊事件之外,还有一个更通用的事件监听器,包含几种类型事件的挂钩。

构建SpringApplicationRunListener的实现,并将其注册到META-INF/spring中。工厂和键org.springframework.boot.SpringApplicationRunListener

示例

public class MyAppRunListener implements SpringApplicationRunListener {

  // this constructor is required!
  public MyAppRunListener(SpringApplication application, String... args) {}

  @Override
  public void environmentPrepared(final ConfigurableEnvironment environment) {

    MutablePropertySources propertySources = environment.getPropertySources();

    Properties props = loadPropertiesFromDatabaseOrSo();
    PropertiesPropertySource propertySource = new PropertiesPropertySource("myProps", props);
    propertySources.addFirst(propertySource);
  }

  // and some empty method stubs of the interface…

}

参考编号: http://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-boot-application.html#howto-customize-the-environment-or-application-context

选项:应用程序上下文初始化程序

这是所有“非引导”Spring开发人员的老朋友。然而,Spring应用程序嘲笑一个配置 - 一开始。

构建< code > ApplicationContextInitializer 的实现,并

在< code > META-INF/spring . factories 和键< code > org . spring framework . context . applicationcontext initializer 中注册它。

-或者-

使用< code > SpringApplicationBuilder :

new SpringApplicationBuilder(App.class)
        .initializers(new MyContextInitializer())
        .run(args);

示例

public class MyContextInitializer implements ApplicationContextInitializer {
  @Override
  public void initialize(final ConfigurableApplicationContext context) {
    ConfigurableEnvironment environment = context.getEnvironment();

    MutablePropertySources propertySources = environment.getPropertySources();

    Properties props = loadPropertiesFromDatabaseOrSo();
    PropertiesPropertySource propertySource = new PropertiesPropertySource("myProps", props);
    propertySources.addFirst(propertySource);
  }

}
 类似资料:
  • 我正在spring boot中构建一个可重用的库,它可以调用Rest API并进行一些验证。这将构建为JAR,目标是通过添加pom将此库用作maven依赖项。其他spring boot项目中的xml。 问题是库如何知道要加载哪些环境属性。因为它没有在任何服务器上运行。例如:调用应用程序将包含为依赖项,并部署在dit环境中。我希望库能够获取dit属性,如url、令牌等,以及关于如何实现这一点的任何建

  • 上一节,历尽艰辛,我们安装、更新和配置了Kali Linux系统,本节在此基础上安装VS Code 和它的Python插件,用来开发和调试Python程序。 0.1 本系列教程说明 本系列教程,采用的大纲母本为《Understanding Network Hacks Attack and Defense with Python》一书,为了解决很多同学对英文书的恐惧,解决看书之后实战过程中遇到的问题

  • 我想在与PRODUCTION域相同的范围内构建一个Lotus Notes TEST环境,并从PRODUCTION环境中获得names.nsf的单向副本。您有逐步参考的说明或指南吗?非常感谢。

  • 我的问题是:我们是否有一种方法来定义绑定,它将在本地环境中监听存储队列,但在部署到生产时将切换到服务总线? 这听起来像XY问题,所以如果有人有更好的主意来解决我的X问题,我洗耳恭听。

  • 本文向大家介绍SpringBoot + SpringSecurity 环境搭建的步骤,包括了SpringBoot + SpringSecurity 环境搭建的步骤的使用技巧和注意事项,需要的朋友参考一下 一、使用SpringBoot+Maven搭建一个多模块项目(可以参考这篇文章 --> 这里) 二、删除父工程的src文件,删除app、browser、core下的.java文件 依赖关系: dem

  • 通过 DSL 可以配置以下 manifest 属性: minSdkVersion targetSdkVersion versionCode versionName applicationId(有效的包名—查看 ApplicationId 与 PackageName 了解更多信息) testApplicationId(测试应用的包名) testInstrumentationRunner 例子: an