0

I'm using next configuration:

@Configuration
@Import({ClientConfig.class})
public class ValidatorsConfiguration {}

ClientConfig is a library class with some configuration like:

@Configuration
public class ClientConfig {

    @Bean
    public Parser parser() {
        return new Parser();
    }

    @Bean
    public Validator validator() {
        return new Validator();
    }
}

This lib configuration can contain a lot of beans and I want to exclude some beans from initialization. How I can Do it? I use XML component scan like:

    <context:component-scan base-package="com.spring.my">

to scan ValidatorsConfiguration. How I can exclude some specific @Bean annotated beans in library configuration ?

UPD: Some clarification - I can't edit library code. I use ClientConfig as dependency

Roman C
  • 49,761
  • 33
  • 66
  • 176
Valeriy K.
  • 2,616
  • 1
  • 30
  • 53

3 Answers3

0

I assume that you would like to include the beans only if some "business feature" is available. For example, you want to load a bean which is a DB driver only if this db is available at runtime.

Consider putting @ConditionalOnProperty annotation on the beans to be included / excluded: You'll end up with something like this:

@Configuration
public class ClientConfig {

    @Bean
    public Parser parser() {
        return new Parser();
    }

    @Bean
    @ConditionalOnProperty(name="validator.enabled", havingValue="true", matchIfMissing=false)
    public Validator validator() {
        return new Validator();
    }
}

In this example, the Validator bean will be loaded only if you've defined in the application.yml the following property

validator:
  enabled: true

Its also possible to put the bean on the entire configuration so that if you have a many inter-connected beans that make sense to load only together (or exclude them all):

@Configuration
@ConditionalOnProperty(name="client.enabled", havingValue="true", matchIfMissing=false)
public class ClientConfig {

    @Bean
    public Parser parser() {
        return new Parser();
    }

    @Bean   
    public Validator validator() {
        return new Validator();
    }
}

@Conditional-s are flexible mechanism, so if you don't want to rely on properties consider using other conditionals or even roll your own.

Update: Based on op's comment:

Without changing the configuration itself, the only way I can think of is implementing a BeanFactoryPostProcessor that can dynamically exclude the bean definition from the Application Context based on the custom logic. But I think its a fragile and error-prone way to work, so I wouldn't have done something like that in a real project.

The idea is simple: Bean Factory Post Processor runs before the beans actually get loaded and based on your logic (that you should implement), will remove the bean definitions populated from the configuration by spring during the start-up. Check this link for example, it shows how to remove the bean

Mark Bramnik
  • 39,963
  • 4
  • 57
  • 97
0

You can use exclusion filters:

<context:component-scan base-package="com.kb.componentscan_filters">
<context:exclude-filter type="regex" expression=".*service.*"/>
Hopey One
  • 1,681
  • 5
  • 10
0

You can't exclude the particular beans that are part of the library as long as the configuration class is not editable.

What you can do is to exclude the configuration class itself:

@SpringBootApplication
@ComponentScan(
    basePackages = { 
        "com.company.app" 
    }, 
    excludeFilters = { 
        @ComponentScan.Filter(
            type = FilterType.ASSIGNABLE_TYPE, 
            value = { ClientConfig.class }
    )
})
public class Application { }

Be careful: all beans defined in ClientConfig will be excluded so if you need some of them, you must redefine them again.

Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183