Spring的@Profile注解用于方法上是一种好的实践吗?

4

我有一个使用Spring Boot框架的Web应用程序,它提供了rest服务。

我在思考如何正确地管理过滤器上的配置文件。 实际上,我的应用程序有2个配置文件:dev和prod(你可以猜出它们代表什么...)

在生产模式下,我需要启用比在开发模式下更多的过滤器。

我的过滤器配置类如下:

@Configuration
public class FiltersConfig {

    @Bean
    public FilterRegistrationBean filterRegistrationBean(CompositeFilter compositeFilter){
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.setFilter(compositeFilter);
        return filterRegistrationBean;
    }

    @Bean
    @Profile("dev")
    public CompositeFilter devCompositeFilter(){
        CompositeFilter compositeFilter = new CompositeFilter();
        List<Filter> filtersList = new ArrayList<>();
        //filtersList.add(filter1());
        compositeFilter.setFilters(filtersList);
        return compositeFilter;
    }


    @Bean
    @Profile("prod")
    public CompositeFilter prodCompositeFilter(){
        CompositeFilter compositeFilter = new CompositeFilter();
        List<Filter> filtersList = new ArrayList<>();
        //filtersList.add(filter1());
        compositeFilter.setFilters(filtersList);
        return compositeFilter;
    }
}

我的问题是:
  • 在方法上添加@Profile是一种好的实践吗?
  • 有没有办法强制编译器排除那些被注解为与当前配置文件不同的profile的类、方法等? (我不想让生产环境的jar/war文件受到不必要的代码影响!)
  • Spring Boot提供了更清晰的组织profile的方式吗?
谢谢。
3个回答

6
根据我的经验,在任何Java代码中使用@Profile都不是一个好主意。这就是为什么我认为你必须避免在代码中使用它的原因:
  1. 您始终可以定义类似于my.feature-for-the-profile.enabled的属性来使用配置文件实现相同的目标。
  2. 配置文件中的属性可以让您更好地控制每个地方的所有内容,而配置文件有时会有所不同。
  3. Spring Boot具有明确定义的特定配置文件的外部化属性支持(如application-prod.yml)。在您的代码库中添加配置文件将使事情更加复杂,有时会产生误导。
  4. 通过使用属性,可以更轻松地进行修改或覆盖,而不需要更新和重新编译代码。
  5. ProfileCondition(作为meta-annotation on @Profile)不是一个SpringBootCondition,您不能使用/autoconfig来确定是否已激活。
底线:为properties定义配置文件,而不是为@Configurations或@Beans定义配置文件。
如果您真的想要排除测试内容以获取生产代码,请查看spring-boot-devtools的文档。如果您使用Maven,则可以将所有测试类/资源放在单独的模块中,并将其标记为<optional>true</optional>或为其定义Maven配置文件。请注意,同时具有Maven配置文件和Spring Boot配置文件可能会令人困惑!

1
我的经验也让我得出了同样的结论。为每个特性定义一个属性而不是使用@Profile使代码更易读,并为您在未来混合和匹配特性提供更多灵活性。 - rougou

2

我认为最好将不同环境的配置放在不同的包中。你不想混淆你的配置。 结构可能看起来像这样:

config
    - Config1.java
    - Config2.java
    dev
        - WebConfig.java
        - DataConfig.java
    prod
        - WebConfig.java
        - DataConfig.java

这与Spring Boot的生态系统如何配合? - rougou

0

在方法上添加@Profile是一个好的实践吗?

这是Spring解决这个问题的方法 - 因此它与Spring生态系统保持一致。

是否有一种方法可以强制编译器排除使用不同配置文件注释的类、方法等,而不是当前设置的配置文件?(我不想让我的生产jar/war充满不必要的代码!)

您需要调整构建以排除类 - 另一种方法是使用ID为bean进行配置,并根据环境使用ID和配置。一种类似于to的方法。

根据我的经验,Profiles更容易。

Spring Boot是否提供了更清晰的组织配置文件的方式?

据我所知,除了上面链接中的方法外,没有更清晰的方式。


如果我调整我的构建以排除类,那么这意味着我在类上设置了@Profile而不是在方法上,对吗?因为如果在同一个类中我有两个用不同profile注释的方法,我猜两个方法都将被编译到.class文件中,无论在编译时使用哪个profile!这正是让我感到困惑的地方。 - Lucas.de
或者使用某种构建过程过滤 - 我想这将把一个配置文件的概念引入您的构建过程中。 - farrellmr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接