-
Notifications
You must be signed in to change notification settings - Fork 37.8k
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
JavaConfig Bean overriding with addition [SPR-10988] #15616
Comments
Phil Webb commented I am not really sure what you are asking here. Could you try to explain in a little more detail. Overriding |
Benoit Lacelle commented Considering a library providing some
to
By "Overriding I get the expected behavior if CCOnfig does not extends AConfig. Would this be a moreusual way of overriding? I tend to extends |
Jose Luis Martin commented I guess that problem is in ConfigurationClass.validate() method. The Configuration class obtained by inheritance (CConfig) has two overloaded methods, bean() and bean(List date). So validate() should report a BeanMethodOverloadingProblem and throw a BeanDefinitionParsingException. I tried to fix it replacing the code that checks for overloaded methods in validate() and seems to work, but MethodMetadata interface don't give access to the introspected method and there are dirty access to it casting to StandardMethodMetadata class.
Full commit is in chelu@c4e6895 |
Phil Webb commented Thanks for the information. That makes much more sense now. When I said:
I was thinking in the context of a single application, as you are talking about reuse of a common configuration provided by a shared library I can see why you would do this. In fact we do this ourselves with classes such as As Jose Luis Martin points out, the restriction on overloaded methods is intentional. One option that might work for you is to leave the @Configuration
public static class CConfig extends AConfig {
@Autowired
private List<Date> dateBeans;
@Bean
public Date anotherBean() {
return new Date();
}
@Bean
public Object bean() {
// can access this.dateBeans here
return "overriden";
}
} You could also make |
Benoit Lacelle commented Thanks for the details Phil. I'm not sure to understand one point: is it legit for a Anyway, if the override describe in this ticket is not legit, a fail-fast fix like the one from Jose Luis Martin would be much helpful. |
Phil Webb commented It is legal to override |
Jose Luis Martin commented Hi Phil I agree that work as designed but ConfigurationClass.validate() still is accepting a invalid configuration. As this bug is now Resolved, should I report a new bug for that? |
Phil Webb commented Jose Luis Martin, I think this one is getting a little cluttered so yes please, a new bug would be appreciated. |
Benoit Lacelle commented Thanks for your help. I was convinced bean overriding through method overloading was legal. Fact is the following overload works:
This is why I was confused about which bean overridings are legal and which ones are not. Jose, Should we take in account |
Phil Webb commented On further investigation is appears that overloaded bean methods are intended to work the way that you describe. It seems that the real problem may lie in the |
Benoit Lacelle commented Great Phil. Would you consider porting the fix in the 3.2 branch? |
Phil Webb commented Unfortunately I don't yet have fix. I am going to assign this one to Juergen Hoeller to take a look at. |
Jose Luis Martin commented I see... though I never would expect that a class will work differently depending on whether it was obtained through inheritance or not. (!) The List argument is not the only problem. As methods are ordered using AutowireUtils.sortConstructors(), overloading a bean method with a less arguments one will fail too. I think that this issue is related to #15620 because overloaded bean definitions are overriden by superclass too. |
Jose Luis Martin commented I'm a bit confused here because overloaded/overwriten methods are supposed to be supported by configuration classes but I have not found any code that handle it in the framework. I have done a new pull request trying add support for both features following the indications of javadoc of BeanMethodPolymorphismTests, ie choosing the most specifc method in the hierarchy. Instead of dealing with ConstructorResolver, I chose to assign the factory method to use at parsing time. The pull request has merged the changes that I proposed to #15620 because overloaded bean definitions are overriden by superclasses too. |
Phil Webb commented See also this comment from #15653. |
Juergen Hoeller commented As of 4.0 RC2, we use Spring's non-lenient constructor resolution mode for Since Juergen |
Benoit Lacelle commented Thanks Juergen! |
Jose Luis Martin commented Hi Juergen, I think that the fix is still ignoring inheritance rule pointed by javadoc in BeanMethodPolymorphismTests
The non-lenient constructor resolution mode will fail or pick the wrong method when overloading a bean method with the same or more number of arguments (already pointed here). For example,
will pick SuperConfig.aString(). Please, consider if the two test cases added to chelu/../BeanMethodPolymorphismTest should fail or not. |
Juergen Hoeller commented In my opinion, neither of the two new test cases should pass. Fundamentally, what we're designing here are regular Java classes, just with a special kind of factory method semantic. Overriding and overloading should work as usual, with the inheritance position of a newly overloaded method not being significant. In other words, except for the Java language override case where obviously the subclass position of a method is significant, it shouldn't matter whether a method is placed on a superclass or a subclass. A method invocation from a Java source file picks the best parameter type fit in an overloading scenario, no matter where the method is defined in the inheritance hierarchy; that's exactly what we're doing here as well. Note that this is substantially different from the scenario where a separate configuration class is being registered, overriding a formerly registered bean definition. In that case, the parameter signature of the factory methods involved is not significant since we're not within a Java class hierarchy. We are rather defining an overriding order for several indiviudally registered configuration classes, just like in the case of several XML bean definition files containing a bean with the same name. So a split into separate configuration classes without inheritance may be one way out for a scenario like yours. Another one would be a superclass method signature that accepts all potentially needed arguments, with the superclass variant itself not making full use of it. Or, as suggested above, access to certain dependencies via One more note: This is about as far as we can go for 3.2.x in any case. Any far-reaching changes to configuration class semantics would have to be a 4.x feature only. However, as noted above, I do not actually believe that we need to bend those semantics any further; the closeness to regular Java method processing is a key feature in its own right. Juergen |
Jose Luis Martin commented Hi Juergen. Thanks for your attention.
Wonderful!, That was my first point of view, but note that the framework is not actually following it. (see my comments on #15653). Although I totally agree with your explanation above, I'm still not sure that current fix solve the problem because to be consistent, for overloaded methods, the bean definition registered at parsing time and the factory method picked at instantiation time should match. (Please, see #15620). |
Juergen Hoeller commented Indeed, that validation step is inaccurate then... It reflects a sort of half-baked guidance that we might be better off just removing. As for the bean definition metadata, indeed, that's not necessarily picked from the actual method used at runtime. I'm going to review what we can do there. We could also insist on all same-named This work will probably only happen for 4.0, though. With 3.2.5, we're really just trying to fix the obvious - like a subclass Juergen |
Benoit Lacelle opened SPR-10988 and commented
I consider injection of beans as a List of automatically detected beans: I introduce several beans implementing the same interface and inject all of them as a List in a later bean.
I've not been able to find official documentation related to this feature. My single source is http://www.coderanch.com/t/605509/Spring/Java-config-autowired-List
Consider this feature, I have an issue with Bean overring: I would like to override a bean defined throught a no-arg method with a bean defined with the List of detected beans. However, spring behave like the second bean definition does not exist.
It can be reproduced with the following test:
If this is an expected behavior, how can I achieve such an overriding?
I asked the same question on SOF: http://stackoverflow.com/questions/19377789/javaconfig-bean-overriding-failing-with-list-injected
Thanks
Affects: 3.2.3
Issue Links:
@Bean
methodsReferenced from: commits b093b84, b00c31a, 78c10cd
0 votes, 5 watchers
The text was updated successfully, but these errors were encountered: