머리말
이전 섹션에서 스프링 암호 해독 - 기본 태그 분석에서 스프링이 기본 태그를 구문 분석하는 방법을 분석하는 데 중점을 둡니다. 따라서이 장은 사용자 정의 태그를 구문 분석하는 방법에 중점을 둔 라벨 구문 분석을 계속 설명합니다. 더 이상 고민하지 않고 자세한 소개를 살펴 보겠습니다.
맞춤형 태그
사용자 정의 태그 분석을 설명하기 전에 태그를 사용자 정의하는 방법을 참조하십시오.
XSD 파일을 정의합니다
구성 요소 내용을 설명하기 위해 XSD 파일을 정의하십시오
<? xml version = "1.0"encoding = "utf-8"?> <xsd : schema xmlns = "http://www.battcn.com/schema/battcn"xmlns : xsd = "http://www.w.w.2.2001/xmlschema" xmlns : beans = "http://www.springframework.org/schema/beans"targetnamespace = "http://www.battcn.com/schema/battcn"ElementformDefault = "regulied"attributeformdefault = "unqualified"> <xsd : 수입 네임 스페이스 = "http://www.springframework.org/schema/beans"/> <xsd : 요소 이름 = "Application"> <xsd : complextype> <xsd : complexcontent> <xsd : extension base = "beans : evidenifiedType"> </xsd : Extension> </xsd : ComplexContent> </xsd : complextype> </xsd : element> </xsd : schema>
구문 분석 규칙을 정의합니다
1. XSD 파일의 정의 및 구성 요소 정의를 구문 분석하기 위해 BeanDefinitionParser 인터페이스 (Spring에서 제공 한 클래스를 상속받을 수 있음)를 구현할 클래스를 만듭니다.
공개 클래스 ApplicationBeanDefinitionParser는 AbstractSingleBeanDefinitionParser를 확장합니다. {@override Protected Class getBeanClass (요소 요소) {// 수신 된 객체의 유형은 다음과 같습니다. 문자열 이름 = (String) context.getBean ( "battcn"); return string.class; } @override protected void doparse (요소 요소, beandefinitionBuilder bean) {// xsd string name = element.getAttribute ( "name")에 정의 된 이름 속성; bean.addconstructorargvalue (이름); }}다음은 ApplicationBeendeFinitionParser를 상속하는 ApplicationBeendeFinitionParser입니다 (BeanDefinitionParser의 서브 클래스). 초점은 Doparse, XML 태그를 구문 분석 한 다음 구문 분석 값 (Levin)을 생성자에 주입하는 것입니다.
2. 네임 스페이스 핸들러 업 스upport 초록 클래스를 상속하기 위해 클래스를 만듭니다
공개 클래스 battcnamespacehandler 확장 네임 스페이스 핸들러 uppport {@override public void init () {registerBeanDefinitionParser ( "Application", new ApplicationBeanDefinitionParser ()); }} battcnnamespacehandler의 기능은 매우 간단합니다. 스프링 컨테이너에 태그 <battcn:application /> 은 그 파서에 의해 구문 분석되어야한다고 말하는 것입니다 (여기서는 우리가 사용자 정의 : ApplicationBeandefinitionParser).
3. Spring.Handlers 및 Spring.Schemas 파일을 쓰십시오
파일이 저장된 디렉토리는 Resources/Meta-Inf/파일 이름에 있습니다.
스프링. 핸들러
http/: //www.battcn.com/schema/battcn=com.battcn.handler.battcnamespacehandler
Spring.schemas
http/: //www.battcn.com/schema/battcn.xsd=battcn.xsd
4. 사용자 정의 태그를 사용하십시오
다음과 같이 정의 된 bean.xml 파일을 선언하십시오
<? xml 버전 = "1.0"alcoding = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans"xmlns : xsi = "http://ww.w.w3.org/2001/xmlschema-instance" xmlns : battcn = "http://www.battcn.com/schema/battcn"xsi : schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/schema/sprideans.xsd http://www.battcn.com/schema/battcn http://www.battcn.com/schema/battcn.xsd "> <battcn : Application id ="battcn "name ="Levin "/> </beans>
테스트 클래스를 만듭니다. 콘솔 출력 Levin Word가 표시되면 사용자 정의 레이블이 정상임을 의미합니다.
공개 클래스 응용 프로그램 {public static void main (String [] args) {ApplicationContext Context = new ClassPathXmlApplicationContext ( "bean.xml"); 문자열 이름 = (문자열) context.getBean ( "battcn"); System.out.println (이름); }}5. 그림과 같이
소스 코드 분석
맞춤형 태그 해상도 포털
Public Class BeanDefinitionParserDelegate {@Nullable Public BeanDefinition ParseCustomEmelement (요소, @Nullable BeanDefinition 포함) {// 네임 스페이스 주소를 가져옵니다 http://www.battcn.com/schema/battcn String Namespaceuri = getamespaceuri (ele); if (namespaceuri == null) {return null; } // NamespaceHandler는 사용자 정의 된 battcnamespacehandler namespacehandler handler = this.readerContext.getNamespaceHandlerResolver () resolve (namespaceURI)에 등록 된 응용 프로그램입니다. if (handler == null) {error ( "XML 스키마 네임 스페이스의 스프링 네임 스페이스 핸들러를 찾을 수 없습니다 [" + namespaceuri + "]", ele); 널 리턴; } return handler.parse (ele, new parserContext (this.readerContext, this, containingbd)); }} 기본 태그 해상도 규칙과 마찬가지로 네임 스페이스는 getNamespaceURI(Node node) 를 통해 얻습니다. 그렇다면 어디서 this.readerContext.getNamespaceHandlerResolver() 가 얻은가? 코드를 추적하면 프로젝트가 시작될 때 모든 Meta-Inf/Spring.handles 파일 내용이 XMLBeanDefinitionReader에서 구문 분석되고 핸드 리머 맵퍼 (ConsurenThashMap)에 저장됩니다. resolve(namespaceUri) 가 확인되면 캐시 된 내용이 비교를 위해 추출됩니다.
공개 클래스 XMLBEANDEFINITIONREADER {public namespaceHandlerResolver getNamespaceHandlerResolver () {if (this.namespaceHandlerResolver == null) {this.namespaceHandlerResolver = createFaultNamesPaceHandlerResolver (); } reture this.namespacehandlerresolver; }}해결하다
1. 지정된 네임 스페이스 핸들러 맵을로드하고 추출 된 네임 스페이스 핸들러가 캐시 된 다음 반환됩니다.
공개 클래스 defaultNamespaceHandlerResolver {@override @nullable public namespacehandler resolve (string namespaceuri) {map <string, object> handlermappings = gethandlermappings (); // HandlerMappings에서 handlerorClassName 추출 객체 handlerorClassName = handlermappings.get (namespaceuri); if (handlerorClassName == null) {return null; } else if (handlerorClassName instanceof namespaceHandler) {return (namespaceHandler) handlerorClassName; } else {string className = (string) handlerorClassName; {class <?> handlerclass = classutils.forname (classname, this.classloader); if (! namespaceHandler.class.isAssignableFrom (handlerClass)) {New FatalBeanException ( "class [" + className + "] 네임 스페이스 [" + namespaceUri + "]는 [" + namesPaceHandler.class.getName () + "interface")를 구현하지 않습니다. } // 네임 스페이스 네임 스페이스 네임 스페이스 핸들러 네임 스페이스 핸들러를 기반으로 해당 정보를 찾으십시오. // handler namespaceHandler.init (); Handlermappings.put (Namespaceuri, NamespaceHandler); 리턴 네임 스페이스 핸들러; } catch (classNotFoundException ex) {네임 스페이스 [ " + namespaceuri +"]를 찾을 수있는 New FatalBeanException ( "네임 스페이스 핸들러 클래스 [" + className + "]를 찾을 수 없음", Ex); } catch (linkageError err) {Throw New FatalBeanException ( "네임 스페이스의 경우"Invalid NamespaceHandler Class [ " + ClassName +"] [ " + namespaceUri +"] : 핸들러 클래스 파일 또는 종속 클래스의 문제 ", err); }}}}태그 분석
네임 스페이스 핸들러를로드 한 후 BattcnamespaceHandler가 초기화되었으며 BattCnnamespaceHandler는 초기화 작업을 완료하기 위해 init() 메소드를 호출합니다. 따라서 다음 코드를 계속 실행합니다 handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); 특정 태그 솔루션.
public class namespacehandlersupport {@override @nullable public beandefinition parse (요소 요소, parsercontext parsercontext) {beandefinitionparser parser = findparserForElement (요소, parserContext); return (parser! = null? parser.parse (요소, parsercontext) : null); } @Nullable private beandefinitionparser findparserforElement (요소 요소, parserconText parserContext) {// <battcn : application /> .getDelegate (). getLocalName (요소); BeanDefinitionParser Parser = this.parsers.get (localName); if (parser == null) {parserconText.getReaderConText (). FATAL ( "요소에 대한 locale beanDefinitionParser [" + localName + "]", element); } 리턴 파서; }}간단히 말해서, Parsers에서 ApplicationBeendefinitionParser 인스턴스를 찾아 자체 도포 스 메소드를 호출하여 추가 분석을 수행하는 것입니다. 마지막으로 기본 태그를 구문 분석하는 것과 동일한 루틴입니다 ...
요약
알려지지 않은 가을, 겨울, 봄, 여름이 몇 번 후에 모든 것이 원하는 방향을 따라갑니다 ...
좋아, 위는이 기사의 전체 내용입니다. 이 기사의 내용에 모든 사람의 연구 나 작업에 대한 특정 참조 가치가 있기를 바랍니다. 궁금한 점이 있으면 의사 소통을 위해 메시지를 남길 수 있습니다. Wulin.com을 지원 해주셔서 감사합니다.
말 해주세요
전문 코드 : https://gitee.com/battcn/battcn-spring-source/tree/master/chapter2