【问题标题】:Spring boot XmlBeanDefinitionReader not working properlySpring Boot XmlBeanDefinitionReader 无法正常工作
【发布时间】:2019-01-23 14:17:46
【问题描述】:

我正在创建具有两个子模块的 Maven 多模块。一个是具有数据库存储库的简单 DAO 层,另一个是 Spring Boot 应用程序,它是命令行应用程序。我正在使用 mongodb 和 spring-data-monodb 作为数据库。当我使用 xml config as 配置 mongodb 时

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mongo="http://www.springframework.org/schema/data/mongo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd">

    <bean id="mongoTemplate" 
    class="org.springframework.data.mongodb.core.MongoTemplate">
        <constructor-arg ref="mongoClient" />
        <constructor-arg name="databaseName" value="test" />
    </bean>

    <mongo:mongo-client id="mongoClient" 
    credentials="username:password@source" replica-set="server1uri:27017,server2uri:27017,server3uri:27017" >
        <mongo:client-options connections-per-host="50" threads-allowed-to-block-for-connection-multiplier="5000" ssl="true" />
    </mongo:mongo-client>

</beans>

它工作正常。我已经在 dao 模块中定义了这个文件,并在 SpringBootApplication 上使用 @ImportResource 在 Spring Boot 模块中使用它,它工作正常。

现在我需要在运行 spring boot jar (java -jar app.jar /path/to/bean.xml) 时将此文件作为命令行参数提供。我所做的是,我在 SpringBootApplication 中实现了 CommandLineRunner,并在该方法中使用 XmlBeanDefinitionReader 加载上述 xml 文件。

    @SpringBootApplication
    public class Application implements CommandLineRunner {

    @Autowired
    private GenericApplicationContext applicationContext;

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        if (args.length == 0 ) {
            System.out.println("Provide path for mongodb connection file");
            return;
        }

        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);

        Resource beanFile = new FileSystemResource(args[0]);
        xmlBeanDefinitionReader.loadBeanDefinitions(beanFile);

        // Rest of logic.
    }
}

然后它不能正确地投射 mongo 凭据。它抛出以下错误。

Caused by: java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'com.mongodb.MongoCredential' for property 'credentials[0]': no matching editors or conversion strategy found

不知何故,它无法转换凭据。我正在使用 spring boot 2.0.2.RELEASE

【问题讨论】:

    标签: java spring spring-boot


    【解决方案1】:

    CommandLineRunner来不及在spring中注册bean定义,所以我们需要实现BeanFactoryPostProcessor来加载bean定义xml,下面的代码我没有完全测试,你可以做到给我反馈

    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.core.io.FileSystemResource;
    import org.springframework.core.io.Resource;
    import org.springframework.data.mongodb.config.MongoCredentialPropertyEditor;
    
    @SpringBootApplication
    public class Application implements BeanFactoryPostProcessor {
        private static String xmlFile;
        public static void main(String[] args) throws Exception {
            if (args.length == 0 ) {
                System.out.println("Provide path for mongodb connection file");
                return;
            }
            xmlFile = args[0];
            SpringApplication.run(Application.class, args);
        }
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
            if (configurableListableBeanFactory instanceof BeanDefinitionRegistry) {
                XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader((BeanDefinitionRegistry)configurableListableBeanFactory);
    
                Resource beanFile = new FileSystemResource(Application.xmlFile);
                xmlBeanDefinitionReader.loadBeanDefinitions(beanFile);
               try {
                configurableListableBeanFactory.registerCustomEditor(Class.forName("[Lcom.mongodb.MongoCredential;"), MongoCredentialPropertyEditor.class);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            }
        }
    }
    

    【讨论】:

    • 当然,我会测试并提供反馈。谢谢
    • 我给你这个问题的解决方法,请再测试一下
    【解决方案2】:

    你应该实现BeanDefinitionRegistryPostProcessor,这样bean注册越早

    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
    import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.core.io.FileSystemResource;
    import org.springframework.core.io.Resource;
    
    @SpringBootApplication
    public class Application implements BeanDefinitionRegistryPostProcessor {
    
        private static String xmlFile;
        public static void main(String[] args) throws Exception {
            if (args.length == 0 ) {
                System.out.println("Provide path for mongodb connection file");
                return;
            }
            xmlFile = args[0];
            SpringApplication.run(MongoApplication.class, args);
        }
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        }
    
        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
                XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(registry);
                Resource beanFile = new FileSystemResource(Application.xmlFile);
                xmlBeanDefinitionReader.loadBeanDefinitions(beanFile);
        }
    }
    

    【讨论】:

    • 我觉得这个答案比上面那个好
    • 谢谢。我会再试一次并通知你。
    • @MaheshBhuva 这个问题有什么进展吗?
    • 我确实修复了这个问题,所以可能还有其他问题,如果你能在github上创建一个demo项目,我想我可以帮助你更多
    • 好的,有时间我会上传的,会通知你的。感谢您的帮助。
    猜你喜欢
    • 2021-11-02
    • 2020-02-09
    • 2021-11-10
    • 2018-09-23
    • 1970-01-01
    • 2015-04-20
    • 2016-09-16
    • 1970-01-01
    • 2023-04-08
    相关资源
    最近更新 更多