Merge branch '6.0.x'

This commit is contained in:
Stephane Nicoll 2023-05-12 08:59:57 +02:00
commit ffa431da7b
5 changed files with 79 additions and 14 deletions

View File

@ -286,7 +286,8 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
String beanName = registeredBean.getBeanName();
RootBeanDefinition beanDefinition = registeredBean.getMergedBeanDefinition();
InjectionMetadata metadata = findInjectionMetadata(beanName, beanClass, beanDefinition);
Collection<AutowiredElement> autowiredElements = getAutowiredElements(metadata);
Collection<AutowiredElement> autowiredElements = getAutowiredElements(metadata,
registeredBean.getMergedBeanDefinition().getPropertyValues());
if (!ObjectUtils.isEmpty(autowiredElements)) {
return new AotContribution(beanClass, autowiredElements, getAutowireCandidateResolver());
}
@ -295,8 +296,8 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
@SuppressWarnings({ "rawtypes", "unchecked" })
private Collection<AutowiredElement> getAutowiredElements(InjectionMetadata metadata) {
return (Collection) metadata.getInjectedElements();
private Collection<AutowiredElement> getAutowiredElements(InjectionMetadata metadata, PropertyValues propertyValues) {
return (Collection) metadata.getInjectedElements(propertyValues);
}
@Nullable
@ -752,7 +753,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
if (checkPropertySkipping(pvs)) {
if (!shouldInject(pvs)) {
return;
}
Method method = (Method) this.member;

View File

@ -97,6 +97,19 @@ public class InjectionMetadata {
return Collections.unmodifiableCollection(this.injectedElements);
}
/**
* Return the {@link InjectedElement elements} to inject based on the
* specified {@link PropertyValues}. If a property is already defined
* for an {@link InjectedElement}, it is excluded.
* @param pvs the property values to consider
* @return the elements to inject
* @since 6.0.10
*/
public Collection<InjectedElement> getInjectedElements(@Nullable PropertyValues pvs) {
return this.injectedElements.stream()
.filter(candidate -> candidate.shouldInject(pvs)).toList();
}
/**
* Determine whether this metadata instance needs to be refreshed.
* @param clazz the current target class
@ -230,21 +243,28 @@ public class InjectionMetadata {
}
}
protected boolean shouldInject(@Nullable PropertyValues pvs) {
if (this.isField) {
return true;
}
return !checkPropertySkipping(pvs);
}
/**
* Either this or {@link #getResourceToInject} needs to be overridden.
*/
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
throws Throwable {
if (!shouldInject(pvs)) {
return;
}
if (this.isField) {
Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field);
field.set(target, getResourceToInject(target, requestingBeanName));
}
else {
if (checkPropertySkipping(pvs)) {
return;
}
try {
Method method = (Method) this.member;
ReflectionUtils.makeAccessible(method);

View File

@ -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.
@ -65,11 +65,15 @@ class AutowiredAnnotationBeanRegistrationAotContributionTests {
private final DefaultListableBeanFactory beanFactory;
private final AutowiredAnnotationBeanPostProcessor beanPostProcessor;
AutowiredAnnotationBeanRegistrationAotContributionTests() {
this.generationContext = new TestGenerationContext();
this.beanRegistrationCode = new MockBeanRegistrationCode(this.generationContext);
this.beanFactory = new DefaultListableBeanFactory();
this.beanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
this.beanPostProcessor.setBeanFactory(this.beanFactory);
}
@ -185,10 +189,19 @@ class AutowiredAnnotationBeanRegistrationAotContributionTests {
});
}
@Test
void contributeWhenMethodInjectionHasMatchingPropertyValue() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(InjectionBean.class);
beanDefinition.getPropertyValues().addPropertyValue("counter", 42);
this.beanFactory.registerBeanDefinition("test", beanDefinition);
BeanRegistrationAotContribution contribution = this.beanPostProcessor
.processAheadOfTime(RegisteredBean.of(this.beanFactory, "test"));
assertThat(contribution).isNull();
}
private RegisteredBean getAndApplyContribution(Class<?> beanClass) {
RegisteredBean registeredBean = registerBean(beanClass);
BeanRegistrationAotContribution contribution = new AutowiredAnnotationBeanPostProcessor()
.processAheadOfTime(registeredBean);
BeanRegistrationAotContribution contribution = this.beanPostProcessor.processAheadOfTime(registeredBean);
assertThat(contribution).isNotNull();
contribution.applyTo(this.generationContext, this.beanRegistrationCode);
return registeredBean;
@ -229,4 +242,15 @@ class AutowiredAnnotationBeanRegistrationAotContributionTests {
result.accept(compiled.getInstance(BiFunction.class), compiled));
}
static class InjectionBean {
private Integer counter;
@Autowired
public void setCounter(Integer counter) {
this.counter = counter;
}
}
}

View File

@ -359,7 +359,8 @@ public class PersistenceAnnotationBeanPostProcessor implements InstantiationAwar
String beanName = registeredBean.getBeanName();
RootBeanDefinition beanDefinition = registeredBean.getMergedBeanDefinition();
InjectionMetadata metadata = findInjectionMetadata(beanDefinition, beanClass, beanName);
Collection<InjectedElement> injectedElements = metadata.getInjectedElements();
Collection<InjectedElement> injectedElements = metadata.getInjectedElements(
registeredBean.getMergedBeanDefinition().getPropertyValues());
if (!CollectionUtils.isEmpty(injectedElements)) {
return new AotContribution(beanClass, injectedElements);
}

View File

@ -43,6 +43,7 @@ import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.test.tools.CompileWithForkedClassLoader;
import org.springframework.core.test.tools.Compiled;
import org.springframework.core.test.tools.TestCompiler;
import org.springframework.lang.Nullable;
import org.springframework.util.ReflectionUtils;
import static org.assertj.core.api.Assertions.assertThat;
@ -67,6 +68,20 @@ class PersistenceAnnotationBeanPostProcessorAotContributionTests {
this.generationContext = new TestGenerationContext();
}
@Test
void processAheadOfTimeWhenPersistenceUnitOnFieldAndPropertyValueSet() {
RegisteredBean registeredBean = registerBean(DefaultPersistenceUnitField.class);
registeredBean.getMergedBeanDefinition().getPropertyValues().add("emf", "myEntityManagerFactory");
assertThat(processAheadOfTime(registeredBean)).isNotNull(); // Field not handled by property values
}
@Test
void processAheadOfTimeWhenPersistenceUnitOnMethodAndPropertyValueSet() {
RegisteredBean registeredBean = registerBean(DefaultPersistenceUnitMethod.class);
registeredBean.getMergedBeanDefinition().getPropertyValues().add("emf", "myEntityManagerFactory");
assertThat(processAheadOfTime(registeredBean)).isNull();
}
@Test
void processAheadOfTimeWhenPersistenceUnitOnPublicField() {
RegisteredBean registeredBean = registerBean(DefaultPersistenceUnitField.class);
@ -192,9 +207,7 @@ class PersistenceAnnotationBeanPostProcessorAotContributionTests {
private void testCompile(RegisteredBean registeredBean,
BiConsumer<BiConsumer<RegisteredBean, Object>, Compiled> result) {
PersistenceAnnotationBeanPostProcessor postProcessor = new PersistenceAnnotationBeanPostProcessor();
BeanRegistrationAotContribution contribution = postProcessor
.processAheadOfTime(registeredBean);
BeanRegistrationAotContribution contribution = processAheadOfTime(registeredBean);
BeanRegistrationCode beanRegistrationCode = mock();
contribution.applyTo(generationContext, beanRegistrationCode);
generationContext.writeGeneratedContent();
@ -202,6 +215,12 @@ class PersistenceAnnotationBeanPostProcessorAotContributionTests {
.compile(compiled -> result.accept(new Invoker(compiled), compiled));
}
@Nullable
private BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
PersistenceAnnotationBeanPostProcessor postProcessor = new PersistenceAnnotationBeanPostProcessor();
return postProcessor.processAheadOfTime(registeredBean);
}
static class Invoker implements BiConsumer<RegisteredBean, Object> {
private Compiled compiled;