首页 > 解决方案 > 在初始化时加载 Spring Boot 属性并尊重所有属性并根据属性文件中的值控制 @Aspect

问题描述

我们正在使用@PropertySources. 现在我想@Aspect基于属性启用/禁用。我尝试使用@ConditionalOnExpressionwhich 不起作用。我通过创建一个propertyplaceholderconfig. 即使在相同的情况下,它也不起作用。然后我尝试@profile了最初也没有工作。

我想出的是,这些变量在启动时propertysourcepropertyplaceholder在启动时使用 bean 时并未初始化。某些变量总是被忽略,例如(logging.file)。但@Value工作正常。为了设置这些变量,我必须将它们作为 JVM 参数传递。

所以我的问题是:
1. 如何让 spring 在启动时始终读取指定的属性文件并尊重所有这些文件?
2.这是启用/禁用的最佳方式@Aspect。使用@profileor@ConditionalOnExpression还是别的什么?

目前,我们logging.file在 main 方法中进行设置,因为它的行为方式也相同。但是你们知道这不是正确的方法,因为我最终可能会像这样一个一个地添加属性。我想将所有属性放入外部文件中,以便 spring 读取这些文件并设置其属性。

我们的物业结构:

  1. common.properties #这个有所有通用属性
  2. service.properties #特定于服务的属性。这还将包含来自 common.properties 的现有属性,这些属性将被覆盖。

我知道我可以使用个人资料。但是,我们希望将属性保留在外部,如果您要更改属性,则需要重新启动服务。我也不想将变量作为 JVM 参数传递,然后我必须以这种方式传递大部分变量。传递 -Dspring.config.location 也很困难,common.properties因为service.properties每个服务都使用了“service.properties”文件名。

示例代码:

主类:

@PropertySources({
        @PropertySource(value = "file:${property_path}/common.properties", ignoreResourceNotFound = false),
        @PropertySource(value = "file:${property_path}/service1.properties", ignoreResourceNotFound = true) })
public class MainClass {
static String logDirectory = ApplicationContext.getGlobalProperty("logging.file");

    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(MainClass.class);

        Properties properties = new Properties();
        properties.put("logging.file", logDirectory);
        springApplication.setDefaultProperties(properties);
        springApplication.run(args);
    }
}

应用环境:

@Configuration
@EnableAutoConfiguration
public class ApplicationContext implements EnvironmentAware {

    private static Environment environment;

    @Override
    public void setEnvironment(Environment environment) {
        ApplicationContext.environment = environment;
    }
    public static String getGlobalProperty(String propertyName) {
    return environment.getProperty(propertyName);
    }
}

在这里,您可以看到我曾经environment获得的任何方式property。有没有办法使用环境设置属性,以便在 spring boot 初始化本身时填充属性?

我们还可以实现ApplicationContextInitializer和覆盖initialize读取属性的方法。但是如何让它读取 2 个属性文件并用最新值覆盖重复的属性?参考(我不确定如何以这种方式实现我的要求。)。即使在这种情况下,您听起来也不像是想用锤子杀死蚊子吗?

当前工作解决方案:

@Aspect
@Profile("!production")
@Configuration
public class ControllerAspect {
@pointcut(....)
} //Here also I've to pass spring.profiles.active as JVM params.
//setting the value in common.properties or service1.properties is not working. 

我是弹簧靴的新手,所以请让我知道以获取更多说明。

标签: javaspringspring-bootpropertiesproperties-file

解决方案


似乎 Spring 默认会在初始化时加载一些属性,除非您专门编写逻辑来覆盖它们(就像我在 中写的那样MainClass.java,否则没有选项可以覆盖这些属性。其中一些包括(logging.file,@ConditionalonExpression 中使用的键)。

一些有自己挑战的技巧:

  1. 在类路径中指定属性application.properties。在早期阶段加载的变量总是从此文件中读取。挑战:我已将所有属性紧密耦合到 jar 中,为了更改值,我必须重新编译并重新启动 Jar。
  2. 使用配置文件并定义application.propertiesapplication-profile.properties. 挑战:我必须创建这么多配置文件,但之前的挑战仍然存在。
  3. 将属性值作为 JVM 参数传递为-Dproperty.key=value. 挑战:认真吗?我应该发送多少属性作为 JVM 参数?
  4. 实现ApplicationContextInitialize和覆盖initialize方法。挑战:不建议覆盖 Spring 的默认行为,并且仅将其用于读取属性文件是不是有点矫枉过正?

解决方案:

用于-Dspring.config.location指定属性文件。在这种情况下,spring 总是只从指定的位置读取属性。您也可以提供多个属性文件。有关更多详细信息,请参阅此内容。如果您在目录弹簧以相反的顺序加载它们时给出属性位置,似乎。但是,如果您指定文件,它将遵循指定的顺序。

注意:所有这些都可以组合在一起。要了解优先级,请参阅此


推荐阅读