From 0e8838db90d481b58860cc151d7510a46acb4936 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 19 Jan 2023 17:10:42 +0100 Subject: [PATCH] Flexible constructor resolution in AutowireCapableBeanFactory.createBean(Class) Closes gh-29855 See gh-29823 --- .../beans/factory/config/AutowireCapableBeanFactory.java | 4 +++- .../support/AbstractAutowireCapableBeanFactory.java | 5 +++-- .../scheduling/quartz/SpringBeanJobFactory.java | 5 ++--- .../orm/hibernate5/SpringBeanContainer.java | 4 ++-- .../web/context/request/RequestScopeTests.java | 6 ++---- .../web/context/request/RequestScopedProxyTests.java | 8 +++----- 6 files changed, 15 insertions(+), 17 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/AutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/AutowireCapableBeanFactory.java index e096fbb38f..5c87f8a984 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/config/AutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/AutowireCapableBeanFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -130,6 +130,8 @@ public interface AutowireCapableBeanFactory extends BeanFactory { * {@link BeanPostProcessor BeanPostProcessors}. *

Note: This is intended for creating a fresh instance, populating annotated * fields and methods as well as applying all standard bean initialization callbacks. + * Constructor resolution is done via {@link #AUTOWIRE_CONSTRUCTOR}, also influenced + * by {@link SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors}. * It does not imply traditional by-name or by-type autowiring of properties; * use {@link #createBean(Class, int, boolean)} for those purposes. * @param beanClass the class of the bean to create diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index e2aa54aa5a..50838d8340 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -314,8 +314,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac @Override @SuppressWarnings("unchecked") public T createBean(Class beanClass) throws BeansException { - // Use prototype bean definition, to avoid registering bean as dependent bean. + // Use non-singleton bean definition, to avoid registering bean as dependent bean. RootBeanDefinition bd = new RootBeanDefinition(beanClass); + bd.setAutowireMode(AUTOWIRE_CONSTRUCTOR); bd.setScope(SCOPE_PROTOTYPE); bd.allowCaching = ClassUtils.isCacheSafe(beanClass, getBeanClassLoader()); return (T) createBean(beanClass.getName(), bd, null); diff --git a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SpringBeanJobFactory.java b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SpringBeanJobFactory.java index 3c6369f9b1..cdeab7f5f2 100644 --- a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SpringBeanJobFactory.java +++ b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SpringBeanJobFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,7 +22,6 @@ import org.quartz.spi.TriggerFiredBundle; import org.springframework.beans.BeanWrapper; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.PropertyAccessorFactory; -import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.lang.Nullable; @@ -88,7 +87,7 @@ public class SpringBeanJobFactory extends AdaptableJobFactory protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { Object job = (this.applicationContext != null ? this.applicationContext.getAutowireCapableBeanFactory().createBean( - bundle.getJobDetail().getJobClass(), AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false) : + bundle.getJobDetail().getJobClass()) : super.createJobInstance(bundle)); if (isEligibleForPropertyPopulation(job)) { diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringBeanContainer.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringBeanContainer.java index c2f327773b..912ebf544a 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringBeanContainer.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringBeanContainer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -144,7 +144,7 @@ public final class SpringBeanContainer implements BeanContainer { try { if (lifecycleOptions.useJpaCompliantCreation()) { return new SpringContainedBean<>( - this.beanFactory.createBean(beanType, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false), + this.beanFactory.createBean(beanType), this.beanFactory::destroyBean); } else { diff --git a/spring-web/src/test/java/org/springframework/web/context/request/RequestScopeTests.java b/spring-web/src/test/java/org/springframework/web/context/request/RequestScopeTests.java index 15f94f4e37..30a48143cc 100644 --- a/spring-web/src/test/java/org/springframework/web/context/request/RequestScopeTests.java +++ b/spring-web/src/test/java/org/springframework/web/context/request/RequestScopeTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,6 @@ import org.springframework.web.testfixture.servlet.MockHttpServletRequest; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.springframework.beans.factory.config.AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR; /** * @author Rob Harrop @@ -174,8 +173,7 @@ public class RequestScopeTests { assertThat(beanProvider.getIfAvailable()).isNull(); assertThat(beanProvider.getIfUnique()).isNull(); - ObjectProvider provider = - ((ProviderBean) this.beanFactory.createBean(ProviderBean.class, AUTOWIRE_CONSTRUCTOR, false)).provider; + ObjectProvider provider = this.beanFactory.createBean(ProviderBean.class).provider; assertThatExceptionOfType(ScopeNotActiveException.class).isThrownBy(provider::getObject); assertThat(provider.getIfAvailable()).isNull(); assertThat(provider.getIfUnique()).isNull(); diff --git a/spring-web/src/test/java/org/springframework/web/context/request/RequestScopedProxyTests.java b/spring-web/src/test/java/org/springframework/web/context/request/RequestScopedProxyTests.java index 859808030b..65605e1a47 100644 --- a/spring-web/src/test/java/org/springframework/web/context/request/RequestScopedProxyTests.java +++ b/spring-web/src/test/java/org/springframework/web/context/request/RequestScopedProxyTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,6 @@ import org.springframework.web.testfixture.servlet.MockHttpServletRequest; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.springframework.beans.factory.config.AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR; /** * @author Juergen Hoeller @@ -209,13 +208,12 @@ public class RequestScopedProxyTests { assertThatExceptionOfType(ScopeNotActiveException.class).isThrownBy( () -> this.beanFactory.getBean(CountingTestBean.class).absquatulate()); - final ObjectProvider beanProvider = this.beanFactory.getBeanProvider(CountingTestBean.class); + ObjectProvider beanProvider = this.beanFactory.getBeanProvider(CountingTestBean.class); assertThatExceptionOfType(ScopeNotActiveException.class).isThrownBy(() -> beanProvider.getObject().absquatulate()); beanProvider.ifAvailable(TestBean::absquatulate); beanProvider.ifUnique(TestBean::absquatulate); - final ObjectProvider provider = - ((ProviderBean) this.beanFactory.createBean(ProviderBean.class, AUTOWIRE_CONSTRUCTOR, false)).provider; + ObjectProvider provider = this.beanFactory.createBean(ProviderBean.class).provider; assertThatExceptionOfType(ScopeNotActiveException.class).isThrownBy(() -> provider.getObject().absquatulate()); provider.ifAvailable(TestBean::absquatulate); provider.ifUnique(TestBean::absquatulate);