Browse Source

Merge branch '6.0.x'

pull/30404/head
Stephane Nicoll 3 years ago
parent
commit
ffa431da7b
  1. 9
      spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java
  2. 26
      spring-beans/src/main/java/org/springframework/beans/factory/annotation/InjectionMetadata.java
  3. 30
      spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanRegistrationAotContributionTests.java
  4. 3
      spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java
  5. 25
      spring-orm/src/test/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessorAotContributionTests.java

9
spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java

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

26
spring-beans/src/main/java/org/springframework/beans/factory/annotation/InjectionMetadata.java

@ -97,6 +97,19 @@ public class InjectionMetadata {
return Collections.unmodifiableCollection(this.injectedElements); 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. * Determine whether this metadata instance needs to be refreshed.
* @param clazz the current target class * @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. * Either this or {@link #getResourceToInject} needs to be overridden.
*/ */
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs) protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
throws Throwable { throws Throwable {
if (!shouldInject(pvs)) {
return;
}
if (this.isField) { if (this.isField) {
Field field = (Field) this.member; Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field); ReflectionUtils.makeAccessible(field);
field.set(target, getResourceToInject(target, requestingBeanName)); field.set(target, getResourceToInject(target, requestingBeanName));
} }
else { else {
if (checkPropertySkipping(pvs)) {
return;
}
try { try {
Method method = (Method) this.member; Method method = (Method) this.member;
ReflectionUtils.makeAccessible(method); ReflectionUtils.makeAccessible(method);

30
spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanRegistrationAotContributionTests.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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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 DefaultListableBeanFactory beanFactory;
private final AutowiredAnnotationBeanPostProcessor beanPostProcessor;
AutowiredAnnotationBeanRegistrationAotContributionTests() { AutowiredAnnotationBeanRegistrationAotContributionTests() {
this.generationContext = new TestGenerationContext(); this.generationContext = new TestGenerationContext();
this.beanRegistrationCode = new MockBeanRegistrationCode(this.generationContext); this.beanRegistrationCode = new MockBeanRegistrationCode(this.generationContext);
this.beanFactory = new DefaultListableBeanFactory(); 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) { private RegisteredBean getAndApplyContribution(Class<?> beanClass) {
RegisteredBean registeredBean = registerBean(beanClass); RegisteredBean registeredBean = registerBean(beanClass);
BeanRegistrationAotContribution contribution = new AutowiredAnnotationBeanPostProcessor() BeanRegistrationAotContribution contribution = this.beanPostProcessor.processAheadOfTime(registeredBean);
.processAheadOfTime(registeredBean);
assertThat(contribution).isNotNull(); assertThat(contribution).isNotNull();
contribution.applyTo(this.generationContext, this.beanRegistrationCode); contribution.applyTo(this.generationContext, this.beanRegistrationCode);
return registeredBean; return registeredBean;
@ -229,4 +242,15 @@ class AutowiredAnnotationBeanRegistrationAotContributionTests {
result.accept(compiled.getInstance(BiFunction.class), compiled)); result.accept(compiled.getInstance(BiFunction.class), compiled));
} }
static class InjectionBean {
private Integer counter;
@Autowired
public void setCounter(Integer counter) {
this.counter = counter;
}
}
} }

3
spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java

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

25
spring-orm/src/test/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessorAotContributionTests.java

@ -43,6 +43,7 @@ import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.test.tools.CompileWithForkedClassLoader; import org.springframework.core.test.tools.CompileWithForkedClassLoader;
import org.springframework.core.test.tools.Compiled; import org.springframework.core.test.tools.Compiled;
import org.springframework.core.test.tools.TestCompiler; import org.springframework.core.test.tools.TestCompiler;
import org.springframework.lang.Nullable;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -67,6 +68,20 @@ class PersistenceAnnotationBeanPostProcessorAotContributionTests {
this.generationContext = new TestGenerationContext(); 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 @Test
void processAheadOfTimeWhenPersistenceUnitOnPublicField() { void processAheadOfTimeWhenPersistenceUnitOnPublicField() {
RegisteredBean registeredBean = registerBean(DefaultPersistenceUnitField.class); RegisteredBean registeredBean = registerBean(DefaultPersistenceUnitField.class);
@ -192,9 +207,7 @@ class PersistenceAnnotationBeanPostProcessorAotContributionTests {
private void testCompile(RegisteredBean registeredBean, private void testCompile(RegisteredBean registeredBean,
BiConsumer<BiConsumer<RegisteredBean, Object>, Compiled> result) { BiConsumer<BiConsumer<RegisteredBean, Object>, Compiled> result) {
PersistenceAnnotationBeanPostProcessor postProcessor = new PersistenceAnnotationBeanPostProcessor(); BeanRegistrationAotContribution contribution = processAheadOfTime(registeredBean);
BeanRegistrationAotContribution contribution = postProcessor
.processAheadOfTime(registeredBean);
BeanRegistrationCode beanRegistrationCode = mock(); BeanRegistrationCode beanRegistrationCode = mock();
contribution.applyTo(generationContext, beanRegistrationCode); contribution.applyTo(generationContext, beanRegistrationCode);
generationContext.writeGeneratedContent(); generationContext.writeGeneratedContent();
@ -202,6 +215,12 @@ class PersistenceAnnotationBeanPostProcessorAotContributionTests {
.compile(compiled -> result.accept(new Invoker(compiled), compiled)); .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> { static class Invoker implements BiConsumer<RegisteredBean, Object> {
private Compiled compiled; private Compiled compiled;

Loading…
Cancel
Save