-
Notifications
You must be signed in to change notification settings - Fork 41.1k
Consider providing recommendation for override/replace beans usecase #18228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I'm not sure we have clear guidelines ourselves when it comes to these more complex scenarios. Generally speaking Without knowing the details of your specific use-case, it's very hard to offer general advice. It also feels like something that's quite unusual for a typical Spring Boot user to do (so we don't want to add a section to the reference documentation). We've tried to document that Your |
We create a library that multiple service applications use. The "common-library" provides implementation classes and configurations, such as followings:
Each service application team can use common-library to their applications, and choose Here is our usecase for bean override. For example, Another example is in In addition to bean override, ideally, I would like to use While writing this, an idea I came up is to make I believe writing such library is not something special; rather it is very typical especially in this microservice era. There are many applications within organization that share common code/infra/setup. From such library perspective, I think here is the things would be nice to have:
Thanks, |
Closing following the discussion in #19400 (comment) |
@philwebb Regarding that "@conditional...` annotations should only be used with auto-configuration classes, but unfortunately some users still use them incorrectly." Is this still true in 2024? I'm trying to find any mention in the documentation but I am failing to do so |
@nightswimmings There are some notes in the javadoc. For example Lines 53 to 56 in c1fcce4
|
@philwebb Thanks!! So is the consideration something that applies only to particular conditions that work especially then? |
@nightswimmings As a general rule, we recommend not using any Having said that, conditions such as |
Since spring-boot 2.1, bean overriding is disabled by default.
I think this is very reasonable and protects from unknowns by preventing hidden bean overriding.
However, time to time, there is a need to override beans.
It would be great to have the best practice/guideline for handling such use cases.
Background:
I write a library which is used by multiple service applications. The library is written on top of spring-boot and provides
@Enable...
annotations.Typically we create
@Enable...
annotations rather than creating auto configurations.This is a decision that we want to explicitly turn on/off features in service rather than auto-magically happen via auto configuration.
The issue is that sometimes services want to override some beans defined in library.
If we provide auto configuration, we can use
@ConditionalOn...
annotations since it is guaranteed to be evaluated after all@Configuration
classes are processed byAutoConfigurationImportSelector
.However, since we use
@EnableX
, there is no distinction for@Configuration
classes whether they are from library's or from application's while processing configuration classes.Therefore, due to the component scan is not deterministic to process configuration classes, we cannot reliably use
@ConditionalOnX
annotations because the configuration class processing order might change.One approach is I can write a custom import-selector that makes sure all library configurations are processed after application's configurations but before auto configurations. This could allow library configurations to use
@ConditionalOn
annotations. However, it is a bit of too much in custom framework and even writing a custom import-selector, we also need to@EnableAutoConfiguration
equivalent to bring in the custom import-selector to be in effect on application.We also want to avoid using
@Primary
defined in application configuration in order to override beans in library. This is because@Primary
bean may have impact writing tests in application.Instead, an approach I chose was using
BeanFactoryPostProcessor
and unregister bean definitions that I want to override.This is so far working good(with limited usage), since the post processor is called after all configurations are processed(including auto configuration) but before instantiating beans. The drawback is bean-name based injection will have a problem but typically beans are injected by type.
I have seen people use
@ConditionalOn[Bean|Class]
on non autoconfiguration classes(with component scan). Mostly, people don't realize the fragility of@ConditionalOnX
annotations.Simply, it is working in their current environment, so that they think it is ok to use.
From library/framework development perspective, one suggestion is that spring-boot to provide a mechanism to guarantee certain configuration classes to be processed after normal configurations but before auto configurations. For example, provide a means to list up such configuration classes in
spring.factories
with certain key(which is pretty similar to what autoconfiguration do), then defer the configuration processing right before autoconfigurations.Another way would be making
allow-bean-definition-overriding
flag to be per bean definition. Currently, this is abeanFactory
level switch. However, if it is down to per bean definition level, it can fine control what beans to be overridable. (maybe too much granularity)It's my feedback about bean overriding usecase.
It is common that people create own framework/library on top of spring/spring-boot in order to share their architecture/infrastructure to applications. So it is nice to have some level of support in spring-boot for developing library on top.
Also, it would be great if you could provide some clear guideline for bean override dos and donts, blog post, documentation, some support in framework(spring or spring-boot), etc.
Thanks,
References:
spring-projects/spring-framework#15434
spring-projects/spring-framework#19229
The text was updated successfully, but these errors were encountered: