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

Wrong bean factory method used when method names are the same in one @Configuration #25653

Closed
xak2000 opened this issue Aug 27, 2020 · 5 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: duplicate A duplicate of another issue type: bug A general bug

Comments

@xak2000
Copy link
Contributor

xak2000 commented Aug 27, 2020

When one @Configuration class have two bean factory methods with same name (but different arguments), then Spring creates both beans using only one of those factory methods.

Example:

@Configuration
public class Config {

    @Bean
    public String foo() {
        return "foo";
    }

    @Qualifier("printer1")
    @Bean(name = "printer1")
    public Printer printer1() {
        return new Printer1();
    }

    // This factory method overrides the method with the same name for both beans.
    // The result is context with 2 beans, each has own name and qualifier, but both created with
    // the same factory method (this method). Other factory method (printer1()) is ignored.
    // So, basically there are 2 Printer2 instances in the context.
    @Qualifier("printer2")
    @Bean(name = "printer2")
    public Printer printer1/* Here is the bug */(String foo) {
        return new Printer2();
    }


    public interface Printer {
        void print();
    }

    public static class Printer1 implements Printer {
        @Override
        public void print() {
            System.out.println("I'm Printer 1");
        }
    }

    public static class Printer2 implements Printer {
        @Override
        public void print() {
            System.out.println("I'm Printer 2");
        }
    }

}
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Bean
    ApplicationRunner applicationRunner(List<Config.Printer> printers) {
        return args -> printers.forEach(Config.Printer::print);
    }

}

This prints:

I'm Printer 2
I'm Printer 2

If you try to inject qualified printer1 bean it also will print I'm Printer 2. So, basically the context will have 2 beans, each with own qualifier etc, but both will be created using second factory method.

The solution is to rename first or second factory method to any other name to be different from name of the other method (e.g. printer5). Splitting @Configuration to 2 configurations also works.

As @mdeinum mentioned here the problem can be with ConfigurationClassBeanDefinitionReader.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Aug 27, 2020
@jnizet
Copy link

jnizet commented Aug 27, 2020

This looks like a duplicate of #25263

@jhoeller
Copy link
Contributor

This looks like a duplicate of the recently fixed #25263 indeed. Please try the latest 5.3.0.BUILD-SNAPSHOT if you have a chance.

Generally speaking, please try to avoid using the same factory method names for different bean names. This is brittle since at a fundamental level, such same-named methods are overloaded methods in Java and should be treated as such.

@jhoeller jhoeller self-assigned this Aug 27, 2020
@xak2000
Copy link
Contributor Author

xak2000 commented Aug 27, 2020

Thanks! I understand that I should try to avoid same-named methods, and that it's a little contrived example. But still think that Spring should not behave like that. If it would print an error, it is totally acceptable. But silently use wrong factory method is not, IMHO. Can be source of strange bugs in end-user code.

I'll try the SNAPSHOT version, thanks!
The version I tested was 5.2.8.RELEASE.

@xak2000
Copy link
Contributor Author

xak2000 commented Aug 27, 2020

5.3.0-SNAPSHOT version fixes the issue. Feel free to close as duplicate then.

@jhoeller
Copy link
Contributor

jhoeller commented Aug 28, 2020

Thanks for trying the snapshot so quickly!
I forgot to mention that this will also be in 5.2.9 and is therefore also available in 5.2.9.BUILD-SNAPSHOT already.

Closing as a duplicate of #25263 then.

@jhoeller jhoeller added in: core Issues in core modules (aop, beans, core, context, expression) status: duplicate A duplicate of another issue type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Aug 28, 2020
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: duplicate A duplicate of another issue type: bug A general bug
Projects
None yet
Development

No branches or pull requests

4 participants