简体   繁体   中英

Why is an @Autowire null in a bean retrieved from ApplicationContext?

I have studied many other StackOverflow posts on Spring autowire issues. This question is not so simple as "don't expect @Autowire to work on an object you new ".

I have a library that constructs objects from class names. The object classes must extend class F. The library is not built with Spring. It accepts a class loader for resolving the class names. It is doing this:

     Class<?> someClass = Class.forName(className, true, classLoader);
     if (F.class.isAssignableFrom(someClass)) {
          Class<? extends F> fClass = (Class<? extends F>) someClass; 
          Constructor constructor = fClass.getConstructor(FMap.class, Object.class);
          F fobject = (F) constructor.newInstance(parameterMap, applicationContext);
      ...

The library allows some context to be passed in. Here I provide the Spring ApplicationContext. A particular subclass of F has code like this in its constructor:

    ApplicationContext applicationContext = (ApplicationContext)context;
    X xbean = (X)applicationContext.getBean("xbean");
    S sobject = new S(xbean);

Class X is defined like this:

    @Component
    public class X {

    private final Y ybean;

    @Autowired
    public X(Y ybean) {
        this.ybean = ybean;
    }
    ...

Class Y is another @Component.

The sobject is able to call a method in the xbean (xbean is not null), but the ybean is null. Why?

I thought that Spring constructed and wired up the @Components at application start time. I expected that using an object from ApplicationContext would give me a completely built and wired up object.

Updates 06/03/2020 I added an @PostConstruct as suggested in the first answer. That showed that the object is getting constructed early in the life of the application.

I tried disabling spring.devtools.restart.enabled with no change in behavior.

I tried disabling spring.main.lazy-initialization with no change in behavior.

I removed spring-boot-devtools from my build.gradle with no change in behavior. However, the class loader being reported when the F objects and the Y bean are constructed is sun.misc.Launcher$AppClassLoader

We are running org.springframework.boot:spring-boot-starter-web:2.2.6.RELEASE.

Your class Y will only be autowired, when it is also present in Springs' application context. Verify that you actually have your component scan configured so that it picks up your Y component. you can quickly verify this by adding a post consturct snippet to Y.

@PostConstruct
void init() {
   logger.info("Here I am");
}

If your logger prints nothing, Y is definitely not loaded into the application context.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM