-
Notifications
You must be signed in to change notification settings - Fork 38.4k
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
Bean Configuration Overriding [SPR-5509] #10181
Comments
Chris Beams commented Slating for review during the 3.2 timeline, when a number of other issues related to bean visibility and overriding will be addressed. |
Chris Beams commented #12637 also suggests an 'override' attribute but with conflicting semantics. |
Neale Upstone commented Looking forward to seeing this in 4 (and it would be worthy of a 4.0 release, to see the end of bean override gotchas). Here's what I've just somehow done in a haze when migrating towards Java Config from XML. I (sleepily) replaced
with:
Where CacheConfig is:
And what I got was that I can boot up a context with CacheConfig.class directly, but when I referenced the bean from the XML it failed, because I'd typed id="cacheManager" when I meant id="cacheConfig" (and in fact would be wiser leaving it out). Default bean definition behaviour of requiring override="true" (or And this was a simple one to resolve ;) |
Bulk closing outdated, unresolved issues. Please, reopen if still relevant. |
Ben Rowlands opened SPR-5509 and commented
Overview
Spring provides a powerful mechanism to "pull" (inherit) configuration from a "parent" configuration. Sometimes it would be convenient to "push" (override) configuration onto a target bean or replace the bean definition entirely using a single consistent mechanism.
We see 2 main use-cases for configuration overriding:
Use-Case A
When running an integration style test we find we need to override properties or even entire beans in the production configuration to allow tests to run quickly by swapping out real resources with mocked or faked implementations.
Use-Case B
Frameworks built on top of Spring often ship with some 'default' configuration. Applications using this framework import the default configuration into their own configuration to get the framework setup. If these defaults need to be tweaked the only practical option is often to copy & paste the framework configuration and update the required property(s). It is preferable for the Application importing the defaults to be very specific and only override the specific properties it needs to rather than copying the entire config and avoiding getting future changes to the defaults. A real world example of this can be found in our own runtime framework. It manages Application caches in a cache manager configured by the framework defaults. Often Applications want to customize the cache manager, for example, to tweak the size of the thread pool used to keep caches refreshed.
Details
Applications can be designed up front for overriding by using ${} placeholders however this is not always convenient and can obscure the configuration. In other cases the PropertyOverrideConfigurer can help but this requires the overrides be placed in a separate properties file. Spring also provides the ability to re-define beans by putting a bean with the same name in a later configuration file. Together these techniques can solve most, if not all, use-cases however individually they confuse and scatter the overrides. If united into a single mechanism it would allow a consistent approach and central location to define these overrides.
Examples of overriding features we use
1 and 2 represent the 80-90% case.
It is possible to implement these features in an ad-hoc fashion using a custom BFPP to implement the overriding. However we feel a more natural, integrated and standard solution to express the overriding intent in a first class way would be generally useful in Spring. Some ideas on possible approaches to give more background are:
XML Syntactic Sugar
This is interpreted as "foo" in Config#2 redefines and overrides "foo" from Config#1. This isn't possible with the current implementation since bean definitions with the same name replace previous bean definitions so once Config#2 is read the original 'foo' is lost.
This is interpreted as "+" (add) the configuration to the bean definition for "foo". This is unlikely to be a general solution since it would break backwards compatibility, but gives an example of what a custom BFPP could do.
This explicitly "overrides" the configuration for "foo".
With both these approaches it isn't clear how to remove configuration - they can only add properties (replacing any previous properties). An additional property attribute or special value could be used to declare that the property should be removed from the definition. Its not clear if this is a real limitation.
Java code
Java is the most powerful and natural mechanism to override beans. For example, if the original configuration was expressed using Spring JavaConfig it would just a case of overriding the method and calling super if required:
Most configuration is currently expressed in XML so bridging the gap and allowing Java to override selected beans definitions would provide a powerful mechanism. Its not clear if the bean-instance (easiest to work with) or bean-definition (most powerful) should be given to the overriding method. For example, all these overrides could be expressed as methods in a class:
The AbstractBeanDefinition API can be cumbersome to use, especially when dealing with collections and bean references. For some use-cases it may be sufficient to work with the concrete bean-instance, a factory pattern like that used in the Scope API would allow for the XML bean definition to be completely ignored if required:
Both Java approaches work cleanly with the testing use-case since a single test class can define both the test logic and test overrides, rather than spreading these throughout multiple files.
Issue Links:
@Bean
methods to override definitions in XML27 votes, 29 watchers
The text was updated successfully, but these errors were encountered: