Add support for @ScopedProxy for factory beans using the @FactoryBean annotation within a @Component
Add missing unit tests
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user