Browse Source

Do not cache PropertyDescriptors for autowireBean calls anymore, avoiding ClassLoader leaks

Issue: SPR-8956
pull/181/head
Juergen Hoeller 13 years ago
parent
commit
e1d11ec99d
  1. 54
      spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java
  2. 6
      spring-beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java

54
spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java

@ -285,6 +285,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac @@ -285,6 +285,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
// Use prototype bean definition, to avoid registering bean as dependent bean.
RootBeanDefinition bd = new RootBeanDefinition(beanClass);
bd.setScope(SCOPE_PROTOTYPE);
bd.allowCaching = false;
return (T) createBean(beanClass.getName(), bd, null);
}
@ -292,6 +293,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac @@ -292,6 +293,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
// Use non-singleton bean definition, to avoid registering bean as dependent bean.
RootBeanDefinition bd = new RootBeanDefinition(ClassUtils.getUserClass(existingBean));
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
bd.allowCaching = false;
BeanWrapper bw = new BeanWrapperImpl(existingBean);
initBeanWrapper(bw);
populateBean(bd.getBeanClass().getName(), bd, bw);
@ -310,6 +312,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac @@ -310,6 +312,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
if (bd == null) {
bd = new RootBeanDefinition(mbd);
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
bd.allowCaching = false;
}
BeanWrapper bw = new BeanWrapperImpl(existingBean);
initBeanWrapper(bw);
@ -1053,7 +1056,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac @@ -1053,7 +1056,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
* @param mbd the bean definition for the bean
* @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();
if (bw == null) {
@ -1109,7 +1112,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac @@ -1109,7 +1112,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
@ -1237,34 +1240,51 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac @@ -1237,34 +1240,51 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
/**
* Extract a filtered set of PropertyDescriptors from the given BeanWrapper,
* excluding ignored dependency types or properties defined on ignored
* dependency interfaces.
* excluding ignored dependency types or properties defined on ignored 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) {
protected PropertyDescriptor[] filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw, boolean cache) {
PropertyDescriptor[] filtered = this.filteredPropertyDescriptorsCache.get(bw.getWrappedClass());
if (filtered == null) {
synchronized (this.filteredPropertyDescriptorsCache) {
filtered = this.filteredPropertyDescriptorsCache.get(bw.getWrappedClass());
if (filtered == null) {
List<PropertyDescriptor> pds =
new LinkedList<PropertyDescriptor>(Arrays.asList(bw.getPropertyDescriptors()));
for (Iterator<PropertyDescriptor> it = pds.iterator(); it.hasNext();) {
PropertyDescriptor pd = it.next();
if (isExcludedFromDependencyCheck(pd)) {
it.remove();
}
if (cache) {
synchronized (this.filteredPropertyDescriptorsCache) {
filtered = this.filteredPropertyDescriptorsCache.get(bw.getWrappedClass());
if (filtered == null) {
filtered = filterPropertyDescriptorsForDependencyCheck(bw);
this.filteredPropertyDescriptorsCache.put(bw.getWrappedClass(), filtered);
}
filtered = pds.toArray(new PropertyDescriptor[pds.size()]);
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
* @return the filtered PropertyDescriptors
* @see #isExcludedFromDependencyCheck
*/
protected PropertyDescriptor[] filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw) {
List<PropertyDescriptor> pds =
new LinkedList<PropertyDescriptor>(Arrays.asList(bw.getPropertyDescriptors()));
for (Iterator<PropertyDescriptor> it = pds.iterator(); it.hasNext();) {
PropertyDescriptor pd = it.next();
if (isExcludedFromDependencyCheck(pd)) {
it.remove();
}
}
return pds.toArray(new PropertyDescriptor[pds.size()]);
}
/**
* Determine whether the given bean property is excluded from dependency checks.
* <p>This implementation excludes properties defined by CGLIB and

6
spring-beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java

@ -1,5 +1,5 @@ @@ -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");
* you may not use this file except in compliance with the License.
@ -56,7 +56,9 @@ public class RootBeanDefinition extends AbstractBeanDefinition { @@ -56,7 +56,9 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
private BeanDefinitionHolder decoratedDefinition;
boolean isFactoryMethodUnique;
boolean allowCaching = true;
boolean isFactoryMethodUnique = false;
/** Package-visible field for caching the resolved constructor or factory method */
Object resolvedConstructorOrFactoryMethod;

Loading…
Cancel
Save