'BeanCurrentlyInCreationException when @Autowired and @Bean are present in same class

@Configuration
public class Test1 {

    @Autowired
    private Test3 test3;

}

@Configuration
public class Test2 {

    @Autowired
    private Test3 test3;

    @Bean(name = "test3 ")
    Test3 test3 () {
        return new Test3(); 
    }
}

The above code gives the following error.

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'test1': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private Test3 com.package.name.Test1.test3;

nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'test2': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private Test3 com.package.name.Test2.test3;

nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'test3': Requested bean is currently in creation: Is there an unresolvable circular reference?

How is this an example of circular dependency? If it is, any ideas on resolving this.



Solution 1:[1]

You don't need to autowire a bean defined in the same class since you can just reference that bean directly by calling the initialising method test3().

@Configuration
public class Test2{

    @Bean(name = "test3 ")
    Test3 test3 () {
        return new Test3(); 
    }

    public void exampleOfUsingTest3Bean() {
        System.out.println("My test3 bean is" + test3().toString());
    }
}

And, indeed, you should not do what you were trying to do since @Autowired fields are injected into a class on construction of the class and at this point no bean called Test3 exists because it is defined by a method of the class being constructed. Theoretically you could define this @Bean method to be static and it should be available to autowire but you shouldn't do this.

@Bean(name = "test3 ")
public static Test3 test3 () {
    return new Test3(); 
}

Solution 2:[2]

I'm not sure what is the use case for such a configuration. I usually do not use autowiring in the java configuration classes.

@Configuration annotated classes are beans by themselves so spring creates a bean that represents 'Test1'...

So, following your example:

@Configuration
public class Test1 {

    @Autowired
    private Test3 test3;

}

@Configuration
public class Test2 {

    @Autowired
    private Test3 test3;

    @Bean(name = "test3 ")
    Test3 test3 () {
        return new Test3(); 
    }
}

I'll start with Test2 bean. So you create a bean for Test3, fine, but then why do you autowire it as a data field on class Test2? I see only one possible reason for it: you have other beans that want to use this Test3 bean. In this case you can do the following:

Option 1

@Configuration
public class Test2 {

  
    @Bean(name = "test3 ")
    Test3 test3 () {
        return new Test3(); 
    }

    @Bean
    public SomeOtherBean someOtherBean() {
       return new SomeOtherBean(test3()); 
    }

    @Bean
    public YetAnotherBean yetAnotherBean() {
       return new YetAnotherBean(test3()); 
    }
}

Note that test3() is called twice here, yet the same instance of Test3 will be returned (because Test3 is a singleton). This is one of those 'magical' places in spring (technically it wraps the @Configuration annotated classes into smart proxies, but its beyond the scope of the question).

Option 2

@Configuration
public class Test2 {

  
    @Bean(name = "test3 ")
    Test3 test3 () {
        return new Test3(); 
    }

    @Bean
    public SomeOtherBean someOtherBean(Test3 test3) {
       return new SomeOtherBean(test3); 
    }

    @Bean
    public YetAnotherBean yetAnotherBean(Test3 test3) {
       return new YetAnotherBean(test3); 
    }
}

Here, note the dependency on these beans.

Now, to continue with Test1: if you have another configuration file (Test) - again I assume you would like to inject this Test3 bean somewhere into the beans defined in this Test1 configuration class. Obviously the first aforementioned option is not available to you because it just won't compile, however you can easily use the second option.

So bottom line, in my personal opinion, you should not consider classes annotated with @Configuration as real classes, but rather a very restricted DSL (that happened to obey java syntax) that will allow bean definitions. So currently in my projects when I work with @Configuration classes I use @Autowired probably only in Tests.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Plog
Solution 2 Mark Bramnik