首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何从应用程序上下文编程创建spring xml配置文件?

如何从应用程序上下文编程创建spring xml配置文件?
EN

Stack Overflow用户
提问于 2017-04-10 08:50:42
回答 1查看 2.9K关注 0票数 0

我已经以语法的方式在spring应用程序上下文中加载了bean定义。(xml配置为空)。我需要在这里做反向处理。目前,我已经加载了带有bean定义的上下文。现在,我想将这些转换为xml配置文件。有人知道怎么做吗?

下面给出的是样例方法.

代码语言:javascript
运行
复制
static ApplicationContext appContext = new ClassPathXmlApplicationContext("beans.xml"); //beans.xml has no bean definitions
AutowireCapableBeanFactory factory = appContext.getAutowireCapableBeanFactory();
BeanDefinitionRegistrry registry = (BeanDefinitionRegistry) factory;
GenericBeanDefinition beanDefinition;

public void registerBeanDefintions(List<SimpleField> simpleFields) {
if (null != simpleFields) {
String beanId;
for (SimpleField simpleField : simpleFields) {
beanId = simpleField.getDataField().replace(".", "_");
beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(SimpleField.class);
beanDefinition.setAutowireCandidate(true);
MutablePropertyValues values = new MutablePropertyValues();
values.add("engineFields", simpleField.getEngineFields());
values.add("dataField", simpleField.getDataField());
values.add("fieldDataType", simpleField.getFieldDataType());
values.add("setDefaultValueIfNull", simpleField.getSetDefaultValueIfNull());
beanDefinition.setPropertyValues(values);
if (!factory.containsBean(beanId)) {
registry.registerBeanDefinition(beanId, beanDefinition);                factory.autowireBeanProperties(this,AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
}}}}

beans.xml

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">



</beans>

加载的bean可以作为appContext.getBean("beanName")访问。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-04-24 10:34:47

最后,解决办法在这里!让我们来看看吧。

问题陈述

众所周知,在spring应用程序中,我们通过‘ApplicationContext’提供配置信息。spring框架提供了多个类来实现这个接口,并帮助我们在应用程序中使用配置信息,ClassPathXmlApplicationContext就是其中之一。通常,在这种情况下,所有bean定义都配置在一个独立的xml文件中,通常称为‘application-context.xml’。

但是,在较大的项目结构中,最好的做法是保留多个spring配置文件,以便于维护和模块化,而不是将所有内容堆积到一个文件中。在这种情况下,最好的做法是将所有Spring配置文件组织到一个XML文件中,并在其中导入整个文件。此外,在应用程序上下文中,我们加载了这个单个xml文件。

如果要创建的配置文件的数量过大,那么现在怎么办?例如,接近100或更多?

这是一个乏味的工作和蜗牛一样的工作!是时候找到一条自动执行此过程的路径了。让我们考虑一个场景,在外部源中有所有必需的数据,例如,excel表。现在,我们需要从表中读取数据,并自发生成近100个弹簧配置文件。

如何自动化这个过程?JAXB到救援

JAXB有一个绑定编译器。JAXB模式绑定编译器将源XML模式转换或绑定到Java编程语言中的一组JAXB内容类。

  1. 查找要生成的xml中需要引用的xml模式-http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  2. 在浏览器中点击这个url以获得xsd。现在将其保存在某个位置(如spring.xsd)。
  3. 下载jaxbri包和设置maven项目的环境路径变量.In情况,包括jaxb-ri和jaxb-core的依赖项。
  4. 从存在xjc.exe spring.xsd的文件夹中执行命令spring.xsd。这将生成与xsd关联的类。

如果在执行命令时发生了‘属性已定义’错误,需要做什么?

很可能会出现这样一个例外,即“属性已经定义”。如果是这样,则可以通过创建绑定文件来解决此问题,以覆盖抛出异常的属性。

绑定文件

代码语言:javascript
运行
复制
<jxb:bindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    version="1.0">

    <jxb:bindings schemaLocation="http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" node="/xs:schema">

<!-- Resolve:
[ERROR] Property "Ref" is already defined. Use &lt;jaxb:property> to resolve this conflict.
  line 975 of file:/home/dw/sandbox/BRZtests/src/jaxb/spring25.xsd

[ERROR] Property "Value" is already defined. Use &lt;jaxb:property> to resolve this conflict.
  line 977 of file:/home/dw/sandbox/BRZtests/src/jaxb/spring25.xsd
  -->
        <jxb:bindings node="//xs:complexType[@name='propertyType']">
            <jxb:bindings node=".//xs:attribute[@name='ref']">
                <jxb:property name="refAttribute"/>
            </jxb:bindings>
            <jxb:bindings node=".//xs:attribute[@name='value']">
                <jxb:property name="valueAttribute"/>
            </jxb:bindings>
        </jxb:bindings>
<!--
[ERROR] Property "Ref" is already defined. Use &lt;jaxb:property> to resolve this conflict.
  line 577 of file:/home/dw/sandbox/BRZtests/src/jaxb/spring25.xsd

[ERROR] The following location is relevant to the above error
  line 606 of file:/home/dw/sandbox/BRZtests/src/jaxb/spring25.xsd

[ERROR] Property "Value" is already defined. Use &lt;jaxb:property> to resolve this conflict.
  line 579 of file:/home/dw/sandbox/BRZtests/src/jaxb/spring25.xsd

[ERROR] The following location is relevant to the above error
  line 613 of file:/home/dw/sandbox/BRZtests/src/jaxb/spring25.xsd

-->
        <jxb:bindings node="//xs:element[@name='constructor-arg']">
            <jxb:bindings node=".//xs:attribute[@name='ref']">
                <jxb:property name="refAttribute"/>
            </jxb:bindings>
            <jxb:bindings node=".//xs:attribute[@name='value']">
                <jxb:property name="valueAttribute"/>
            </jxb:bindings>
        </jxb:bindings>

<!--
[ERROR] Property "Key" is already defined. Use &lt;jaxb:property> to resolve this conflict.
  line 1063 of file:/home/dw/sandbox/BRZtests/src/jaxb/spring25.xsd

[ERROR] The following location is relevant to the above error
  line 1066 of file:/home/dw/sandbox/BRZtests/src/jaxb/spring25.xsd
-->
        <jxb:bindings node="//xs:complexType[@name='entryType']">
            <jxb:bindings node=".//xs:attribute[@name='key']">
                <jxb:property name="keyAttribute"/>
            </jxb:bindings>
        </jxb:bindings>
    </jxb:bindings>
</jxb:bindings>

使用下面的命令解析架构并生成类。

-b spring25.xjb -verbose -xmlschema http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

与xsd关联的所有类都是generated.Now,创建一个Bean实例并对其进行马歇尔。这将生成具有所需输出的xml文件。

示例代码-在生成的类文件夹中创建的测试类

代码语言:javascript
运行
复制
package org.springframework.schema.beans;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URISyntaxException;
import java.util.ArrayList;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.namespace.QName;

import org.springframework.util.CollectionUtils;

import com.hrb.leap.bean.SpringConfigGenerator;

public class Test {
    public static void main(String[] args) throws JAXBException {
        ObjectFactory factory = new ObjectFactory();
        JAXBContext context = JAXBContext.newInstance("org.springframework.schema.beans");

        /*
         * Create the root element 'Beans'
         * Set the required schema properties
         */
        Beans rootElement = factory.createBeans();
        rootElement.getOtherAttributes().put(new QName("xmlns:xsi"), "http://www.w3.org/2001/XMLSchema-instance");
        rootElement.getOtherAttributes().put(new QName("xsi:schemaLocation"), "http://www.springframework.org/schema/beans spring-beans-3.2.xsd");

        /*
         * How to import resources
         * How to define list of reference beans
         */
        java.util.List<String> resources = new ArrayList<>();
        resources.add("ResourceOne");
        resources.add("ResourceTwo");
        resources.add("ResourceThree");

        resources.forEach(resourceName -> {
            Import importResource = new Import();
            importResource.setResource(resourceName+".xml");
            rootElement.getImportOrAliasOrBean().add(importResource);
        });

        Bean bean = factory.createBean();
        bean.setId("id");
        bean.setClazz("java.util.ArrayList");
        if (!CollectionUtils.isEmpty(resources)) {
            ConstructorArg constructorArgs = factory.createConstructorArg();
            org.springframework.schema.beans.List listOfResources = new org.springframework.schema.beans.List();
            resources.forEach(referenceFormName -> {
                Ref refBean = new Ref();
                refBean.setBean(referenceFormName);
                listOfResources.getBeanOrRefOrIdref().add(refBean);
            });
            constructorArgs.setList(listOfResources);
            bean.getMetaOrConstructorArgOrProperty().add(constructorArgs);
        }
        rootElement.getImportOrAliasOrBean().add(bean);

        /*
         * Sample bean definition to show how to store list of values as a property
         */
            Bean simpleBean = factory.createBean();
            simpleBean.setId("SimpleBean");
            simpleBean.setClazz("com.packagename.ClassName");

            PropertyType firstProperty= factory.createPropertyType();
            firstProperty.setName("listOfValuesDemo");

            java.util.List<String> listOfValues = new ArrayList<>();
            listOfValues.add("ValueOne");
            listOfValues.add("ValueTwo");
            listOfValues.add("ValueThree");

            org.springframework.schema.beans.List listToStoreValues = new org.springframework.schema.beans.List();
            listOfValues.forEach(name -> {
                 Value value = factory.createValue();
                 value.getContent().add(name);
                 listToStoreValues.getBeanOrRefOrIdref().add(value);
             });
            firstProperty.setList(listToStoreValues);
            //Add the property to the bean.
            simpleBean.getMetaOrConstructorArgOrProperty().add(factory.createProperty(firstProperty));
            // Add the bean under the root element 'beans'
            rootElement.getImportOrAliasOrBean().add(simpleBean);

        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty("jaxb.formatted.output",Boolean.TRUE);
        createXmlConfiguration(marshaller , "output", rootElement);
    }

    /*
     * Method create the xml under the 'src/main/resources' folder in the project.
     */
    public static void createXmlConfiguration (Marshaller marshaller , String fileName, Beans rootElement) {
        try {
            java.net.URL url = SpringConfigGenerator.class.getResource("/");
            File fullPathToSubfolder = new File(url.toURI()).getAbsoluteFile();
            String projectFolder = fullPathToSubfolder.getAbsolutePath().split("target")[0];
            // TODO - Destination folder to be configured
            File outputFile = new File(projectFolder + "src/main/resources/" + "/"+fileName+".xml");
            if (!outputFile.exists()) {
                outputFile.createNewFile();
            }
            OutputStream os = new FileOutputStream(outputFile);
            marshaller.marshal(rootElement, os);
        } catch (URISyntaxException uriException) {

        } catch (IOException ioException) {

        } catch (JAXBException jaxbException) {

        }

    }
}

输出

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<beans xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans spring-beans-3.2.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <import resource="ResourceOne.xml"/>
    <import resource="ResourceTwo.xml"/>
    <import resource="ResourceThree.xml"/>
    <bean class="java.util.ArrayList" id="id">
        <constructor-arg>
            <list>
                <ref bean="ResourceOne"/>
                <ref bean="ResourceTwo"/>
                <ref bean="ResourceThree"/>
            </list>
        </constructor-arg>
    </bean>
    <bean class="com.packagename.ClassName" id="SimpleBean">
        <property name="listOfValuesDemo">
            <list>
                <value>ValueOne</value>
                <value>ValueTwo</value>
                <value>ValueThree</value>
            </list>
        </property>
    </bean>
</beans>

按照以下步骤查看示例输出

  1. 点击浏览器中的架构url以获得xsd。现在将其保存在某个位置(例如:- spring.xsd)。
  2. 下载jaxbri包和设置环境路径变量。
  3. 设置jaxb库的类路径和当前路径(点),如示例(在IDE中执行此命令、提示符或相等)设置classpath =C:\文件夹_name\jaxb-ri\lib;;
  4. 将生成的类解压缩到下面命令运行的文件夹(从cmd中提取的文件夹)之后,编译‘Test’类。javac folder_name\Test.java
  5. 最后运行程序。如果‘createXmlConfiguration(封送组,“输出”,rootElement)替换为’marshaller.marshal(rootElement,System.out);‘,则输出将在控制台中打印。

优势

  • 工作大大减少了。考虑到我必须手动配置bean定义的复杂性,一个人至少需要20-25天才能配置近85个文件(考虑9小时/天),这将占225小时。然而,上面的工具将花费不到3秒的时间来完成。
  • 如果将来需要做一些小的配置更改,我们可以单独处理特定的文件并进行更正。

替代方法

如果配置文件的数量非常少,我们可以尝试动态加载所有bean定义的上下文,而无需生成物理xml文件。这可以通过编程方式加载spring上下文来实现,并在需要时运行应用程序。

缺点

  • 内存
  • 性能
  • 数据源中的小错误会产生很大的影响。
  • 在生产环境中运行是危险的,在飞行中。
  • 不建议,如果数据源仍然几乎未被触及。
  • 很难排除。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43318683

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档