* removed custom implementation of type lookup as {{{getBeanNamesForType}}} suddenly does work as expected

* added property to allow dedicated configuration, if {{{FactoryBean}}}s shall be initialized eagerly or not

git-svn-id: svn+ssh://svn.synyx.de/var/svn/synyx/opensource/synyx-plugin/trunk@2931 5a64d73e-33d6-4ccc-9058-23f8668ecac9
This commit is contained in:
Oliver Gierke
2008-10-07 19:56:49 +00:00
parent 282facb713
commit e4a61d14a7

View File

@@ -1,6 +1,6 @@
package org.synyx.plugin.core.support;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -8,11 +8,8 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.ListFactoryBean;
import org.springframework.beans.factory.config.RuntimeBeanReference;
@@ -20,11 +17,30 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.util.StringUtils;
import org.synyx.plugin.core.PluginRegistry;
/**
* Simple {@link BeanFactoryPostProcessor} to autocreate lists of the configured
* {@code lists} property. The post processor will register
* {@link ListFactoryBean}s for each list named with the given key containing
* all beans of the {@link org.springframework.context.ApplicationContext}
* implementing the interface defines as lists value. E.g.:
*
* <pre>
* &lt;bean class=&quot;org.synyx.plugin.core.support.BeanListFactoryPostProcessor&quot;&gt;
* &lt;property name=&quot;lists&quot;&gt;
* &lt;map&gt;
* &lt;entry key=&quot;beanName&quot; value=&quot;org.synyx.plugin.core.Plugin&quot; /&gt;
* &lt;/map&gt;
* &lt;/property&gt;
* &lt;/bean&gt;
* </pre>
*
* This would register all Spring beans implementing the
* {@link org.synyx.plugin.core.Plugin} interface in a list bean with the name
* {@coder beanName}.
*
* @author Oliver Gierke - gierke@synyx.de
*/
public class BeanListBeanFactoryPostProcessor implements
@@ -35,6 +51,8 @@ public class BeanListBeanFactoryPostProcessor implements
private Map<String, Class<?>> lists = new HashMap<String, Class<?>>();
private boolean initFactories = false;
/**
* Setter to inject required plugin registry configuration. The map's keys
@@ -50,6 +68,23 @@ public class BeanListBeanFactoryPostProcessor implements
}
/**
* Setter to activate {@link org.springframework.beans.factory.FactoryBean}
* scanning. This allows auto-registration of factory bean targets (the
* objects actually created by the factory bean} but comes with the drawback
* of having to initialize those factories eagerly. This can cause
* unpredictable behaviour if other {@link BeanFactoryPostProcessor}s would
* have been applied to these factories. Defaults to {@value #initFactories}
* .
*
* @param initFactories the allowEagerInit to set
*/
public void setInitFactories(boolean initFactories) {
this.initFactories = initFactories;
}
/*
* (non-Javadoc)
*
@@ -161,7 +196,10 @@ public class BeanListBeanFactoryPostProcessor implements
protected List<RuntimeBeanReference> getBeanReferencesOfType(
ConfigurableListableBeanFactory beanFactory, Class<?> type) {
List<String> beanNames = getBeanCandidates(beanFactory, type);
// Lookup bean candidates either via Spring or manually
List<String> beanNames =
Arrays.asList(beanFactory.getBeanNamesForType(type, true,
initFactories));
List<RuntimeBeanReference> beanReferences =
new ManagedList(beanNames.size());
@@ -176,62 +214,4 @@ public class BeanListBeanFactoryPostProcessor implements
return (List<RuntimeBeanReference>) beanReferences;
}
/**
* Looks up candidate beans for the given type from the {@link BeanFactory}.
* Does <em>not</em> use Spring type lookup facilities as this initializes
* {@link FactoryBean}s eagerly breaking possible registered
* {@link BeanPostProcessor}s.
* <p>
* We traverse the entire {@link BeanFactory} hierarchy to lookup beans.
*
* @param beanFactory
* @param type
* @return
*/
private List<String> getBeanCandidates(
ConfigurableListableBeanFactory beanFactory, Class<?> type) {
List<String> candidates = new ArrayList<String>();
// None given or most top bean factory reached?
if (null == beanFactory) {
return candidates;
}
String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
for (String beanName : beanDefinitionNames) {
BeanDefinition beanDefinition =
beanFactory.getBeanDefinition(beanName);
// No bean class available at all
if (!StringUtils.hasText(beanDefinition.getBeanClassName())) {
continue;
}
try {
Class<?> beanClass =
Class.forName(beanDefinition.getBeanClassName());
if (type.isAssignableFrom(beanClass)) {
candidates.add(beanName);
}
} catch (ClassNotFoundException e) {
continue;
}
}
// Traverse parent bean factories
if (beanFactory.getParentBeanFactory() instanceof ConfigurableListableBeanFactory) {
candidates.addAll(getBeanCandidates(
(ConfigurableListableBeanFactory) beanFactory
.getParentBeanFactory(), type));
}
return candidates;
}
}