Skip to content

Consistent autowiring behavior for specifically typed injection points against loosely typed @Bean methods [SPR-14960] #19527

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

Closed
spring-projects-issues opened this issue Nov 29, 2016 · 2 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Nov 29, 2016

satish surabhi opened SPR-14960 and commented

I want to report somewhat similar issue reported here: #15673 , now we are noticing autowire failing intermittently at least on the versions I have tried : 3.2.14 and 4.1.7.RELEASE. Following are the test classes with unit test. The test fails with NoSuchBeanDefinitionException for at least 2 (random) out of 5 attempts.

public interface BarInterface {}

public class Bar implements BarInterface {}

public class Foo {
 @Autowired
 public Bar bar;
}

@Configuration
public class FooBarConfiguration {
    @Bean
    public Foo foo() {
        return new Foo();
    }
    @Bean
    public BarInterface bar() {
        return new Bar();
    }
}

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {FooBarConfiguration.class}, loader=AnnotationConfigContextLoader.class)
public class TestSpringConfiguration {

    @Test
    public void testSpringConfiguration() {
        System.out.println("config test");
    }
}

Reference URL: #15673

Issue Links:

Referenced from: commits 845dbf0, 66aeeed

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Nov 29, 2016

Juergen Hoeller commented

This is essentially a consequence of #19074: Depending on the particular runtime method order within a configuration class, a different bean may get initialized first... leading to different exceptions - or in your case, even to a different resolution outcome.

The root of all evil: The JVM does retain source declaration order in runtime reflection. As a consequence, Class.getDeclaredMethods() returns the methods in arbitrary order... even differening per JVM run, which is why you're seeing a random outcome for repeated runs.

To make things even more complicated, the bytecode in the class files does retain source declaration order. So if you're loading configuration class files through ASM, e.g. during classpath scanning, you will get a reliable initialization order... but not when you specify the .class directly like in your @ContextConfiguration, since we're using reflection there.

In your particular case, according to source declaration order, we'd initialize the foo bean first. The Bar injection point in that Foo class is not resolvable against the predicted types (return type declarations) of your bean definitions, so we unfortunately fail with a {NoSuchBeanDefinitionException}}. However, if we start initialization with the bar bean, we create it first and therefore know its specific instance type already... initializing foo next, resolving the Bar injection point against the known Bar instance type.

We generally try to provide predictable resolution behavior independent from the bean declaration order (see e.g. #19073). Let's see what we can do for your scenario, finding out about potential matches with loosely typed @Bean methods (which could match once their instance type is known) before failing with a NoSuchBeanDefinitionException.

Of course, the recommended solution is to declare Bar as return type of your bar method. We generally recommend to be as specific as you can there, and in particular as specific as your injection points need it to be.

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Dec 23, 2016

Juergen Hoeller commented

From my perspective, this is addressed along with #19074, with source-code declaration order consistently respected at runtime. We still can't predict @Bean implementation types before they're actually created, but at least we consistently succeed or consistently fail now.

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) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants