カスタムラベルの解析
1.カスタムラベルの解析
Springのラベルは標準ラベルとカスタムラベルの2種類に分けられています。以前は標準ラベルの解析を分析しました。Doccumentに設定ファイルを変換し、対応するrootを抽出した後、すべての要素の解析を開始しました。ここで解析すると、デフォルトのラベルとカスタムラベルの2つの区分が始まります。ソースは以下の通りです。
カスタムラベル解析パーrseCustoomelement方法:
ラベルの解析は名前空間の提起から始まります。Springではデフォルトのラベルとカスタムラベルはラベルによって提供される名前空間に基づいています。org.w 3 c.dom.Nodeではすでに方法が提供されています。
名前空間があれば、Namespace Handlerの抽出ができます。Namespace Handler handler=this.reader Conttext.get Namespace HandlerResoliver()ここでDefault Namespace HandlerResolaverのresove方法を呼び出しました。
解析器と分析する元素を得ました。Springは解析作業をカスタム解像器に委託して、return handle.parse(ele,new PaserContext)を解析します。Namespace Handler Support.javaにおけるparse方法:
2.カスタムラベルの使用
多くの場合、開発にはシステムの構成化サポートが必要であり、最も簡単なのはSpringの標準beanに基づいて配置されていますが、配置が複雑で、またはより多くの豊富な制御が必要な場合、不器用に見えます。実現するのは比較的に煩わしい。Springは、拡張可能なSchemaのサポートを提供しています。Springを拡張するカスタムタグは、ステップ(Springのcoreパッケージが必要です)を設定する必要があります。1.拡張が必要なコンポーネントを作成します。2.XSDファイル記述コンポーネントの内容を定義します。3.ファイルを作成し、BenDefinitionParterインターフェースを実現して、XSDファイルの定義とコンポーネント定義を解析します。4.Handlerファイルを作成します。Namespace Handler Supportから拡張して、目的はコンポーネントをSpring容器5に拡張することです。Spring.handersとSpring.schemasファイルを作成します。
2.1通常のpojoオブジェクトを作成する:
クラスを作成して、XSDファイルの定義とコンポーネントの定義を解析するために、BeanDefinitionParsserインターフェースを実現します。
Handlerファイルを作成し、Namespace Handler Supportから拡張します。目的は、Spring容器にコンポーネントを登録するためです。
Spring.handers:
Springのラベルは標準ラベルとカスタムラベルの2種類に分けられています。以前は標準ラベルの解析を分析しました。Doccumentに設定ファイルを変換し、対応するrootを抽出した後、すべての要素の解析を開始しました。ここで解析すると、デフォルトのラベルとカスタムラベルの2つの区分が始まります。ソースは以下の通りです。
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for(int i = 0; i < nl.getLength(); ++i) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element)node;
if (delegate.isDefaultNamespace(ele)) {
//
this.parseDefaultElement(ele, delegate);
} else {
//
delegate.parseCustomElement(ele);
}
}
}
} else {
//
delegate.parseCustomElement(root);
}
}
上記のソースから分かります。Springが元素を手に入れた時、まず名前空間の解析を行いました。もしデフォルトの名前空間であれば、Parse DefaultElementを使って解析を行います。カスタムラベル解析パーrseCustoomelement方法:
public BeanDefinition parseCustomElement(Element ele) {
return this.parseCustomElement(ele, (BeanDefinition)null);
}
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
//
String namespaceUri = this.getNamespaceURI(ele);
// NameSpaceHandler
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
this.error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
} else {
// handler
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
}
1.1タグの名前空間を取得するラベルの解析は名前空間の提起から始まります。Springではデフォルトのラベルとカスタムラベルはラベルによって提供される名前空間に基づいています。org.w 3 c.dom.Nodeではすでに方法が提供されています。
public String getNameSpaceURI(Node node){
return node.getNameSpaceURI();
}
1.2カスタムラベルプロセッサを抽出する名前空間があれば、Namespace Handlerの抽出ができます。Namespace Handler handler=this.reader Conttext.get Namespace HandlerResoliver()ここでDefault Namespace HandlerResolaverのresove方法を呼び出しました。
public NamespaceHandler resolve(String namespaceUri) {
// handler
Map handlerMappings = this.getHandlerMappings();
//
Object handlerOrClassName = handlerMappings.get(namespaceUri);
if (handlerOrClassName == null) {
return null;
} else if (handlerOrClassName instanceof NamespaceHandler) {
// ,
return (NamespaceHandler)handlerOrClassName;
} else {
String className = (String)handlerOrClassName;
try {
//
Class> handlerClass = ClassUtils.forName(className, this.classLoader);
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri + "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
} else {
//
NamespaceHandler namespaceHandler = (NamespaceHandler)BeanUtils.instantiateClass(handlerClass);
// NamespaceHandler
namespaceHandler.init();
// 。
handlerMappings.put(namespaceUri, namespaceHandler);
return namespaceHandler;
}
} catch (ClassNotFoundException var7) {
throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "] not found", var7);
} catch (LinkageError var8) {
throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]: problem with handler class file or dependent class", var8);
}
}
}
get Handler Mappings()方法:private Map getHandlerMappings() {
if (this.handlerMappings == null) {
//
synchronized(this) {
if (this.handlerMappings == null) {
try {
//location META-INF
Properties mappings = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Loaded NamespaceHandler mappings: " + mappings);
}
// properties Map handMapping
Map handlerMappings = new ConcurrentHashMap(mappings.size());
CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
this.handlerMappings = handlerMappings;
} catch (IOException var5) {
throw new IllegalStateException("Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", var5);
}
}
}
}
return this.handlerMappings;
}
1.3ラベル解析:解析器と分析する元素を得ました。Springは解析作業をカスタム解像器に委託して、return handle.parse(ele,new PaserContext)を解析します。Namespace Handler Support.javaにおけるparse方法:
public BeanDefinition parse(Element element, ParserContext parserContext) {
//
return this.findParserForElement(element, parserContext).parse(element, parserContext);
}
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
// ,
操作の方法this.findParserForElement.parserContt.).parsepublic final BeanDefinition parse(Element element, ParserContext parserContext) {
// AbstractBeanDefinition
AbstractBeanDefinition definition = this.parseInternal(element, parserContext);
if (definition != null && !parserContext.isNested()) {
try {
//id,alias
String id = this.resolveId(element, definition, parserContext);
if (!StringUtils.hasText(id)) {
parserContext.getReaderContext().error("Id is required for element '" + parserContext.getDelegate().getLocalName(element) + "' when used as a top-level tag", element);
}
String[] aliases = null;
if (this.shouldParseNameAsAliases()) {
String name = element.getAttribute("name");
if (StringUtils.hasLength(name)) {
aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
}
}
// AbstractBeanDefinition BeanDefinitionHolder
BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);
this.registerBeanDefinition(holder, parserContext.getRegistry());
if (this.shouldFireEvents()) {
//
BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);
this.postProcessComponentDefinition(componentDefinition);
parserContext.registerComponent(componentDefinition);
}
} catch (BeanDefinitionStoreException var8) {
parserContext.getReaderContext().error(var8.getMessage(), element);
return null;
}
}
return definition;
}
上記のパース方法では、最初の文のパーサーInternalは主にカスタムメソッドへの呼び出しです。protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
String parentName = this.getParentName(element);
if (parentName != null) {
builder.getRawBeanDefinition().setParentName(parentName);
}
// class, eg:UserBeanDefinitionParse getBeanClass
Class> beanClass = this.getBeanClass(element);
if (beanClass != null) {
builder.getRawBeanDefinition().setBeanClass(beanClass);
} else {
// getBeanClass , getBeanClassName
String beanClassName = this.getBeanClassName(element);
if (beanClassName != null) {
builder.getRawBeanDefinition().setBeanClassName(beanClassName);
}
}
builder.getRawBeanDefinition().setSource(parserContext.extractSource(element));
if (parserContext.isNested()) {
// scope
builder.setScope(parserContext.getContainingBeanDefinition().getScope());
}
if (parserContext.isDefaultLazyInit()) {
//
builder.setLazyInit(true);
}
// doParse
this.doParse(element, parserContext, builder);
return builder.getBeanDefinition();
}
以上はSpringがどのようにカスタムラベルを解析する過程ですか?Springが設定ファイルからメモリをロードするまでの全過程を勉強しました。2.カスタムラベルの使用
多くの場合、開発にはシステムの構成化サポートが必要であり、最も簡単なのはSpringの標準beanに基づいて配置されていますが、配置が複雑で、またはより多くの豊富な制御が必要な場合、不器用に見えます。実現するのは比較的に煩わしい。Springは、拡張可能なSchemaのサポートを提供しています。Springを拡張するカスタムタグは、ステップ(Springのcoreパッケージが必要です)を設定する必要があります。1.拡張が必要なコンポーネントを作成します。2.XSDファイル記述コンポーネントの内容を定義します。3.ファイルを作成し、BenDefinitionParterインターフェースを実現して、XSDファイルの定義とコンポーネント定義を解析します。4.Handlerファイルを作成します。Namespace Handler Supportから拡張して、目的はコンポーネントをSpring容器5に拡張することです。Spring.handersとSpring.schemasファイルを作成します。
2.1通常のpojoオブジェクトを作成する:
package pojo;
public class User {
private String userName;
private String email;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
2.2 XSDファイルを定義し、コンポーネントの内容を説明する
2.3 UserBeanDefinitionParaserを作成するクラスを作成して、XSDファイルの定義とコンポーネントの定義を解析するために、BeanDefinitionParsserインターフェースを実現します。
package com.SpringBean.test;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
import pojo.User;
public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
/**
* Element
*/
@Override
protected Class> getBeanClass(Element element) {
return User.class;
}
/**
* element
* @param element
* @param builder
*/
@Override
protected void doParse(Element element, BeanDefinitionBuilder builder) {
String userName=element.getAttribute("userName");
String email=element.getAttribute("email");
if(StringUtils.hasText(userName)){
builder.addPropertyValue("userName",userName);
}
if(StringUtils.hasText(email)){
builder.addPropertyValue("email",email);
}
}
}
2.4 Handlerファイルを作成するHandlerファイルを作成し、Namespace Handler Supportから拡張します。目的は、Spring容器にコンポーネントを登録するためです。
package com.SpringBean.test;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class MyNameSpaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("user",new UserBeanDefinitionParser());
}
}
2.5 Spring.handersとSpring.schemasファイルを作成するSpring.handers:
http\://www.test.com/sehema/user=com.SpringBean.test.MyNameSpaceHandler
Spring.schemas:http\://www.test.com/sehema/user.xsd=META-INF/userschema.xsd
上のソースコードの解析では、この2つのファイルを通してデフォルトのlocationはMETA-INFパスですので、ファイルをclasassipath:META-INFパッケージに入れたり、ソースを修正したりすればいいです。beans.xml:
test:package com.SpringBean.test;
import bean.GetBeanTest;
import bean.TestChangeMethod;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import pojo.User;
@SuppressWarnings("deprecation")
public class SpringTest {
public static void main(String[] args) throws Exception {
// Resource resource = new ClassPathResource("beans.xml");
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beans.xml"));
/* GetBeanTest test=(GetBeanTest) bf.getBean("getBeanTest");
TestChangeMethod me=(TestChangeMethod) bf.getBean("testChangeMethod");
me.changeMe();*/
User user=(User) bf.getBean("testBean");
System.out.println(user.getUserName()+" "+user.getEmail());
// test.showMain();
}
}
運転結果:[email protected]