Skip to content

AutowireCapableBeanFactory.createBean does not prefer default constructor anymore #30041

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Artur- opened this issue Feb 27, 2023 · 4 comments
Closed
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: regression A bug that is also a regression
Milestone

Comments

@Artur-
Copy link
Contributor

Artur- commented Feb 27, 2023

With a project from start.spring.io.

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import jakarta.annotation.PostConstruct;

@SpringBootApplication
public class DemoApplication {

	public static class Base {
		public Base() {
			System.err.println("Class of type " + getClass().getSimpleName() + " created");
		}

		public Base(Base[] otherBases) {
			this();
			System.err.println("This constructor should not run");
		}
	}

	@Component
	@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
	public static class Other extends Base {
	}

	@Autowired
	private ApplicationContext context;

	@PostConstruct
	public void init() {
		Base object = context.getAutowireCapableBeanFactory().createBean(Base.class);
		System.err.println("Bean factory returned bean of type " + object.getClass().getSimpleName());
	}

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

}

Expected output, as with version 6.0.4 / Spring Boot 3.0.2

Class of type Base created
Bean factory returned bean of type Base

Actual output with 6.0.5 / Spring Boot 3.0.3

Class of type Other created
Class of type Base created
This constructor should not run
Bean factory returned bean of type Base
@Artur-
Copy link
Contributor Author

Artur- commented Feb 27, 2023

Probably related to #29855 by @jhoeller

@sbrannen sbrannen added type: regression A bug that is also a regression in: core Issues in core modules (aop, beans, core, context, expression) labels Feb 27, 2023
@jhoeller jhoeller removed the status: waiting-for-triage An issue we've not yet triaged or decided on label Feb 27, 2023
@jhoeller jhoeller self-assigned this Feb 27, 2023
@jhoeller jhoeller added this to the 6.0.6 milestone Feb 27, 2023
@jhoeller jhoeller changed the title Extra beans created with 6.0.5 AutoWireCapableBeanFactory.createBean AutowireCapableBeanFactory.createBean does not prefer default constructor anymore Feb 27, 2023
@Artur-
Copy link
Contributor Author

Artur- commented Feb 28, 2023

Just to be clear: for us the main problem is that an extra bean is created, not that the wrong constructor is used (although I am sure the latter will be a problem also..)

@jhoeller
Copy link
Contributor

jhoeller commented Mar 2, 2023

Understood. From the framework perspective, the root of the problem is the selection of a different constructor in the case of multiple public constructors, hence the change of title.

I've applied a narrower algorithm now that selects a Kotlin primary / single public / single non-public constructor candidate, analogous to our constructor resolution convention for data/record classes, in addition to the default constructor. So in ambiguous scenarios with multiple constructors at the same level, we prefer the default constructor now rather than select by autowiring ability, while at the same time picking the obvious preferred constructor in other scenarios (analogous to AutowiredAnnotationBeanPostProcessor, just without the differentiation of annotated versus non-annotated constructors).

This will be included in the 6.0.6 release tonight, hopefully addressing the common regression while also keeping the intention of #29855. In 6.1, we will eventually deprecate the overloaded createBean variants and phase out autowiring modes such as AUTOWIRE_CONSTRUCTOR completely (except for XML definitions), consistently relying on constructor selection conventions for Class-based bean definitions outside of the annotation-based programming model as well.

@Artur-
Copy link
Contributor Author

Artur- commented Mar 2, 2023

Thanks, latest 6.0-SNAPSHOT seems to work again

jhoeller added a commit that referenced this issue Apr 30, 2023
Includes consistent usage of createBean(Class) in SpringBeanJobFactory and SpringBeanContainer.

Closes gh-30345
See gh-29855
See gh-30041
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: regression A bug that is also a regression
Projects
None yet
Development

No branches or pull requests

4 participants