머리말
Spring Boot의 인기가 높아짐에 따라 응용 프로그램의 대부분의 구성이 숨겨져 있습니다. 우리는 실제 비즈니스 컨텐츠, 컨트롤러, 서비스, 저장소에 대해서만 신경을 주어야하며 키보드를 선택하면 비즈니스 코드의 사본을 사용할 수 있습니다. 특정 구성 요소 스캔, 뷰, 자리 표시 자 ... 뒤에 남겨질 수 있습니다. 그러나 실제로이 제로 구성은 Java 응용 프로그램 개발에서는 오래 걸리지 않습니다. "사치스러운 것에서 절제에 이르기가 어렵습니다." 많은 개발자들이 긴 스프링 XML 구성을 경험 했으며이 구성으로 돌아 가기가 어렵습니다.
그러나 때로는 구성 컨텐츠가 Spring Boot와 같은 구성으로 잘 구현되지 않기 때문에 XML 구성 양식을 사용한 다음 ImportSource를 사용해야합니다. 또는 일부 프로젝트는 환경의 영향을 받고 부팅을 사용하여 개발되지 않으므로 구성에 대한 특정 이해가 필요합니다.
그런 다음 XML 구성의 일부 사용자 정의 스키마 컨텐츠, 일부 사용자 정의 스키마 컨텐츠가 구성을 위해 Spring에 통합되는 방법을 다시 살펴 보겠습니다. 예를 들어:
스프링 데이터 ES
더보
우리가 그것들을 하나씩 나열하지 않는 많은 예가 있습니다. 그러나 위의 두 수치를 통해 일반적인 기능을 찾습니다.
그렇다면이 사용자 정의 구성은 언제 작동합니까? 구성이 올바른지 확인하는 방법은 무엇입니까?
Spring.handlers라는 파일이 포함 된 스프링을 살펴 보겠습니다. 모든 사용자 정의 확장은이 파일을 통해 적용됩니다. 봄 공식 AOP와 TX 도이 원칙을 가지고 있습니다.
이 파일은 어디에 있습니까?
위의 그림과 같이 Meta-Inf/spring.handlers입니다. 파일 내용도 매우 간단합니다.
http/: //www.springframework.org/schema/data/elasticsearch=org.springframework.data.elasticsearch.config.elasticsearchnamespacehandler
첫 번째는 각 스키마의 접두사이고 다음은 스키마에 해당하는 구문 분석 클래스입니다. spring.handlers 파일은 언제로드됩니까?
사용자 정의 구성 파일을 구문 분석 할 때도 발생합니다. 해결 프로세스가 있습니다. 현재 현재 클래스 로더에 해당하는 모든 Spring.handlers 파일이로드됩니다.
이 분석 클래스를 다시 살펴 보겠습니다. 내용은 다음과 같습니다.
공개 클래스 elasticsearchnamespacehandler 확장 네임 스페이스 핸들러 업 스upport {public elasticsearchnamespacehandler () {} public void init () {repositoryConfigurationExtension Extension = 새로운 elasticsearchRepositoryConfigextension (); repositoryBeanDefinitionParser Parser = New RepositoryBeanDefinitionParser (Extension); this.registerbeanDefinitionParser ( "리포지토리", 파서); this.registerbeanDefinitionParser ( "Node-Client", New NodeClientBeanDefinitionParser ()); this.registerbeanDefinitionParser ( "Transport-Client", New TransportClientBeanDefinitionParser ()); }} 첫째, NamesapceHandlersUpport에서 상속됩니다
그런 다음 재 작성 된 초기 방법에 일련의 파서가 등록됩니다. 각 파서는 문자열에 해당합니다.이 문자열은 위의 ES 구성과 같은 XML 구성 파일에서 사용하는 사용자 정의 컨텐츠입니다.
<Elasticsearch : Transport-Client id = "Client"Cluster-Nodes = "192.168.73.186:9300"클러스터
여기의 구성은 결국 TransportClientBeanDefinitionParser를 통해 구문 분석됩니다
위에서 언급 한 파서는 init 메소드의 맵에 저장됩니다.
개인 최종지도 <String, BeanDefinitionParser> Parsers = New Hashmap ();
소위 파서 등록은이 파서의지도를 넣는 것입니다.
되돌아 보면 봄에 가장 핵심 콘텐츠는 무엇입니까? 콩입니다. 실제로 XML에서 구성하는 내용은 결국 해당 콩으로 생성됩니다. 모든 구성은 단지 콩을 생성하는 것입니다. 이러한 사용자 정의 구성을 BeanDefinition이라고합니다.
따라서 스프링이 구성 파일을 구문 분석 할 때 다음과 같은 판단이 있습니다. 그렇지 않다면 CustomElementParse로 이동하십시오
보호 된 void parsebeandefinitions (요소 루트, 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 = (요소) 노드; if (delegate.isdefaultNamespace (ele)) {this.parsedEfaultElement (ele, delegate); } else {delegate.parsecustomElement (ele); }}}} else {delegate.parsecustomElement (루트); }} 대신, DefaultNamespace가 아닌 판단은 더 직접적입니다. 네임 스페이스 URI에는 내용이 있습니까? 아니면 스프링 콩에 대한 진술입니까?
Public Boolean isdefaultNamespace (String NomespaceUri) {return! stringUtils.haslength (NesmetpaceUri) || "http://www.springframework.org/schema/beans".equals(namespaceuri); } 따라서 요청은 모두 parsecustomelement로 이동했으며 구성 분석이 시작되었습니다. 구문 분석되면 해당 핸들러가 uriresolver를 통해 발견되었습니다
공개 beandefinition parsecustomelement (요소 Ele, beandefinition includainsbd) {String namespaceuri = this.getnamespaceuri (ele); NamespaceHandler handler = this.ReaderConText.getNamespaceHandlerResolver (). resolve (namespaceuri); if (handler == null) {this.error ( "XML 스키마 네임 스페이스의 스프링 네임 스페이스 핸들러를 찾을 수 없습니다 [" + namespaceuri + "]", ele); 널 리턴; } else {return handler.parse (ele, new parserconText (this.readerConText, this, containingbd)); }} 현재 반환되는 유일한 것은 스프링 핸들러로 구성된 핸들러이며 각 핸들러는 많은 구문 분석을 등록하며 구문 분석 프로세스가 필요합니다.
public beandefinition parse (요소 요소, parsercontext parsercontext) {return.findparserforelement (요소, parsercontext) .parse (요소, parsercontext); } private beandefinitionparser findparserforeLement (요소 요소, parserconText parserContext) {String localName = parserContext.getDelegate (). getLocalName (요소); BeanDefinitionParser Parser = (BeanDefinitionParser) this.parsers.get (localName); if (parser == null) {parserconText.getReaderConText (). FATAL ( "요소에 대해 BeanDefinitionParser를 찾을 수 없습니다 [" + localName + "]", element); } 리턴 파서; } 이를 얻는 과정은 전달 된 문자열을 통해 선언하는지도에서 해당 구문 분석기를 가져온 다음 구성 구문 분석에 사용하는 것입니다.
Parser를 사용하면 Beandefinition을 생성하는 과정이 이어집니다.
우리는이 파서가 AbstractBeandefinitionParser에서 상속되거나 BeanDefinitionParser의 인터페이스를 구현한다는 것을 알 수 있습니다. 인터페이스 구문 분석 방법은 통합 구문 분석 입구입니다.
공공 클래스 TransportClientBeanDefinitionParser는 AbstractBeanDefinitionParser {Public TransportClientBeanDefinitionParser () {} 보호 된 AbstractBeanDefinition Parseinternal (요소 요소, ParserconText parsercontext) {BeanDefinitionBuilder = BeanDefinitionBuilder.RootBeanDefinition (TransportClientFactoryBean.class); this.setConfigurations (요소, 빌더); getSourcedBeanDefinition (builder, element, parsercontext); }} 재 작성 된 parseinternal 방법에서 구성을 구문 분석 한 후 해당 Beandefinition을 반환하십시오. 이것은 또한 다양한 프레임 워크가 자유롭게 추상화되는 곳이기도합니다. 예를 들어, 일부 프레임 워크는 간단하고 간단한 반면, 일부 프레임 워크는 전략 및 데코레이터와 같은 일부 설계 패턴을 적용하여 더 많은 유연성을 제공합니다.
Beandefinition을 얻은 후 전체 컨텍스트에 넣어 스프링 빈의 내용을 생성하면 나중에 분석합니다.
요약
위는이 기사의 전체 내용입니다. 이 기사의 내용에 모든 사람의 연구 나 작업에 대한 특정 참조 가치가 있기를 바랍니다. 궁금한 점이 있으면 의사 소통을 위해 메시지를 남길 수 있습니다. Wulin.com을 지원 해주셔서 감사합니다.