For our applications we use a self written auto configuration to create a /version endpoint for example. When migrating from Spring-Boot 2.7.6 to Spring-Boot 3.0.3 i followed the instructions provided by you

In the paragraph "Auto-configuration Files" you link to the newly introduced Auto-configuration Mechanism. I clicked on the link to get to the according Section in the 2.7-Release-Notes

There is a paragraph called New @AutoConfiguration Annotation that reccomends to use @AutoConfiguration at the top-level auto-configuration instead of @Configuration.

By doing so my /version endpoint no longer works as expected.

I want to provide some code for context:

Auto-Configuration-File

@Bean
@ConditionalOnProperty("teamstarter.add.version-endpoint")
public VersionController versionController() {
    return new VersionController(versionService());
}

@Bean
@ConditionalOnProperty("teamstarter.add.version-endpoint")
public VersionService versionService() {
    return new VersionService();
}

Version Service

```java /* * The version field contains the current version of the pom.xml / @Value("${teamstarter.version:unknown}") private String version;

/* * Obtains the value from the {@link #version version field} and returns it to the caller. * * @return Value of the {@link #version version field}. / public String getVersion() { return this.version; }


When using the old `@Configuration`-Annotation this works fine and the version from the application.yml is returned.
But when i use the new `@AutoConfiguration`-Annotation, it always returns null.

While Debugging i added 
```java
@PostConstruct
public void init(){
    System.out.println("Version in PostConstruct" + this.version);
}

and found out that the Bean with the Version set is created, but an other instance is used later in the Controller.

To me, this seems like a bug, or is this intentional behavior? If this behavior is intentional, should I continue to use @Configuration instead and what are the reasons for this behaviour?

Comment From: philwebb

The @AutoConfiguration annotation is meta-annotated with @Configuration so they should work in the same way. Could you please provide a sample application that replications the problem so we can try to get to the bottom of it.

Comment From: NicoStrecker

Where could i provide that ? @philwebb

Comment From: NicoStrecker

Spring-AutoConfiguration-Demo.zip Here is my Demo @philwebb

How-To:

Unpack zip mvn clean install auto-config-project mvn clean package demo project


Run demo Project and call localhost:8080/v1/version/ endpoint Should work


Change @Configuration to @AutoConfiguration in ProblematicAutoCofing class mvn clean install auto-config-project mvn clean package demo project


Run demo Project and call localhost:8080/v1/version/ endpoint Should not work now

Comment From: mhalbritter

The @AutoConfiguration is a @Configuration(proxyBeanMethods = false). In your autoconfiguration:

    @Bean
    @ConditionalOnProperty("app.add.version-endpoint")
    public VersionController versionController() {
        return new VersionController(versionService());
    }

this call to versionService() doesn't work with proxyBeanMethods = false. Rewriting it this way (which I recommend to always do):

    @Bean
    @ConditionalOnProperty("app.add.version-endpoint")
    public VersionController versionController(VersionService versionService) {
        return new VersionController(versionService);
    }

and it works.

Comment From: NicoStrecker

@mhalbritter Could you explain what the difference is between this two approaches?

Comment From: mhalbritter

When calling versionService() inside a @Bean method on a @Configuration(proxyBeanMethods = false), the instance returned by versionService() is not a Spring managed bean. That's why @Value isn't injected and is null. By using method parameter injection via versionController(VersionService versionService) the argument in VersionService versionService is managed by spring and the @Value has been injected.

It behaves the same when using @Configuration(proxyBeanMethods = true) (or just @Configuration, which defaults to true for proxyBeanMethods), because then Spring creates a CGlib-proxy for your configuration class and intercepts calls to versionService() and replaces the return value with a managed Spring bean. But this ONLY works when a proxy is created.

The method parameter injection (versionController(VersionService versionService)) works regardless of a proxy or not, and is much less "magic", therefore I favor this approach.

Comment From: NicoStrecker

Thank you a lot now i got it.