프로그래밍 방식으로 애플리케이션 컨텍스트에서 Spring XML 구성 파일을 만드는 방법은 무엇입니까?

스리 데비 사라 스

나는 스프링 애플리케이션 컨텍스트에 프로그래밍 방식으로 빈 정의를로드했다. (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);
}}}}

beans.xml

<?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 컨텐츠 클래스 세트로 변환하거나 바인드합니다.

  1. 생성 할 xml에서 참조해야하는 xml 스키마를 찾으십시오 ( http://www.springframework.org/schema/beans/spring-beans-3.0.xsd) .
  2. xsd를 얻으려면 브라우저에서이 URL을 누르십시오. 이제 특정 위치 (예 : spring.xsd)에 저장하십시오.
  3. jaxbri 패키지를 다운로드하고 환경 경로 변수를 설정합니다. Maven 프로젝트의 경우 jaxb-ri 및 jaxb-core에 대한 종속성을 포함합니다.
  4. spring.xsd가있는 폴더에서 xjc.exe spring.xsd 명령을 실행하십시오. 이것은 xsd와 관련된 클래스를 생성합니다.

명령 실행 중 '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 &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>

아래 명령을 사용하여 스키마를 구문 분석하고 클래스를 생성하십시오.

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>

샘플 출력을 보려면 아래 단계를 따르십시오.

  1. xsd를 얻으려면 브라우저에서 스키마 URL을 누르십시오. 이제 어떤 위치 (예 : spring.xsd)에 저장하십시오.
  2. jaxbri 패키지를 다운로드하고 환경 경로 변수를 설정합니다.
  3. jaxb 라이브러리의 클래스 경로 및 현재 경로 (점)를 예제와 같이 설정합니다 (이 명령 프롬프트 또는 IDE에서 동일 함) set classpath = C : \ folder_name \ jaxb-ri \ lib;.;
  4. 생성 된 클래스를 cmd의 압축을 푼 폴더에서 아래 명령을 실행하여 폴더에 추출한 후 'Test'클래스를 컴파일합니다. javac folder_name \ Test.java
  5. 마지막으로 프로그램을 실행하십시오. java folder_name.Test 참고 :- 'createXmlConfiguration (marshaller, "output", rootElement);'인 경우 출력이 콘솔에 인쇄됩니다. 'marshaller.marshal (rootElement, System.out);'으로 대체됩니다.

장점

  • 노력이 상당히 줄어 듭니다. 수동으로 구성해야하는 Bean 정의의 복잡성을 고려할 때, 한 사람이 85 개에 가까운 파일 (하루 9 시간 고려)을 구성하는 데 최소 20-25 일이 걸렸을 것입니다. 이는 225 시간에 해당합니다. 그러나 위의 도구를 사용하면 3 초도 채 걸리지 않습니다.
  • 나중에 수행 할 사소한 구성 변경이있는 경우 특정 파일 만 가져 와서 수정할 수 있습니다.

대체 접근법

구성 파일 수가 매우 적 으면 실제 xml 파일을 생성하지 않고 즉시 모든 빈 정의가 포함 된 컨텍스트를로드 할 수 있습니다. 이는 프로그래밍 방식으로 스프링 컨텍스트를로드하고 필요할 때 애플리케이션을 실행하여 달성 할 수 있습니다.

단점

  • 기억
  • 공연
  • 데이터 소스의 사소한 실수는 큰 영향을 미칩니다.
  • 프로덕션 환경에서 즉시 실행하는 것은 위험합니다.
  • 데이터 소스가 거의 변경되지 않은 경우 권장되지 않습니다.
  • 문제를 해결하기 어려울 것입니다.

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

Related 관련 기사

뜨겁다태그

보관