1

I am aware of calling @Bean annotated methods from within a @Configuration as already discussed.

But I don't understand why it doesn't work when the bean is overwritten.

I have a legacy class, which I can't modify. It's a configuration and a business bean at the same time. This is a simplified version:

@Configuration
public class MyBean {

    String someMethod() {
        return otherBean() + "|" + otherBean();
    }

    int called = 0;

    @Bean
    Object otherBean() {
        return called ++;
    }
}

Inside the someMethod() the factory method otherBean() is called two times and as far as annotated with @Bean the instance should be gotten from the Spring context and therefore should the actual code return called ++; be called only once. Expected output from the someMethod() should be always 0|0 and it is so indeed in the production.

Trouble comes when I am about to redefine the bean in a unit test:

@SpringJUnitConfig//(MyBean.class)
public class BeanTest {

    @Autowired
    MyBean myBean;

    @Test
    void testIt() {
        assertEquals("0|0", myBean.someMethod());
    }

    @Configuration
    static class TestConfig {    

        @Bean
        MyBean myBean() {
            return new MyBean();
        }
    }
}

The reason could be some additional settings of the MyBean instance in the test (not included in the snippet above).

Now, calling myBean.someMethod() returns 0|1 instead of 0|0.

Everything works again (result is 0|0), when the TestConfig configuration is removed and configuration of the test context is set as @SpringJUnitConfig(MyBean.class).

What's different in registering the bean in the test?

Barney
  • 797
  • 1
  • 11
  • 20

1 Answers1

4

The "magic" of proxying method calls annotated with @Bean and returning instances from the Spring context happens only in configuration beans (like here: @SpringJUnitConfig(MyBean.class)).

But when you create a new instance as return new MyBean(), the @Configuration annotation is ignored and the object is registered as a normal bean (@Bean MyBean myBean()) but not a configuration. That's why the methods calls otherBean() create always a new instance.

ttulka
  • 10,309
  • 7
  • 41
  • 52