New postProcessProperties variant on InstantiationAwareBeanPostProcessor
Allows for skipping the now-deprecated postProcessPropertyValues callback with its expensive PropertyDescriptor retrieval requirement. RequiredAnnotationBeanPostProcessor (which is dependent on postProcessPropertyValues) and the @Required annotation itself are also deprecated now: in favor of constructor injection (or afterPropertiesSet). Issue: SPR-16918
This commit is contained in:
@@ -365,9 +365,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyValues postProcessPropertyValues(
|
||||
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
|
||||
|
||||
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
|
||||
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
|
||||
try {
|
||||
metadata.inject(bean, beanName, pvs);
|
||||
@@ -381,6 +379,14 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
return pvs;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public PropertyValues postProcessPropertyValues(
|
||||
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
|
||||
|
||||
return postProcessProperties(pvs, bean, beanName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 'Native' processing method for direct calls with an arbitrary target instance,
|
||||
* resolving all of its fields and methods which are annotated with {@code @Autowired}.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -31,7 +31,10 @@ import java.lang.annotation.Target;
|
||||
* @author Rob Harrop
|
||||
* @since 2.0
|
||||
* @see RequiredAnnotationBeanPostProcessor
|
||||
* @deprecated as of 5.1, in favor of using constructor injection for required settings
|
||||
* (or a custom {@link org.springframework.beans.factory.InitializingBean} implementation)
|
||||
*/
|
||||
@Deprecated
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface Required {
|
||||
|
||||
@@ -25,7 +25,6 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.PropertyValues;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
@@ -72,7 +71,10 @@ import org.springframework.util.Assert;
|
||||
* @since 2.0
|
||||
* @see #setRequiredAnnotationType
|
||||
* @see Required
|
||||
* @deprecated as of 5.1, in favor of using constructor injection for required settings
|
||||
* (or a custom {@link org.springframework.beans.factory.InitializingBean} implementation)
|
||||
*/
|
||||
@Deprecated
|
||||
public class RequiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
|
||||
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
|
||||
|
||||
@@ -142,7 +144,7 @@ public class RequiredAnnotationBeanPostProcessor extends InstantiationAwareBeanP
|
||||
|
||||
@Override
|
||||
public PropertyValues postProcessPropertyValues(
|
||||
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
|
||||
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
|
||||
|
||||
if (!this.validatedBeanNames.contains(beanName)) {
|
||||
if (!shouldSkip(this.beanFactory, beanName)) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -55,7 +55,7 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
|
||||
* {@link #postProcessAfterInitialization} callback from the configured
|
||||
* {@link BeanPostProcessor BeanPostProcessors}.
|
||||
* <p>This callback will only be applied to bean definitions with a bean class.
|
||||
* In particular, it will not be applied to beans with a "factory-method".
|
||||
* In particular, it will not be applied to beans with a factory method.
|
||||
* <p>Post-processors may implement the extended
|
||||
* {@link SmartInstantiationAwareBeanPostProcessor} interface in order
|
||||
* to predict the type of the bean object that they are going to return here.
|
||||
@@ -65,8 +65,8 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
|
||||
* @return the bean object to expose instead of a default instance of the target bean,
|
||||
* or {@code null} to proceed with default instantiation
|
||||
* @throws org.springframework.beans.BeansException in case of errors
|
||||
* @see #postProcessAfterInstantiation
|
||||
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#hasBeanClass
|
||||
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#getFactoryMethodName
|
||||
*/
|
||||
@Nullable
|
||||
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
|
||||
@@ -86,11 +86,37 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
|
||||
* Returning {@code false} will also prevent any subsequent InstantiationAwareBeanPostProcessor
|
||||
* instances being invoked on this bean instance.
|
||||
* @throws org.springframework.beans.BeansException in case of errors
|
||||
* @see #postProcessBeforeInstantiation
|
||||
*/
|
||||
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-process the given property values before the factory applies them
|
||||
* to the given bean, without any need for property descriptors.
|
||||
* <p>Implementations should return {@code null} (the default) if they provide a custom
|
||||
* {@link #postProcessPropertyValues} implementation, and {@code pvs} otherwise.
|
||||
* In a future version of this interface (with {@link #postProcessPropertyValues} removed),
|
||||
* the default implementation will return the given {@code pvs} as-is directly.
|
||||
* @param pvs the property values that the factory is about to apply (never {@code null})
|
||||
* @param bean the bean instance created, but whose properties have not yet been set
|
||||
* @param beanName the name of the bean
|
||||
* @return the actual property values to apply to the given bean (can be the passed-in
|
||||
* PropertyValues instance), or {@code null} which proceeds with the existing properties
|
||||
* but specifically continues with a call to {@link #postProcessPropertyValues}
|
||||
* (requiring initialized {@code PropertyDescriptor}s for the current bean class)
|
||||
* @throws org.springframework.beans.BeansException in case of errors
|
||||
* @since 5.1
|
||||
* @see #postProcessPropertyValues
|
||||
*/
|
||||
@Nullable
|
||||
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
|
||||
throws BeansException {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-process the given property values before the factory applies them
|
||||
* to the given bean. Allows for checking whether all dependencies have been
|
||||
@@ -104,12 +130,14 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
|
||||
* dependency types - which the factory handles specifically - already filtered out)
|
||||
* @param bean the bean instance created, but whose properties have not yet been set
|
||||
* @param beanName the name of the bean
|
||||
* @return the actual property values to apply to the given bean
|
||||
* (can be the passed-in PropertyValues instance), or {@code null}
|
||||
* to skip property population
|
||||
* @return the actual property values to apply to the given bean (can be the passed-in
|
||||
* PropertyValues instance), or {@code null} to skip property population
|
||||
* @throws org.springframework.beans.BeansException in case of errors
|
||||
* @see #postProcessProperties
|
||||
* @see org.springframework.beans.MutablePropertyValues
|
||||
* @deprecated as of 5.1, in favor of {@link #postProcessProperties(PropertyValues, Object, String)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Nullable
|
||||
default PropertyValues postProcessPropertyValues(
|
||||
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -42,7 +42,7 @@ public abstract class InstantiationAwareBeanPostProcessorAdapter implements Smar
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
|
||||
public Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -68,6 +68,14 @@ public abstract class InstantiationAwareBeanPostProcessorAdapter implements Smar
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
|
||||
throws BeansException {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public PropertyValues postProcessPropertyValues(
|
||||
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
|
||||
|
||||
@@ -1292,6 +1292,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* @param mbd the bean definition for the bean
|
||||
* @param bw the BeanWrapper with bean instance
|
||||
*/
|
||||
@SuppressWarnings("deprecation") // for postProcessPropertyValues
|
||||
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
|
||||
if (bw == null) {
|
||||
if (mbd.hasPropertyValues()) {
|
||||
@@ -1347,25 +1348,33 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
|
||||
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
|
||||
|
||||
if (hasInstAwareBpps || needsDepCheck) {
|
||||
PropertyDescriptor[] filteredPds = null;
|
||||
if (hasInstAwareBpps) {
|
||||
if (pvs == null) {
|
||||
pvs = mbd.getPropertyValues();
|
||||
}
|
||||
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
|
||||
if (hasInstAwareBpps) {
|
||||
for (BeanPostProcessor bp : getBeanPostProcessors()) {
|
||||
if (bp instanceof InstantiationAwareBeanPostProcessor) {
|
||||
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
|
||||
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
|
||||
if (pvs == null) {
|
||||
for (BeanPostProcessor bp : getBeanPostProcessors()) {
|
||||
if (bp instanceof InstantiationAwareBeanPostProcessor) {
|
||||
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
|
||||
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
|
||||
if (pvsToUse == null) {
|
||||
if (filteredPds == null) {
|
||||
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
|
||||
}
|
||||
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
|
||||
if (pvsToUse == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
pvs = pvsToUse;
|
||||
}
|
||||
}
|
||||
if (needsDepCheck) {
|
||||
checkDependencies(beanName, mbd, filteredPds, pvs);
|
||||
}
|
||||
if (needsDepCheck) {
|
||||
if (filteredPds == null) {
|
||||
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
|
||||
}
|
||||
checkDependencies(beanName, mbd, filteredPds, pvs);
|
||||
}
|
||||
|
||||
if (pvs != null) {
|
||||
@@ -1543,12 +1552,12 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* @see #isExcludedFromDependencyCheck(java.beans.PropertyDescriptor)
|
||||
*/
|
||||
protected void checkDependencies(
|
||||
String beanName, AbstractBeanDefinition mbd, PropertyDescriptor[] pds, PropertyValues pvs)
|
||||
String beanName, AbstractBeanDefinition mbd, PropertyDescriptor[] pds, @Nullable PropertyValues pvs)
|
||||
throws UnsatisfiedDependencyException {
|
||||
|
||||
int dependencyCheck = mbd.getDependencyCheck();
|
||||
for (PropertyDescriptor pd : pds) {
|
||||
if (pd.getWriteMethod() != null && !pvs.contains(pd.getName())) {
|
||||
if (pd.getWriteMethod() != null && (pvs == null || !pvs.contains(pd.getName()))) {
|
||||
boolean isSimple = BeanUtils.isSimpleProperty(pd.getPropertyType());
|
||||
boolean unsatisfied = (dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_ALL) ||
|
||||
(isSimple && dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_SIMPLE) ||
|
||||
|
||||
Reference in New Issue
Block a user