próbuje wymyślić ładnym rozwiązaniem tego sobie, że
- kręci się wokół tworzenia XSD dla pliku konfiguracyjnym - ponieważ w mojej głowie cały zaletą korzystania z XML jest to, że można mocno wpisać plik konfiguracyjny pod względem typów danych i pól, które są obowiązkowe/opcjonalne
- Sprawdza poprawność kodu XML w stosunku do XSD, więc jeśli brakuje wartości, wygeneruje błąd, zamiast wstrzykiwania komponentu bean z wartością "null" "
- Nie polega na adnotacjach wiosennych (takich jak @Value - w moim umyśle daje to wiedzę o fasoli na temat ut ich pojemnik + relacja z innymi ziarnami, więc łamie IOC)
- Sprawdza wartość sprężyny XML względem XSD, więc jeśli spróbujesz odwołać się do pola XML nieobecnego w XSD, to wyrzuci on również błąd
- Ziarno nie ma wiedzy, że jego wartości właściwości są wstrzykiwane z XML (np. Chcę wstrzyknąć poszczególne właściwości, a nie obiekt XML jako całość)
To, co wymyśliłem, to tak, jak poniżej, przeprosiny są dość długie, ale podoba mi się to jako rozwiązanie, ponieważ uważam, że obejmuje wszystko. Mam nadzieję, że może się to okazać przydatne dla kogoś. Pierwsze kawałki trywialne:
Fasola Chcę wartości nieruchomości wstrzykiwane do:
package com.ndg.xmlpropertyinjectionexample;
public final class MyBean
{
private String firstMessage;
private String secondMessage;
public final String getFirstMessage()
{
return firstMessage;
}
public final void setFirstMessage (String firstMessage)
{
this.firstMessage = firstMessage;
}
public final String getSecondMessage()
{
return secondMessage;
}
public final void setSecondMessage (String secondMessage)
{
this.secondMessage = secondMessage;
}
}
klasy testowym stworzyć powyższy fasoli i zrzucić wartości właściwości to otrzymała:
package com.ndg.xmlpropertyinjectionexample;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public final class Main
{
public final static void main (String [] args)
{
try
{
final ApplicationContext ctx = new ClassPathXmlApplicationContext ("spring-beans.xml");
final MyBean bean = (MyBean) ctx.getBean ("myBean");
System.out.println (bean.getFirstMessage());
System.out.println (bean.getSecondMessage());
}
catch (final Exception e)
{
e.printStackTrace();
}
}
}
MyConfig.xsd :
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:myconfig="http://ndg.com/xmlpropertyinjectionexample/config" targetNamespace="http://ndg.com/xmlpropertyinjectionexample/config">
<xsd:element name="myConfig">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="1" maxOccurs="1" name="someConfigValue" type="xsd:normalizedString" />
<xsd:element minOccurs="1" maxOccurs="1" name="someOtherConfigValue" type="xsd:normalizedString" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Próbka MyConfig.xml plik na podstawie XSD:
<?xml version="1.0" encoding="UTF-8"?>
<config:myConfig xmlns:config="http://ndg.com/xmlpropertyinjectionexample/config">
<someConfigValue>First value from XML file</someConfigValue>
<someOtherConfigValue>Second value from XML file</someOtherConfigValue>
</config:myConfig>
fragment pliku pom.xml do uruchomienia xsd2java (nie było nic innego tu oprócz ustawienie Java 1.6, a zależność wiosna-context): Sam
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<executions>
<execution>
<id>main-xjc-generate</id>
<phase>generate-sources</phase>
<goals><goal>generate</goal></goals>
</execution>
</executions>
</plugin>
Teraz XML wiosny. Stwarza to schematu/walidatora, a następnie wykorzystuje JAXB stworzyć unmarshaller stworzyć POJO z pliku XML, a następnie wykorzystuje wiosna # adnotacji wstrzyknąć wartości nieruchomości przez quering z POJO:
<?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.2.xsd" >
<!-- Set up schema to validate the XML -->
<bean id="schemaFactory" class="javax.xml.validation.SchemaFactory" factory-method="newInstance">
<constructor-arg value="http://www.w3.org/2001/XMLSchema"/>
</bean>
<bean id="configSchema" class="javax.xml.validation.Schema" factory-bean="schemaFactory" factory-method="newSchema">
<constructor-arg value="MyConfig.xsd"/>
</bean>
<!-- Load config XML -->
<bean id="configJaxbContext" class="javax.xml.bind.JAXBContext" factory-method="newInstance">
<constructor-arg>
<list>
<value>com.ndg.xmlpropertyinjectionexample.config.MyConfig</value>
</list>
</constructor-arg>
</bean>
<bean id="configUnmarshaller" class="javax.xml.bind.Unmarshaller" factory-bean="configJaxbContext" factory-method="createUnmarshaller">
<property name="schema" ref="configSchema" />
</bean>
<bean id="myConfig" class="com.ndg.xmlpropertyinjectionexample.config.MyConfig" factory-bean="configUnmarshaller" factory-method="unmarshal">
<constructor-arg value="MyConfig.xml" />
</bean>
<!-- Example bean that we want config properties injected into -->
<bean id="myBean" class="com.ndg.xmlpropertyinjectionexample.MyBean">
<property name="firstMessage" value="#{myConfig.someConfigValue}" />
<property name="secondMessage" value="#{myConfig.someOtherConfigValue}" />
</bean>
</beans>
To zdecydowanie przydatny wiedzieć, a będzie przydatnym wsparciem.Domyślam się, że łatwo jest przesłonić PropertiesPersister, aby zaimplementować parsowanie stylu Apache Digester, zamiast standardowego formatu XML właściwości. – GaryF
Co trzeba zrobić, aby utworzyć coś, co ładuje niestandardowe (nie własności) pliki xml przy użyciu modułów ładujących zasoby? –