스프링 소스 코드를보기 시작하는 이유
나는 거의 1 년 반 동안 경력을 반쯤 쓰고 있습니다. 작업을 시작한 이래로 스프링 프레임 워크를 사용하고 있습니다. 나는 그것을 사용할 수 있지만 그것을 만들 수는 있지만, 스프링이 트랜잭션을 제어하는 방법, SpringMVC가 요청을 처리하는 방법 및 AOP의 구현 방법 ... 이렇게하면 사람들이 매우 불안감을 느끼게되므로 책을 읽는 동안 스프링 소스 코드를 천천히 연구하기 시작합니다 !!!
소스 코드를 효율적으로 보는 방법
내 대답은 특정 질문이있는 소스 코드를 보는 것입니다. 그렇지 않으면 소스 코드 세부 사항에 갇히기가 매우 쉽습니다. 마지막으로, 당신은 당신이 오랫동안 읽었던 것을 알아냅니다.
소개
Spring은 비즈니스 로직 계층과 다른 계층 간의 느슨한 커플 링 문제를 해결하고 전체 시스템 애플리케이션에서 인터페이스 지향 프로그래밍 아이디어를 통합하는 오픈 소스 설계 레벨 프레임 워크입니다. 또한 Java Work의 필수 기술 중 하나입니다 ...
스프링 소스 코드 분석 프로세스를 기록하기 때문에 자세한 사용법에 대해 자세히 설명하지 않습니다.
핵심 코드
<pectionency> <groupid> org.springframework </groupid> <artifactid> spring-context </artifactid> <버전> 5.0.2. release </version> </fectionency>
용법
공개 클래스 응용 프로그램 {public static void main (String [] args) {beandefinitionregistry beanfactory = new defaultListableBeanFactory (); XMLBEANDEFINITIONREADER Reader = New XMLBeanDefinitionReader (BeanFactory); classPathResource resource = new ClassPathResource ( "bean.xml"); // 전체 리소스로드의 진입 점. reader.loadBeanDefinitions (자원); }}암호 해독
DefaultListableBeanFactory는 스프링 등록 및 로딩 콩의 기본 구현입니다. 전체 스프링 IOC 템플릿에서 조상이라고 할 수 있습니다.
DefaultListableBeanFactory를 추적하면 다음 코드 블록을 찾을 수 있습니다. 이 디자인의 목적은 무엇입니까?
public AbstractAutowIrecapableBeanFactory () {super (); 무시 의존성 interface (beannameaware.class); 무시 의존성 interface (beanfactoryaware.class); 무시한 의존성 interface (beanclassloaderaware.class);}예를 들어, A에 속성 B가있는 경우, 속성 A를 얻을 때 속성 B가 인스턴스화되지 않는 경우 스프링이 속성 B를 자동으로 인스턴스화합니다. 이는 스프링에 제공되는 중요한 기능이기도합니다. 경우에 따라 Beannameaware 인터페이스 구현과 같은 B는 초기화되지 않습니다.
Spring은 다음을 소개합니다. 자동 조립하면 Application-ContextAware를 통한 ApplicationContext를 통한 BeanFactory의 주입과 유사한 자동 조립일이 다른 방법을 통해 응용 프로그램 컨텍스트 등록 종속성을 파싱하는 것과 같은 주어진 종속성 인터페이스를 무시합니다.
자원 관리
리소스 인터페이스는 파일, URL, 클래스 경로 및 기타 리소스를 관리하는 데 사용됩니다. Resource는 구성 파일, 즉 구성 파일을 리소스로 캡슐화 한 다음 처리를 위해 XMLBeanDefinitionReader로 넘겨주는 책임이 있습니다.
XML 파싱
XMLBEANDEFINITIONREADER는 Spring Resource 파일 판독, 구문 분석 및 등록을 구현 한 것이므로이 클래스에 중점을 두어야합니다.
트랙 reader.loadBeanDefinitions(resource); , 우리는 다음 핵심 코드를 볼 수 있습니다 (의견 제외 및 예외 예외)
public int loadbeandefinitions (encodedResource encodedResource) beandefinitionStoreException {try {inputStream inputStream = encodedResource.getResource (). getInputStream (); try {inputSource inputSource = new InputSource (inputStream); if (encodedResource.getEncoding ()! = null) {inputSource.setencoding (encodedResource.getEncoding ()); } return doloadBeanDefinitions (inputSource, encodedResource.getResource ()); } 마침내 {inputStream.close (); }}}위의 코드는 XML의 인코딩 문제에 대해 걱정할 목적으로 리소스에서 코딩 작업을 처음 수행했습니다.
InputSource inputSource = new InputSource(inputStream); 패키지 이름은 실제로 org.xml.sax이므로 Spring은 Sax Parsing을 사용하고 InputSource를 사용하여 XML 파일을 읽는 방법을 결정한다는 결론을 내릴 수 있습니다.
마지막으로, 준비된 데이터는 매개 변수 doLoadBeanDefinitions(inputSource, encodedResource.getResource())
문서를 얻으십시오
1. doLoadBeanDefinitions(inputSource, encodedResource.getResource()); , 몇 가지 어획량과 의견을 생략하십시오
보호 된 DOLOADBEANDEDEFINITIONS (InputSource InputSource, Resource Resource)는 BeanDefinitionStoreException {Try {Docum Doc = DOLOADDOCUMENT (InputSource, Resource); 리턴 레지스터 비밀 정화 (Doc, Resource); }} 2. doLoadDocument(inputSource, resource);
보호 된 문서 DOLOADDOCUMENT (InputSource InputSource, Resource Resource)는 예외를 발생시킵니다 {return this.documentLoader.loadDocument (inputSource, getEntityResolver (), this.errorHandler, getValidationModeForresource (resource), isnamespaceaware ();};먼저 GetValidationModeForResource를 통해 XML 파일의 확인 모드 (DTD 또는 XSD)를 얻을 수 있습니다. 검증 방법을 직접 설정할 수 있습니다. 기본적으로 Validation_auto가 활성화됩니다. 즉, 검증 모드가 자동으로 얻어집니다. inputStream을 통해 XML 파일을 읽고 DocType 단어가 포함되어 있는지 확인하십시오. 포함 된 경우 DTD이고 XSD를 반환합니다.
일반적인 XML 파일 확인 패턴은 다음과 같습니다.
공개 클래스 XMLVALIDATIONMODEDETECTOR { /***는 DTD 검증을 사용해야 함을 나타냅니다 ( "DocType"선언을 찾았습니다). */ public static final int validation_dtd = 2; /***는 XSD 유효성 검사를 사용해야 함을 나타냅니다 ( "DocType"선언이 없습니다). */ public static final int validation_xsd = 3; public int detectValidationMode (inputStream inputStream) IoException {}} EntityResolver 매개 변수는 this.documentLoader.loadDocument 에 관련되어 있습니다 .documentloader.loaddocument 메소드
공개 문서로드 문서 (InputSource inputSource, EntityResolver entityResolver, ErrorHandler ErrorHandler, int validationMode, Boolean NamesPaceAware) 예외 {} 던지기EntityResolver 란 무엇입니까? 공식 설명 : SAX 응용 프로그램이 외부 엔티티의 사용자 정의 처리를 구현 해야하는 경우이 인터페이스를 구현하고 SetentityResolver 메소드를 사용하여 SAX 드라이브에 인스턴스를 등록해야합니다. 즉, SAX는 XML 문서의 선언을 먼저 읽고 선언에 따라 해당 DTD 정의를 검색하여 문서, 기본 검색 규칙 (예 : 네트워크 다운로드, XML이 선언 한 DTD URI 주소를 통해 DTD 정의를 다운로드하고 DTD 정의를 다운로드하여 DTD 정의를 다운로드합니다. 다운로드 프로세스는 긴 프로세스이며 네트워크를 사용할 수 없을 때 해당 DTD가 발견되지 않았기 때문에 오류가 여기에보고됩니다.
EntityResolver의 기능은 프로젝트 자체가 DTD 선언을 찾는 방법, 즉 프로그램이 DTD를 찾는 프로세스를 구현하여 네트워크를 통해 해당 선언을 찾는 것을 피할 수 있다는 것입니다.
3. 엔티티 크레 솔버는 두 가지 매개 변수를 수락합니다.
공개 초록 입력 소스 결의 (String Publicid, String SystemID)는 saxexception, ioexception을 던졌습니다.
3.1 컨텐츠가 다음과 같이 Bean.xml 파일을 정의하십시오 (XSD 모드)
<? xml 버전 = "1.0"alcoding = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans"xmlns : xsi = "http://ww.w.w3.org/2001/xmlschema-instance" xsi : schemalocation = "http://www.springframework.org/schema/beans.xsd"> </beans>
다음 두 매개 변수로 구문 분석 :
3.2 컨텐츠와 함께 Bean.xml 파일을 다음과 같이 정의하십시오 (DTD 모드)
<? xml version = "1.0"encoding = "utf-8"?> <! doctype beans public "-// spring // dtd bean 2.0 // en" "http://www.springframework.org/dtd/spring-beans.dtd"> </beans>
다음 두 매개 변수로 구문 분석 :
3.3 Spring은 EntityResolver를 구문 분석하기 위해 DelegatingentityResolver를 사용합니다
공개 클래스 대표단 대표 {@override @override @nullable public inputsource resolveentity (string publicid, @nullable String SystemID)는 saxexception, ioexception {if (systemId! = null) {if (systemId.endswith (dtd_suffix)) {return this.dtdresolver.resentity (systemid); } else if (systemId.endswith (xsd_suffix)) {return this.schemaresolver.resolventity (publicid, systemId); }} return null; }}우리는 다른 모드에 다른 구문 분석기가 사용되는 것을 볼 수 있습니다.
콩을 등록하십시오
구문 분석 XML 검증을 읽은 후 코드를 계속 추적하고 스프링이 문서를 기반으로 BEAN 정보를 등록하는 방법을 확인하십시오.
공개 클래스 XMLBEANDEFINITIONREADER {public int registerBeanDefinitions (문서 문서, 리소스 리소스) 던지기 BeanDefinitionStoreException {// DocumentReader BeanDefinitionDocumentReader DocumentReader = CreateBeanDefinitionDocumentReader (); // 통계 이전에 beandefinitions의 수를 기록 int countbefore = getRegistry (). getBeanDefinitionCount (); // Register BeanDefinition DocumentReader.registerBeanDefinitions (Doc, CreateReaderContext (Resource)); //로드 된 beandefinitions의 수를 기록합니다. }}Bean을 등록 할 때 먼저 BeanDefinitionParserDelegate 클래스를 사용하여 기본 네임 스페이스인지 확인하십시오. 구현은 네임 스페이스 URI가 기본 URI와 같은지 여부를 결정하는 것입니다.
공개 클래스 BeanDefinitionParserDelegate {public static final String beans_namespace_uri = "http://www.springframework.org/schema/beans"; public boolean isdefaultnamespace (@nullable String namespaceuri) {return (! stringUtils.haslength (namespaceuri) || beans_namespace_uri.equals (namespaceuri)); }} Track documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); , 여기서 Doc은 이전 코드 블록에서로드 문서를 통해 변환됩니다. 이 방법의 주요 목적은 루트 노드 (콩)를 추출하는 것입니다.
공개 클래스 DefaultBeanDefinitionDocumentReader {@override public void registerBeanDefinitions (문서 doc, XMLREADERCONTEXT readErConText) {this.ReadErcOnText = readErConText; logger.debug ( "bean 정의로드"); 요소 root = doc.getDocumentElement (); Doregisterbeandefinitions (루트); }} doRegisterBeanDefinitions(root) 추적하면 다음 처리 흐름이 보입니다.
보호 된 void doregisterbeandefinitions (요소 root) {// ... String profilespec = root.getAttribute (profection_attribute); // ... // 빈 구현 preprocessxml (루트); parsebeendefinitions (root, this.delegate); // 빈 구현 postprocessxml (root); this.delegate = 부모;}먼저 프로필을 구문 분석합니다 (더 일반적인 재생 방법은 다른 프로파일로 초기화 된 Bean 객체가 다르므로 여러 환경을 구현한다는 것입니다).
다음 구문 분석은 preprocessxml 및 postprocessxml이 모두 빈 메소드 인 템플릿 메소드 모드를 사용하므로 후속 서브 클래스는 구문 분석 전후에 일부 처리를 수행 할 수 있습니다. 이 두 가지 방법을 무시하십시오.
BeanDefinition을 분석하고 등록하면 코드 의이 부분은 비교적 간단합니다.
공개 클래스 DefaultBeanDefinitionDocumentReader { / *** 루트 노드 가져 오기에서 다른 노드를 해결하십시오 ","alias ","bean ".* @param root node name* / protected void parsebeanDefinitions (요소 root, beandefinitionparserdelegate delegate) {if (delegate.isdefaultnpace (root)) root.getchildnodes (int i = 0; i <nl.getlength) {node instance emection (node ele); delegate.parsecustomEmelement (ele)}} else {delegate.parsecustomelement (root); importBeendefinitionResource (ELE) else (elegate.nodenameequals (ele, alias_element)) {elegate.nodenameequals (ele, bean_element) {eLe, delegate (ele}); Nested_beans_Element)) {// regorse doregisterbeandefinitions (ele)} / ** * Process Beans 태그에 등록하십시오. delegate.parsebeendefinitionlement (bdholder! = null). catch (beanDefinitionStoreException ex) {getReaderContext (). 요소 구문 분석에 대한 BeanDefinitionParserDelegate 클래스의 ParseBeendefinitionElement 메소드를 위임하고 BeanDefinitionHolder Type BDHolder의 인스턴스를 반환합니다 (구성 파일 클래스, 이름, ID, 별명 등의 다양한 속성 포함).
반환 된 BDHolder가 비어 있지 않은 경우, 기본 레이블의 하위 노드에 사용자 정의 속성이있는 경우 사용자 정의 레이블이 구문 분석되고 다시 구문 분석 된 다음 BeanDefinitionReaderUtils.registerBeanDefinition(); BDHolder를 등록하고 등록 이벤트를 보낸다.
요약
알려지지 않은 가을, 겨울, 봄, 여름이 몇 번 후에 모든 것이 원하는 방향을 따라갑니다 ...
좋아, 위는이 기사의 전체 내용입니다. 이 기사의 내용에 모든 사람의 연구 나 작업에 대한 특정 참조 가치가 있기를 바랍니다. 궁금한 점이 있으면 의사 소통을 위해 메시지를 남길 수 있습니다. Wulin.com을 지원 해주셔서 감사합니다.
말 해주세요
전체 텍스트 코드 : https://gitee.com/battcn/battcn-spring-source/tree/master/chapter1 (로컬 다운로드)