Skip to content
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

Support disabling @Autowired on a per-@Bean basis [SPR-8396] #13043

Closed
spring-projects-issues opened this issue Jun 3, 2011 · 10 comments
Closed
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Jun 3, 2011

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:

Issue Links:

1 votes, 4 watchers

@spring-projects-issues
Copy link
Collaborator Author

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.

@spring-projects-issues
Copy link
Collaborator Author

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.

@spring-projects-issues
Copy link
Collaborator Author

Stepan Koltsov commented

Chris, I still want other bean properties to be autowired (as in XML conf).

@spring-projects-issues
Copy link
Collaborator Author

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)?

@spring-projects-issues
Copy link
Collaborator Author

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.

@spring-projects-issues
Copy link
Collaborator Author

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.

@spring-projects-issues
Copy link
Collaborator Author

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

@spring-projects-issues
Copy link
Collaborator Author

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.

@spring-projects-issues
Copy link
Collaborator Author

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();
}

 

@spring-projects-issues spring-projects-issues added the type: enhancement A general enhancement label Jan 11, 2019
@spring-projects-issues spring-projects-issues added this to the 5.x Backlog milestone Jan 11, 2019
@rstoyanchev rstoyanchev added the in: core Issues in core modules (aop, beans, core, context, expression) label Jul 26, 2021
@jhoeller
Copy link
Contributor

jhoeller commented Jan 8, 2024

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.

@jhoeller jhoeller closed this as not planned Won't fix, can't repro, duplicate, stale Jan 8, 2024
@jhoeller jhoeller added the status: declined A suggestion or change that we don't feel we should currently apply label Jan 8, 2024
@jhoeller jhoeller removed this from the 6.x Backlog milestone Jan 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

3 participants