Getting Exception while creating beans using @Bean Spring annotation

CuriousMind :

I was trying to understand difference between @component and @Bean in Spring framework, and referred to this SO question.

Based on the answer, I got a fair understanding, and tried to reinforce the concept by implementing a simple example (to check whether I really understood the concept).

The below is the code which I wrote. I wanted to see @Bean for "third party" libs (so that it can be instantiated using @Bean annotation)

package com.example.thirdparty.code;

public class ThirdPartyUtil {

    public ThirdPartyUtil() {
    }

    public void print(String str) {
        System.out.println("String passed is --> " + str);

    }
}

In above, I tried to simulate a "third party lib/class - NON spring" which isn't a spring based (and so there won't be any @component in that class.

Now, below is the main application which I created:

package com.example.spring;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import com.example.thirdparty.code.ThirdPartyUtil;

@Configuration
@ComponentScan(basePackages = { "com.example.spring" })
@Component
public class SpringBasedMainApp {

    @Autowired
    private ApplicationContext ctx;

    @Autowired
    private static ThirdPartyUtil thirdPartyUtil;

    @Bean
    public ThirdPartyUtil beanThirdPartyUtil() {
        try {
            Class c = getClass().getClassLoader().loadClass("com.example.thirdparty.code.ThirdPartyUtil");
            return (ThirdPartyUtil) ctx.getBean(c);
        } catch (ClassNotFoundException e) {
            throw new IllegalArgumentException("Exception");
        }
    }

    public static void main(String[] args) {

        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringBasedMainApp.class);

        System.out.println("thirdPartyUtil is " + thirdPartyUtil);

    }
}

I was hoping that using @Bean annotation, it would create ThirdPartyUtil as Spring bean, and then inject using @Autowired into field thirdPartyUtil.

However, when I run this program, I got altogether a surprising exception, listed below:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'beanThirdPartyUtil' defined in com.example.spring.SpringBasedMainApp: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.thirdparty.code.ThirdPartyUtil]: Factory method 'beanThirdPartyUtil' threw exception; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanThirdPartyUtil': Requested bean is currently in creation: Is there an unresolvable circular reference?
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:627)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:456)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1288)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1127)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:846)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546)
    at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:88)
    at com.example.spring.SpringBasedMainApp.main(SpringBasedMainApp.java:41)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.thirdparty.code.ThirdPartyUtil]: Factory method 'beanThirdPartyUtil' threw exception; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanThirdPartyUtil': Requested bean is currently in creation: Is there an unresolvable circular reference?
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:622)
    ... 14 more
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanThirdPartyUtil': Requested bean is currently in creation: Is there an unresolvable circular reference?
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:339)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:215)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:224)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1112)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:407)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:341)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:335)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1101)
    at com.example.spring.SpringBasedMainApp.beanThirdPartyUtil(SpringBasedMainApp.java:33)
    at com.example.spring.SpringBasedMainApp$$EnhancerBySpringCGLIB$$d93c67f4.CGLIB$beanThirdPartyUtil$0(<generated>)
    at com.example.spring.SpringBasedMainApp$$EnhancerBySpringCGLIB$$d93c67f4$$FastClassBySpringCGLIB$$9349d69b.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363)
    at com.example.spring.SpringBasedMainApp$$EnhancerBySpringCGLIB$$d93c67f4.beanThirdPartyUtil(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
    ... 15 more

I didn't understand why it is giving this exception. I am creating an applicationContext using AnnotationConfigApplicationContext and passing the necessary details to it.

I expected it to work, however got the above exception (which I have seen maiden time).

Can anyone help why this exception came and is my understanding not correct about @Bean. Thanks for your time and help in advance.

JB Nizet :

The goal of the @Bean annotation is to annotate a method whose responsibility is to create an object, that will then be registered as a bean by Spring.

But inside your method, you ask Spring (using ctx.getBean()) to give you the bean that you're currently creating. So you get that exception.

Here's what your methd should look like:

@Bean
public ThirdPartyUtil beanThirdPartyUtil() {
    return new ThirdPartyUtil();
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=148565&siteId=1