은 여기 간단한 예제 프로그램이 있습니다스프링 빈 객체 마샬링은 XML에 주어진 순서에 따라 달라 집니까?
package com.test;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class Main {
public static void main(String[] args) throws InterruptedException {
try {
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("TestBeanFile.xml");
Object o = context.getBean("AInstance");
}
catch (Throwable e) {
e.printStackTrace();
}
Thread.sleep(Long.MAX_VALUE);
}
private static class A implements InitializingBean {
private B myB;
public A() {
System.out.println("A constructor");
}
public void setB(B aB) {
myB = aB;
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("A aps");
}
}
private static class B implements Runnable, InitializingBean {
private C myC;
private volatile boolean exit = false;
public B() {
System.out.println("B constructor");
}
public void setC(C aC) {
myC = aC;
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("B aps");
if (myC == null) throw new IllegalArgumentException("C cannot be null");
new Thread(this).start();
}
public void exit() {
exit = true;
}
@Override
public void run() {
while (!exit) {
System.out.println(myC.getValue());
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private static class C implements InitializingBean {
private String value = "C's value";
public C() {
System.out.println("C constructor");
}
public String getValue() {
return value;
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("C aps");
}
}
}
을 그리고 여기에 콩에 대한 간단한 XML 의도적으로 클래스에 잘못된 완전한 이름을 가지고있는 그들을로드입니다. 이것은 C B와 A가 만들어지지 않는다는 것을 의미합니다.
<?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:int="http://www.springframework.org/schema/integration"
xmlns:int-stream="http://www.springframework.org/schema/integration/stream"
xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
http://www.springframework.org/schema/integration/stream http://www.springframework.org/schema/integration/stream/spring-integration-stream-2.1.xsd
http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip-2.1.xsd">
<bean id="CInstance" class = "com.test.Main.C" />
<bean id="BInstance" class = "com.test.Main.B">
<property name="C" ref="CInstance" />
</bean>
<bean id="AInstance" class = "com.test.Main.A1">
<property name="B" ref="BInstance"/>
</bean>
</beans>
위의 XML C 및 B를 사용하여이 응용 프로그램을 실행하면 A가 생성되지만 A는 생성되지 않습니다. 그것은 다음과 같은 출력을 생성합니다 (예외가 슬로우되면 스택 추적을 생략을,하지만 난 당신이 A는 건설되지 않습니다 보장) :
C constructor
C aps
B constructor
B aps
C's value
C's value
C's value
....... // one a second
이 같이하기 위해 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" xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-stream="http://www.springframework.org/schema/integration/stream"
xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
http://www.springframework.org/schema/integration/stream http://www.springframework.org/schema/integration/stream/spring-integration-stream-2.1.xsd
http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip-2.1.xsd">
<bean id="AInstance" class = "com.test.Main.A1">
<property name="B" ref="BInstance"/>
</bean>
<bean id="BInstance" class = "com.test.Main.B">
<property name="C" ref="CInstance" />
</bean>
<bean id="CInstance" class = "com.test.Main.C" />
</beans>
유일한 출력은 스택 추적이며 B 및 C 개체는 전혀 생성되지 않습니다.
이것은 봄에 벌레처럼 보입니다. 개체의 마샬링 및 XML에서 나타나는 순서에 따라 실행되는 생성자/afterpropertiesSet 메서드가 왜 이해가 안되는지. 이것이 나를 위해 무엇을 의미하는지, 그 클래스의 생성자/속성을 설정 한 후에 스레드를 구성 할 때 XML의 요소를 어떻게 정렬하는지 조심하지 않으면 리소스가 누출 될 수 있습니다. 이 예제에서는 A 클래스입니다. 왜냐하면 두 경우 모두 공사가 실패하기 때문입니다.
이렇게 버그입니까? 이해할 수없는 기능입니까? 이것이 기능이라면 bean 정의의 객체 그래프 대신에 XML 파일에 의존하여 마샬링 명령을 내리는 데 어떤 이유가 있을까요?
'com.test.Main.A'가 아니라'com.test.Main.A1'이 될 수 있습니까? – mkobit
@MikeKobit 그 의도는 의도적입니다. 이 예제는 빈 AInstance에 대한 잘못된 정규화 된 이름으로 인해 이러한 오브젝트를 작성해서는 안된다는 것을 demostrates합니다. 그러나 내가 주문하는 방법에 따라, 어쨌든 봄이 B와 C 클래스를 구성 할 가능성이 있습니다. –