我已经在spring spring应用程序上下文中以编程方式加载了bean定义。 (xml配置为空)。我需要在这里做相反的过程。目前我已经使用bean定义加载了上下文。现在我想将这些转换为xml配置文件。 有人知道怎么做吗?
下面给出的是样本方法。
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);
}}}}
<?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(&#34; beanName&#34;)访问。
答案 0 :(得分:0)
最后,解决方案就在这里!我们来看看吧。
问题陈述
众所周知,在spring应用程序中,我们通过'ApplicationContext'提供配置信息。 Spring框架提供了多个类来实现此接口,并帮助我们在应用程序中使用配置信息,而ClassPathXmlApplicationContext就是其中之一。通常在这种情况下,所有bean定义都在一个独立的xml文件中配置,通常称为“application-context.xml”。
但是,在较大的项目结构中,最佳做法是保留多个弹簧配置文件,以便于将所有内容堆叠到一个文件中,从而易于维护和模块化。在这种情况下,最好的办法是将所有Spring bean配置文件组织到一个XML文件中,然后导入其中的所有文件。此外,在应用程序上下文中,我们加载此单个xml文件。
现在如果要创建的配置文件数量超大怎么办?比方说,接近100或更多?
现在这是一个单调乏味的蜗牛工作!是时候找到自动化这个过程的路径了。 让我们想一想我们在外部源中拥有所有必需数据的情况,例如excel表。现在我们需要从工作表中读取数据并自动生成接近100个弹簧配置文件。
如何自动执行此流程? JAXB救援
JAXB有一个绑定编译器。 JAXB XJC模式绑定编译器将源XML模式转换或绑定到Java编程语言中的一组JAXB内容类。
执行命令时,如果“已定义属性”错误,需要执行哪些操作?
可能会出现一个例外情况,即“已定义属性”。如果是这样,可以通过创建绑定文件来解决该问题,以覆盖抛出异常的属性。
绑定文件
<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 <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 <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 <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 <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 <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>
使用以下命令解析架构并生成类。
xjc -b spring25.xjb -verbose -xmlschema http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
将生成与xsd关联的所有类。现在创建一个Bean实例并对其进行编组。这将生成带有所需输出的xml文件。
示例代码 - 在生成的类的文件夹中创建的测试类
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) {
}
}
}
<强>输出强>
<?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>
按照以下步骤查看示例输出
<强>优点强>
替代方法
如果配置文件的数量非常少,我们可以尝试动态加载具有所有bean定义的上下文,而不生成物理xml文件。这可以通过以编程方式加载spring上下文来实现,并在需要时运行应用程序。
缺点