I am using springboot 2.3.5.RELEASE, have one BeanFactory to load prototype beans implements one interface. One has a bean to be autowired, another doesn't have the bean.

    @Bean
    @Scope(value = "prototype")
    public DemoInterface getDemoBean( int i) {
        switch ( i) {
            case 1: return new DemoClassOne();
            case 2:
            default:
                return new DemoClassTwo();

        }
    }
public class DemoClassOne extends AbstractDemoClass {
    @Autowired
    Bean2BeAutowired bean2BeAutowired;
}
public class DemoClassTwo extends AbstractDemoClass {
}

If I load BeanOne first, the bean2BeAutowired works fine, but after I load another bean, then generate bean one, the bean2BeAutowired will be null.

    @Test
    void contextLoads() {
        DemoInterface a1 = ctx.getBean(DemoInterface.class, 1);
        System.out.println( a1);
        System.out.println( "bean2BeAutowired is ok: "+((DemoClassOne)a1).bean2BeAutowired);

        DemoInterface a2 = ctx.getBean( DemoInterface.class, 2);
        System.out.println( a2);

        DemoInterface a3 = ctx.getBean( DemoInterface.class, 1);
        // ctx.getAutowireCapableBeanFactory().autowireBean( a1);
        System.out.println( a3);
        System.out.println( "bean2BeAutowired is null: "+((DemoClassOne)a3).bean2BeAutowired);
    }

The output is:

com.example.demo.DemoClassOne@7561db12
bean2BeAutowired is ok: com.example.demo.Bean2BeAutowired@3301500b
com.example.demo.DemoClassTwo@15deb1dc
com.example.demo.DemoClassOne@6e9c413e
bean2BeAutowired is null: null

It means after I load bean2, the bean1 will not autowired bean2BeAutowired. The demo code is attached.

demo.tar.gz

Comment From: wilkinsona

Thanks for the sample. It's a bit more complicated than it needs to be to reproduce the problem. Your subclass of DefaultListableBeanFactory is also quire unusual and isn't necessary. Here's a single file variant that has the same behaviour while removing the use of Spring Boot and the custom BeanFactory:

package com.example.demo;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = DemoApplication.class)
class DemoApplicationTests {

    @Autowired
    ApplicationContext ctx;

    @Test
    void contextLoads() {
        DemoInterface a1 = ctx.getBean(DemoInterface.class, 1);
        System.out.println( a1);
        System.out.println( "bean2BeAutowired is ok: "+((DemoClassOne)a1).bean2BeAutowired);

        DemoInterface a2 = ctx.getBean( DemoInterface.class, 2);
        System.out.println( a2);

        DemoInterface a3 = ctx.getBean( DemoInterface.class, 1);
        // ctx.getAutowireCapableBeanFactory().autowireBean( a1);
        System.out.println( a3);
        System.out.println( "bean2BeAutowired is null: "+((DemoClassOne)a3).bean2BeAutowired);
    }

}

class DemoClassOne extends AbstractDemoClass {

    @Autowired
    Bean2BeAutowired bean2BeAutowired;

}

class DemoClassTwo extends AbstractDemoClass {

}

interface DemoInterface {

}

class AbstractDemoClass implements DemoInterface {

}

@Configuration
@ComponentScan
class DemoApplication {

    @Bean
    @Scope(value = "prototype")
    public DemoInterface getDemoBean( int i) {
        switch ( i) {
            case 1: return new DemoClassOne();
            case 2:
            default:
                return new DemoClassTwo();

        }
    }

}

@Service
class Bean2BeAutowired {

}

As the problem occurs without Spring Boot's involvement, we'll transfer this to the Framework team so that they can take a look.

Comment From: jhoeller

This seems to be (yet another) regression caused by the InjectionMetadata.EMPTY optimization in 5.2... in this particular case, caused by the previous fix #24485. I'll refine this once more for 5.3.1 and 5.2.11, hopefully for good this time.