diff --git a/plugin-core/src/main/java/org/synyx/plugin/core/support/BeanListBeanFactoryPostProcessor.java b/plugin-core/src/main/java/org/synyx/plugin/core/support/BeanListBeanFactoryPostProcessor.java index 3e0bb7e..0d6d77d 100644 --- a/plugin-core/src/main/java/org/synyx/plugin/core/support/BeanListBeanFactoryPostProcessor.java +++ b/plugin-core/src/main/java/org/synyx/plugin/core/support/BeanListBeanFactoryPostProcessor.java @@ -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.: + * + *
+ * <bean class="org.synyx.plugin.core.support.BeanListFactoryPostProcessor">
+ *    <property name="lists">
+ *       <map>
+ *          <entry key="beanName" value="org.synyx.plugin.core.Plugin" />
+ *       </map>
+ *    </property>
+ * </bean>
+ * 
+ * + * 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> lists = new HashMap>(); + 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 getBeanReferencesOfType( ConfigurableListableBeanFactory beanFactory, Class type) { - List beanNames = getBeanCandidates(beanFactory, type); + // Lookup bean candidates either via Spring or manually + List beanNames = + Arrays.asList(beanFactory.getBeanNamesForType(type, true, + initFactories)); List beanReferences = new ManagedList(beanNames.size()); @@ -176,62 +214,4 @@ public class BeanListBeanFactoryPostProcessor implements return (List) beanReferences; } - - - /** - * Looks up candidate beans for the given type from the {@link BeanFactory}. - * Does not use Spring type lookup facilities as this initializes - * {@link FactoryBean}s eagerly breaking possible registered - * {@link BeanPostProcessor}s. - *

- * We traverse the entire {@link BeanFactory} hierarchy to lookup beans. - * - * @param beanFactory - * @param type - * @return - */ - private List getBeanCandidates( - ConfigurableListableBeanFactory beanFactory, Class type) { - - List candidates = new ArrayList(); - - // 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; - } }