Add support for @ScopedProxy for factory beans using the @FactoryBean annotation within a @Component

Add missing unit tests
This commit is contained in:
Mark Pollack
2009-03-13 18:14:40 +00:00
parent bf31766ff8
commit 13dfa11def
6 changed files with 293 additions and 9 deletions

View File

@@ -65,8 +65,7 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
private boolean includeAnnotationConfig = true;
/**
* Create a new ClassPathBeanDefinitionScanner for the given bean factory.
* @param registry the BeanFactory to load bean definitions into,
@@ -221,14 +220,23 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
protected void postProcessComponentBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
//TODO refactor increment index count as part of naming strategy.
int count = 0;
Set<BeanDefinitionHolder> factoryBeanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitions) {
Set<BeanDefinition> candidates = findCandidateFactoryMethods(beanDefinitionHolder);
for (BeanDefinition candidate : candidates ) {
//TODO refactor to introduce naming strategy and some sanity checks.
String beanName = beanDefinitionHolder.getBeanName() + "$" + candidate.getFactoryMethodName() + "#" + count++;
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
for (BeanDefinition candidate : candidates ) {
BeanDefinitionHolder definitionHolder;
if (candidate.getBeanClassName().equals("org.springframework.aop.scope.ScopedProxyFactoryBean")){
String scopedFactoryBeanName = "scopedTarget." + candidate.getPropertyValues().getPropertyValue("targetBeanName").getValue();
definitionHolder = new BeanDefinitionHolder(candidate, scopedFactoryBeanName);
} else {
String configurationComponentBeanName = beanDefinitionHolder.getBeanName();
String factoryMethodName = candidate.getFactoryMethodName();
String beanName = createFactoryBeanName(configurationComponentBeanName, factoryMethodName);
definitionHolder = new BeanDefinitionHolder(candidate, beanName);
}
factoryBeanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
@@ -236,8 +244,6 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
beanDefinitions.addAll(factoryBeanDefinitions);
}
/**
* Apply further settings to the given bean definition,
* beyond the contents retrieved from scanning the component class.

View File

@@ -27,6 +27,7 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.scope.ScopedProxyFactoryBean;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -34,6 +35,8 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
@@ -77,6 +80,8 @@ public class ClassPathScanningCandidateComponentProvider implements ResourceLoad
protected static final String QUALIFIER_CLASS_NAME = "org.springframework.beans.factory.annotation.Qualifier";
protected static final String SCOPE_CLASS_NAME = "org.springframework.context.annotation.Scope";
protected static final String SCOPEDPROXY_CLASS_NAME = "org.springframework.beans.factory.annotation.ScopedProxy";
protected final Log logger = LogFactory.getLog(getClass());
@@ -90,6 +95,8 @@ public class ClassPathScanningCandidateComponentProvider implements ResourceLoad
private final List<TypeFilter> excludeFilters = new LinkedList<TypeFilter>();
private int factoryBeanCount = 0;
/**
* Create a ClassPathScanningCandidateComponentProvider.
@@ -259,10 +266,33 @@ public class ClassPathScanningCandidateComponentProvider implements ResourceLoad
factoryBeanDef.setResource(containingBeanDef.getResource());
factoryBeanDef.setSource(containingBeanDef.getSource());
if (debugEnabled) {
logger.debug("Identified candidate factory method in class: " + resource);
}
candidates.add(factoryBeanDef);
RootBeanDefinition scopedFactoryBeanDef = null;
if (methodMetadata.hasAnnotation(SCOPEDPROXY_CLASS_NAME)) {
//TODO validate that @ScopedProxy isn't applied to singleton/prototype beans.
Map<String, Object> attributes = methodMetadata.getAnnotationAttributes(SCOPEDPROXY_CLASS_NAME);
scopedFactoryBeanDef = new RootBeanDefinition(ScopedProxyFactoryBean.class);
String t= scopedFactoryBeanDef.getBeanClassName();
String targetBeanName = createFactoryBeanName(beanDefinitionHolder.getBeanName(), factoryBeanDef.getFactoryMethodName());
scopedFactoryBeanDef.getPropertyValues().addPropertyValue("targetBeanName", targetBeanName);
//TODO handle cglib options
// scopedFactoryBeanDef.getPropertyValues().addPropertyValue("proxyTargetClass", Boolean.FALSE);
scopedFactoryBeanDef.setAutowireCandidate(false);
scopedFactoryBeanDef.setResource(containingBeanDef.getResource());
scopedFactoryBeanDef.setSource(containingBeanDef.getSource());
candidates.add(scopedFactoryBeanDef);
}
}
else {
if (traceEnabled) {
@@ -365,4 +395,11 @@ public class ClassPathScanningCandidateComponentProvider implements ResourceLoad
return (beanDefinition.getMetadata().isConcrete() && beanDefinition.getMetadata().isIndependent());
}
protected String createFactoryBeanName(String configurationComponentBeanName, String factoryMethodName) {
//TODO consider adding hex string and passing in definition object.
String beanName = configurationComponentBeanName + "$" + factoryMethodName;
return beanName;
}
}