Spring 引导属性在初始化时加载,并根据 属性 文件中的值尊重所有和控制@Aspect

Spring boot properties to be loaded at initialization and respect all and control @Aspect based on the value from property file

我们正在使用 @PropertySources 从外部文件加载属性。现在我想enable/disable@Aspect基于一个属性。我尝试使用 @ConditionalOnExpression 但没有用。我通过创建 propertyplaceholderconfig 的 bean 来尝试相同的操作。即使在相同的情况下,它也不起作用。然后我尝试了 @profile ,但最初也没有用。

我发现当启动时使用 propertysourcepropertyplaceholder bean 时,这些变量不会在启动时初始化。有些变量总是被忽略,比如 (logging.file)。但是 @Value 工作正常。为了设置这些变量,我必须将它们作为 JVM 参数传递。

所以我的问题是:
1. 如何让 spring 在启动时始终读取指定的 属性 文件并尊重所有文件?
2. enable/disable @Aspect 哪种方法最好。使用 @profile@ConditionalOnExpression 或其他?

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

我们的属性结构:

  1. common.properties #这有所有共同的属性
  2. service.properties #属性 特定于服务。这也将包含来自 common.properties 的现有 属性,它将被覆盖。

我知道我可以使用配置文件。但是,我们希望将属性保留在外部,因此如果您要更改属性,则需要重新启动服务。我也不想将变量作为 JVM 参数传递,然后我必须以这种方式传递大部分变量。传递 -Dspring.config.location 也很困难,因为使用 common.propertiesservice.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 引导初始化本身时填充属性?

我们也可以实现 ApplicationContextInitializer 并覆盖 initialize 方法来读取属性。但是我怎样才能让它读取 2 属性 文件并用最新值覆盖重复的 属性 呢? Reference(I'm not sure how to implement my requirements in this way.)。即使在这种情况下,听起来也不像是在用锤子杀死蚊子?

当前工作解决方案:

@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. 

我是 spring 引导的新手,所以请让我知道更多说明。

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

一些有挑战的技巧:

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

解决方案:

使用-Dspring.config.location指定属性个文件。在这种情况下,总是 spring 只从指定位置读取属性。您也可以提供多个 属性 文件。 Refer this for much more details. 似乎如果您将 属性 位置作为目录 spring 以相反的顺序加载它们。但是,如果您指定文件,它将遵循指定的顺序。

注意:所有这些都可以组合在一起。 To know about precedence refer this.