In spring boot it's possible to autowire custom objects with applicationContext.getAutowireCapableBeanFactory().autowireBean(object). This is really helpful.

But it's not working if the application is compiled as a native application. There is no error or exception but the object was not wired.

Example code here https://github.com/mhus/sample-spring-boot3/tree/additional_configurables

Interesting code are:

public class TryAutowireConfigurable {
    private TryAutowireOtherBean tryAutowireOtherBean;
    @Autowired
    public void setTryAutowireOtherBean(TryAutowireOtherBean tryAutowireOtherBean) {
        System.out.println("--- TryAutowireConfigurable: setTryAutowireOtherBean");
        this.tryAutowireOtherBean = tryAutowireOtherBean;
    }
    public boolean isAutowired() {
        return tryAutowireOtherBean != null;
    }
}

and the caller:

        System.out.println(">>> TryAutowireBaseBean: PostConstruct");
        var configurableObject = new TryAutowireConfigurable();
        applicationContext.getAutowireCapableBeanFactory().autowireBean(configurableObject);
        System.out.println("*** TryAutowireBaseBean: TryAutowireConfigurable autowired " + configurableObject.isAutowired());
        System.out.println("<<< TryAutowireBaseBean: PostConstruct");

I also add code to prove reflection is working for the object, important for native execution.

The result for mvn clean spring-boot:run is:

>>> TryAutowireBaseBean: PostConstruct
--- TryAutowireOtherBean: PostConstruct
--- TryAutowireConfigurable: setTryAutowireOtherBean
*** TryAutowireBaseBean: TryAutowireConfigurable autowired true
<<< TryAutowireBaseBean: PostConstruct

Autowire was successful (line 4) using autowireBean().

But with mvn -Pnative clean native:compile the output is:

>>> TryAutowireBaseBean: PostConstruct
*** TryAutowireBaseBean: TryAutowireConfigurable autowired false
<<< TryAutowireBaseBean: PostConstruct
>>> TryAutowireBaseBean: proveReflectionIsActive
--- TryAutowireOtherBean: PostConstruct
--- TryAutowireConfigurable: setTryAutowireOtherBean
*** TryAutowireBaseBean: TryAutowireConfigurable autowired true
<<< TryAutowireBaseBean: proveReflectionIsActive

Autowire was NOT successful (line 2) but the prove (line 7) shows that manual using of reflection will work.

Looks like something in AutowireCapableBeanFactory has a different behaviour if the application is compiled native.

Comment From: mhalbritter

Hello,

this is to be expected. To make native images work with Spring, the Spring AOT processing translates the bean context into code which removes most of the reflection. More can be read here.

When you invoke autowiring manually, you're working around that process.

Maybe it's possible to add runtime hints for your class so that the autowiring works, but this is nothing which is supported out of the box.

Comment From: mhus

Invoking autowiring in a JVM is working fine. Even for not AOT processed objects. And it is very helpful in a lot of cases. If it is not working in native mode it's a bug and not a 'feature' - in my view. The alternative to AOT is to use reflection even in native. But this seems not to work for some reasons.

In the example reflection hints already set and working for the autowired class.

Comment From: mhalbritter

If it is not working in native mode it's a bug and not a 'feature' - in my view

That's a limitation of the process we use to get Spring apps working in a native image. If you don't agree with it, you can create an issue on the Spring Framework bug tracker, the AOT engine has its home in the Spring Framework, not in Spring Boot.

The alternative to AOT is to use reflection even in native

Yes, that's currently the case if you try to manually invoke autowiring.

But this seems not to work for some reasons.

You can run your application with the GraalVM agent attached and look at the generated reflection config files. I guess you're missing some hints.