如何在 Spring Boot 应用程序中排除给定运行时配置文件中的包

bla*_*ekp 1 java profile spring annotations spring-boot

在我的应用我有两个配置文件dev和prod,我可以用排除豆类org.springframework.context.annotation.Profile注释:

package com.example.prod;

@Service
@Profile("prod")
public class MyService implements MyBaseService {}
Run Code Online (Sandbox Code Playgroud)

问题是,我有几个以这种方式注释的 bean,它们都在同一个 package 中com.example.prod。dev配置文件(com.example.dev包)存在类似的结构,将来我可能会有一些额外的配置文件。是否有可能一次排除整个包裹?我尝试使用org.springframework.context.annotation.ComponentScan,但无法根据实际配置文件添加排除过滤器,我想知道是否有简单的方法可以解决我的问题。

Ken*_*han 5

您可以实现自定义TypeFilter以ComponentScan根据活动配置文件禁用某些包。一个启动示例是:

(1) 实现过滤器。出于演示目的,我硬编码,如果活动配置文件是dev,它将排除由devExcludePackage属性配置的包。对于prodprofile ,它将排除由prodExcludePackage 以下配置的包:

public class ExcludePackageTypeFilter implements TypeFilter , EnvironmentAware  {

    private Environment env;

    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
            throws IOException {

        boolean match = false;
        for (String activeProfile : env.getActiveProfiles()) {
            if (activeProfile.equals("dev")) {
                match = isClassInPackage(metadataReader.getClassMetadata(), env.getProperty("devExcludePackage"));
            } else if (activeProfile.equals("prod")) {
                match = isClassInPackage(metadataReader.getClassMetadata(), env.getProperty("prodExcludePackage"));
            }
        }
        return match;
    }

    private boolean isClassInPackage(ClassMetadata classMetadata, String pacakage) {
        return classMetadata.getClassName().startsWith(pacakage);
    }


    @Override
    public void setEnvironment(Environment environment) {
        this.env = environment;
    }
} 
Run Code Online (Sandbox Code Playgroud)

(2) 配置application.properties定义为不同的配置文件排除哪些包。

devExcludePackage  = com.example.prod
prodExcludePackage = com.example.dev
Run Code Online (Sandbox Code Playgroud)

(3) 将此过滤器应用于@ComponentScan:

@SpringBootApplication
@ComponentScan(excludeFilters = @ComponentScan.Filter(
                type = FilterType.CUSTOM, classes = { ExcludePackageTypeFilter.class }))
public class Application {


}
Run Code Online (Sandbox Code Playgroud)