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 7d1d2e61580..cbb7381e406 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 @@ -1353,10 +1353,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac * @param bw the BeanWrapper with bean instance */ protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { - // record has not set methods - if (mbd.getBeanClass().isRecord()) { - return; - } if (bw == null) { if (mbd.hasPropertyValues()) { throw new BeanCreationException( @@ -1368,6 +1364,17 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac } } + if (bw.getWrappedClass().isRecord()) { + if (mbd.hasPropertyValues()) { + throw new BeanCreationException( + mbd.getResourceDescription(), beanName, "Cannot apply property values to a record"); + } + else { + // Skip property population phase for records since they are immutable. + return; + } + } + // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. diff --git a/spring-context/src/test/java/org/springframework/context/annotation/configuration/AutowiredConfigurationTests.java b/spring-context/src/test/java/org/springframework/context/annotation/configuration/AutowiredConfigurationTests.java index 564e9f7c3e5..1c61c9840ef 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/configuration/AutowiredConfigurationTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/configuration/AutowiredConfigurationTests.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. @@ -43,7 +43,6 @@ import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.annotation.AliasFor; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; -import org.springframework.core.testfixture.stereotype.Component; import static org.assertj.core.api.Assertions.assertThat; @@ -236,11 +235,13 @@ class AutowiredConfigurationTests { @Test void testValueInjectionWithRecord() { - System.setProperty("recordBeanName", "recordBean"); - GenericApplicationContext context = new AnnotationConfigApplicationContext(RecordBean.class); - context.refresh(); - RecordBean recordBean = context.getBean(RecordBean.class); - assertThat(recordBean.name()).isEqualTo("recordBean"); + System.setProperty("recordBeanName", "enigma"); + try (GenericApplicationContext context = new AnnotationConfigApplicationContext(RecordBean.class)) { + assertThat(context.getBean(RecordBean.class).name()).isEqualTo("enigma"); + } + finally { + System.clearProperty("recordBeanName"); + } } private int contentLength() throws IOException { @@ -517,7 +518,7 @@ class AutowiredConfigurationTests { } - @Component - static record RecordBean(@Value("recordBeanName") String name) { + record RecordBean(@Value("${recordBeanName}") String name) { } + }