나는 스프링 애플리케이션 컨텍스트에 프로그래밍 방식으로 빈 정의를로드했다. (xml 구성이 비어 있습니다). 여기서 역방향 프로세스를 수행해야합니다. 현재 나는 빈 정의와 함께로드 된 컨텍스트를 가지고있다. 이제이를 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 ( "beanName")으로 액세스 할 수 있습니다.
마지막으로 해결책이 여기 있습니다 !!! 확인 해보자.
문제 설명
우리 모두 알다시피 Spring 애플리케이션에서는 'ApplicationContext'를 통해 구성 정보를 제공합니다. 이 인터페이스를 구현하고 애플리케이션에서 구성 정보를 사용하는 데 도움이되는 스프링 프레임 워크에서 제공하는 여러 클래스가 있으며 ClassPathXmlApplicationContext가 그중 하나입니다. 일반적으로이 경우 모든 빈 정의는 일반적으로 'application-context.xml'이라고하는 단일 독립형 xml 파일에 구성됩니다.
그러나 더 큰 프로젝트 구조에서 가장 좋은 방법은 모든 것을 하나의 파일에 쌓는 것보다 쉬운 유지 관리 및 모듈화를 위해 여러 스프링 구성 파일을 유지하는 것입니다. 이 경우 가장 좋은 방법은 모든 Spring bean 구성 파일을 단일 XML 파일로 구성하고 그 안에 전체 파일을 가져 오는 것입니다. 또한 애플리케이션 컨텍스트에서이 단일 xml 파일을로드합니다.
이제 생성 할 구성 파일의 수가 너무 많으면 어떨까요? 예를 들어 100에 가깝거나 그 이상?
이제 그것은 겸손하고 달팽이와 같은 직업입니다! 이 프로세스를 자동화 할 경로를 찾을 때입니다. 엑셀 시트와 같은 외부 소스에 필요한 모든 데이터가있는 시나리오를 생각해 봅시다. 이제 시트에서 데이터를 읽고 자발적으로 100 개에 가까운 스프링 구성 파일을 생성해야합니다.
이 프로세스를 자동화하는 방법은 무엇입니까? 구조에 JAXB
JAXB에는 바인딩 컴파일러가 있습니다. JAXB XJC 스키마 바인딩 컴파일러는 소스 XML 스키마를 Java 프로그래밍 언어의 JAXB 컨텐츠 클래스 세트로 변환하거나 바인드합니다.
명령 실행 중 'Property is already defined'오류가 발생하면 어떻게해야합니까?
'속성이 이미 정의되었습니다'라는 예외가 발생할 수 있습니다. 그렇다면 예외가 발생한 속성을 재정의하기 위해 바인딩 파일을 만들어 문제를 해결할 수 있습니다.
바인딩 파일
<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>
샘플 출력을 보려면 아래 단계를 따르십시오.
장점
대체 접근법
구성 파일 수가 매우 적 으면 실제 xml 파일을 생성하지 않고 즉시 모든 빈 정의가 포함 된 컨텍스트를로드 할 수 있습니다. 이는 프로그래밍 방식으로 스프링 컨텍스트를로드하고 필요할 때 애플리케이션을 실행하여 달성 할 수 있습니다.
단점
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다