Stepan Koltsov opened SPR-8396 and commented
public class AutowireOverrides {
public static class TheBean {
@Autowired
@Value("from property")
public void setBla(String value) {
System.out.println("setBla: " + value);
}
}
@Configuration
public static class ContextConfiguration {
@Bean
public TheBean theBean() {
TheBean r = new TheBean();
r.setBla("from @Bean");
return r;
}
}
public static void main(String[] args) {
new AnnotationConfigApplicationContext(ContextConfiguration.class);
}
}
Obviously outputs
setBla: from @Bean
setBla: from property
and property specified in @Bean
method has lower priority.
Requesting a @Bean
(properties=...) attribute, so theBean() declaration could be written as:
@Bean(
properties={
@Property(name="bla", value="from @Bean")
}
)
public TheBean theBean() {
return new TheBean();
}
In this case Spring would call setBla only once with "from @Bean
" parameter value.
Assume HttpServer library class with @Autowired
threadPool property. I cannot declare two HttpServer instances that use different thread pools in the same application (without disabling autowire, switching to xmlconf etc).
Affects: 3.1 M1
Attachments: - mylyn-context.zip (10.84 kB)
Issue Links:
- #20752 Support for autowire-candidate with @Bean
1 votes, 4 watchers
Comment From: spring-projects-issues
Chris Beams commented
Hi Stepan,
It's probably not terribly common to declare @Bean
methods returning types that are also annotated for autowiring (with @Autowired
, @Inject
, @Value
, etc). However, it's reasonable to consider providing support that would meet your needs.
For a number of reasons, it probably won't take the shape that you've described above, but we could consider something like the following:
@Bean(enableAutowiring=false)
public TheBean theBean() {
TheBean r = new TheBean();
r.setBla("from @Bean");
return r;
}
The enableAutowiring
attribute would be true
by default, meaning that @Autowired
, @Value
injection would occur in addition to any properties set within the @Bean
method. However, if explicitly disabled, the bean would no longer be a candidate for such injection by AutowiredAnnotationBeanPostProcessor
.
We'll review this for 3.1 and see if makes the cut.
Comment From: spring-projects-issues
Chris Beams commented
It will also be important to distinguish any such new attribute from the existing Bean#autowire attribute, which controls 'automagic' by-name/by-type autowiring, which is wholly different than annotation-config style autowiring. The former is already off (Autowire.NO) by default because it's generally discouraged; the latter is enabled by default, and implementing this request would provide the user with a way to disable it on a per-@Bean
basis.
Comment From: spring-projects-issues
Stepan Koltsov commented
Chris, I still want other bean properties to be autowired (as in XML conf).
Comment From: spring-projects-issues
Chris Beams commented
Hi Stepan,
Could you clarify a bit further? Are you saying that you want by-name/by-type autowiring to occur for this bean (that's what "as in XML conf" sounds like to me); or are you saying that you still want @Autowired
/@Value
injection to occur for this bean (for all except the 'bla' property in question)?
Comment From: spring-projects-issues
Stepan Koltsov commented
Chris,
Yes, I still want both @Autowired
, @Value
injection and by-name/by-type autowiring (if @Bean
(autowire=BY_...)) for all properties except for 'bla'.
Sorry for late answer.
Comment From: spring-projects-issues
Chris Beams commented
Hi Stepan,
After some consideration, resolving this as "Won't Fix" for now. There's seems to be no elegant way to achieve the kind of per-property disabling that you're looking for, and I'm afraid the nested annotation approach suggested with @Property
depends on stringified property names and probably adds more complexity to the @Bean
annotation than can be justified for a feature that won't likely be used by many.
If this emerges as a more common need, we can revisit it.
Comment From: spring-projects-issues
Juan commented
Hi,
Can we have this bit implemented?
@Bean
(enableAutowiring=false)
I have a "Generic abstract DAO" class which has this:
@Autowired
protected SessionFactory sessionFactory;
Implementations only specify the type of the entity being managed and that's it. It works great when there is only one DB and one session factory in the context (most of the time). But I have an app that connects to three different DBs, and I am not being able to use my generic DAO there. I can use @Qualifier
on the @Configuration
@Bean
method parameter to pick which session factory I want for each DAO, but Spring still tries to @Autowire
the sessionFactory on the DAO, at which point it errors out because there are three in the context.
I believe @Bean
(enableAutowiring=false) is a simple enough way of me telling spring: "it's getting complicated, let me take it from here".
In the mean time, I was able to work around the problem by returning a FactoryBean<...> from the @Bean
method in the @Configuration
class.
Thanks, Juan
Comment From: spring-projects-issues
David Česal commented
I would like to set @Autowired
to required=false when running JUnit tests. I've tried to hack AutowiredAnnotationBeanPostProcessor, but it wasn't working.
Comment From: spring-projects-issues
Yanming Zhou commented
I have encounter the same problem like Stepan Koltsov , currently workaround is mixing xml configuration. I'm vote for introduce a new @BeanPropertySource
like @TestPropertySource
for unit test
@Bean
@BeanPropertySource(properties = { "bla=from @Bean" })
public TheBean theBean() {
return new TheBean();
}
Comment From: jhoeller
We have no intention to introduce a dedicated mechanism for such disabling.
Our recommendation is rather to structure application components accordingly between constructor arguments and bean properties: Constructor arguments are effectively replaced in the @Bean
method body, potentially with a choice of several constructors, bypassing Spring's common constructor resolution (as with XML-defined beans) completely. Additional autowiring will still happen on the returned instance for bean properties and also for fields.
Alternatively, you may entirely go for constructor-based injection and declare the required autowired arguments as parameters on your @Bean
method, passing them into the target constructor programmatically. This is arguably cleaner since it all happens within a single factory method then, composing the target state from factory method parameters and local state as needed.