Do not cache PropertyDescriptors for autowireBean calls anymore, avoiding ClassLoader leaks
Issue: SPR-8956
This commit is contained in:
@@ -285,6 +285,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
|||||||
// Use prototype bean definition, to avoid registering bean as dependent bean.
|
// Use prototype bean definition, to avoid registering bean as dependent bean.
|
||||||
RootBeanDefinition bd = new RootBeanDefinition(beanClass);
|
RootBeanDefinition bd = new RootBeanDefinition(beanClass);
|
||||||
bd.setScope(SCOPE_PROTOTYPE);
|
bd.setScope(SCOPE_PROTOTYPE);
|
||||||
|
bd.allowCaching = false;
|
||||||
return (T) createBean(beanClass.getName(), bd, null);
|
return (T) createBean(beanClass.getName(), bd, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,6 +293,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
|||||||
// Use non-singleton 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(ClassUtils.getUserClass(existingBean));
|
RootBeanDefinition bd = new RootBeanDefinition(ClassUtils.getUserClass(existingBean));
|
||||||
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||||
|
bd.allowCaching = false;
|
||||||
BeanWrapper bw = new BeanWrapperImpl(existingBean);
|
BeanWrapper bw = new BeanWrapperImpl(existingBean);
|
||||||
initBeanWrapper(bw);
|
initBeanWrapper(bw);
|
||||||
populateBean(bd.getBeanClass().getName(), bd, bw);
|
populateBean(bd.getBeanClass().getName(), bd, bw);
|
||||||
@@ -310,6 +312,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
|||||||
if (bd == null) {
|
if (bd == null) {
|
||||||
bd = new RootBeanDefinition(mbd);
|
bd = new RootBeanDefinition(mbd);
|
||||||
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||||
|
bd.allowCaching = false;
|
||||||
}
|
}
|
||||||
BeanWrapper bw = new BeanWrapperImpl(existingBean);
|
BeanWrapper bw = new BeanWrapperImpl(existingBean);
|
||||||
initBeanWrapper(bw);
|
initBeanWrapper(bw);
|
||||||
@@ -1053,7 +1056,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
|||||||
* @param mbd the bean definition for the bean
|
* @param mbd the bean definition for the bean
|
||||||
* @param bw BeanWrapper with bean instance
|
* @param bw BeanWrapper with bean instance
|
||||||
*/
|
*/
|
||||||
protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {
|
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
|
||||||
PropertyValues pvs = mbd.getPropertyValues();
|
PropertyValues pvs = mbd.getPropertyValues();
|
||||||
|
|
||||||
if (bw == null) {
|
if (bw == null) {
|
||||||
@@ -1109,7 +1112,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
|||||||
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
|
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
|
||||||
|
|
||||||
if (hasInstAwareBpps || needsDepCheck) {
|
if (hasInstAwareBpps || needsDepCheck) {
|
||||||
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);
|
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
|
||||||
if (hasInstAwareBpps) {
|
if (hasInstAwareBpps) {
|
||||||
for (BeanPostProcessor bp : getBeanPostProcessors()) {
|
for (BeanPostProcessor bp : getBeanPostProcessors()) {
|
||||||
if (bp instanceof InstantiationAwareBeanPostProcessor) {
|
if (bp instanceof InstantiationAwareBeanPostProcessor) {
|
||||||
@@ -1237,32 +1240,49 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract a filtered set of PropertyDescriptors from the given BeanWrapper,
|
* Extract a filtered set of PropertyDescriptors from the given BeanWrapper,
|
||||||
* excluding ignored dependency types or properties defined on ignored
|
* excluding ignored dependency types or properties defined on ignored dependency interfaces.
|
||||||
* dependency interfaces.
|
* @param bw the BeanWrapper the bean was created with
|
||||||
|
* @param cache whether to cache filtered PropertyDescriptors for the given bean Class
|
||||||
|
* @return the filtered PropertyDescriptors
|
||||||
|
* @see #isExcludedFromDependencyCheck
|
||||||
|
* @see #filterPropertyDescriptorsForDependencyCheck(org.springframework.beans.BeanWrapper)
|
||||||
|
*/
|
||||||
|
protected PropertyDescriptor[] filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw, boolean cache) {
|
||||||
|
PropertyDescriptor[] filtered = this.filteredPropertyDescriptorsCache.get(bw.getWrappedClass());
|
||||||
|
if (filtered == null) {
|
||||||
|
if (cache) {
|
||||||
|
synchronized (this.filteredPropertyDescriptorsCache) {
|
||||||
|
filtered = this.filteredPropertyDescriptorsCache.get(bw.getWrappedClass());
|
||||||
|
if (filtered == null) {
|
||||||
|
filtered = filterPropertyDescriptorsForDependencyCheck(bw);
|
||||||
|
this.filteredPropertyDescriptorsCache.put(bw.getWrappedClass(), filtered);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
filtered = filterPropertyDescriptorsForDependencyCheck(bw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract a filtered set of PropertyDescriptors from the given BeanWrapper,
|
||||||
|
* excluding ignored dependency types or properties defined on ignored dependency interfaces.
|
||||||
* @param bw the BeanWrapper the bean was created with
|
* @param bw the BeanWrapper the bean was created with
|
||||||
* @return the filtered PropertyDescriptors
|
* @return the filtered PropertyDescriptors
|
||||||
* @see #isExcludedFromDependencyCheck
|
* @see #isExcludedFromDependencyCheck
|
||||||
*/
|
*/
|
||||||
protected PropertyDescriptor[] filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw) {
|
protected PropertyDescriptor[] filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw) {
|
||||||
PropertyDescriptor[] filtered = this.filteredPropertyDescriptorsCache.get(bw.getWrappedClass());
|
List<PropertyDescriptor> pds =
|
||||||
if (filtered == null) {
|
new LinkedList<PropertyDescriptor>(Arrays.asList(bw.getPropertyDescriptors()));
|
||||||
synchronized (this.filteredPropertyDescriptorsCache) {
|
for (Iterator<PropertyDescriptor> it = pds.iterator(); it.hasNext();) {
|
||||||
filtered = this.filteredPropertyDescriptorsCache.get(bw.getWrappedClass());
|
PropertyDescriptor pd = it.next();
|
||||||
if (filtered == null) {
|
if (isExcludedFromDependencyCheck(pd)) {
|
||||||
List<PropertyDescriptor> pds =
|
it.remove();
|
||||||
new LinkedList<PropertyDescriptor>(Arrays.asList(bw.getPropertyDescriptors()));
|
|
||||||
for (Iterator<PropertyDescriptor> it = pds.iterator(); it.hasNext();) {
|
|
||||||
PropertyDescriptor pd = it.next();
|
|
||||||
if (isExcludedFromDependencyCheck(pd)) {
|
|
||||||
it.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
filtered = pds.toArray(new PropertyDescriptor[pds.size()]);
|
|
||||||
this.filteredPropertyDescriptorsCache.put(bw.getWrappedClass(), filtered);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return filtered;
|
return pds.toArray(new PropertyDescriptor[pds.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2010 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
@@ -56,7 +56,9 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
|||||||
|
|
||||||
private BeanDefinitionHolder decoratedDefinition;
|
private BeanDefinitionHolder decoratedDefinition;
|
||||||
|
|
||||||
boolean isFactoryMethodUnique;
|
boolean allowCaching = true;
|
||||||
|
|
||||||
|
boolean isFactoryMethodUnique = false;
|
||||||
|
|
||||||
/** Package-visible field for caching the resolved constructor or factory method */
|
/** Package-visible field for caching the resolved constructor or factory method */
|
||||||
Object resolvedConstructorOrFactoryMethod;
|
Object resolvedConstructorOrFactoryMethod;
|
||||||
|
|||||||
Reference in New Issue
Block a user