占位符不在自定义架构元素上

时间:2014-07-17 08:45:19

标签: spring spring-mvc dependency-injection

我试图从占位符中获取一些值到自定义架构属性(cfg:merge-elements' target),但它不起作用:

somexml.xml:

<bean id="stateMachineNamingStrategy" class="com.mycompany.statemachine.hibernate.StateMachineNamingStrategy">
    <property name="prefix" value="${statemachine.table_prefix}"/>
</bean>

<cfg:merge-elements id="packages-com.mycompany.statemachine" target="${session-factory-pkgs}">
    <value>com.mycompany.statemachine.machine.impl</value>
</cfg:merge-elements>

这些定义在同一个xml中。第一个(stateMachineNamingStrategy)正确地从$ {statemachine.table_prefix}获取值。

第二个无法在 $ {session-factory-pkgs} 中检索它。例外情况表明属性值尚未转换:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named '${session-factory-pkgs}' is defined

为什么不将占位符转换为其值?

1 个答案:

答案 0 :(得分:0)

如果有人遇到同样的问题:

事实证明,在我的NamespaceHandler中,我注册了一个扩展BeanDefinitionRegistryPostProcessor的新BeanDefinition。这些特殊的后处理器在正常BeanFactoryPostProcessor之前执行,以允许注册或删除BeanDefinitions。因此,没有办法让PropertyPlaceholderConfigurer(这是一个普通的BeanPostProcessor)在BeanDefinitionRegistryPostProcessor之前执行。

你可以在XmlWebApplicationContext(AbstractApplicationContext).invokeBeanFactoryPostProcessors中看到它:

        Map<String, BeanDefinitionRegistryPostProcessor> beanMap =
                beanFactory.getBeansOfType(BeanDefinitionRegistryPostProcessor.class, true, false);
        List<BeanDefinitionRegistryPostProcessor> registryPostProcessorBeans =
                new ArrayList<BeanDefinitionRegistryPostProcessor>(beanMap.values());
        OrderComparator.sort(registryPostProcessorBeans);
        for (BeanDefinitionRegistryPostProcessor postProcessor : registryPostProcessorBeans) {

            //!!!!! BeanDefinitionRegistryPostProcessors are excecuted!!!!!
            postProcessor.postProcessBeanDefinitionRegistry(registry);
        }
        invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(registryPostProcessorBeans, beanFactory);
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        processedBeans.addAll(beanMap.keySet());
    }
    else {
        // Invoke factory processors registered with the context instance.
        invokeBeanFactoryPostProcessors(getBeanFactoryPostProcessors(), beanFactory);
    }

    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let the bean factory post-processors apply to them!
    String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

    // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    List<String> orderedPostProcessorNames = new ArrayList<String>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
    for (String ppName : postProcessorNames) {