なぜスプリングソースコードを見始めるのか
私はほぼ1年半の間、キャリアの途中でコードを書いています。私は仕事を始めて以来、スプリングフレームワークを使用しています。使用して構築することはできますが、Spring Controls Transactions、SpringMVCがリクエストを処理する方法、AOPの実装方法など、その背後にある原則を理解していません。これにより、人々は非常に不安になります。
ソースコードを効率的に表示する方法
私の答えは、特定の質問でソースコードを見ることです。そうしないと、ソースコードの詳細に固執するのは非常に簡単です。最後に、あなたは長い間読んできたものを見つけます。
導入
Springは、ビジネスロジックレイヤーと他のレイヤーの間のゆるい結合問題を解決し、システムアプリケーション全体でインターフェイス指向のプログラミングアイデアを統合するオープンソースデザインレベルのフレームワークです。また、Java Workの重要なスキルの1つです...
Spring Sourceコード分析プロセスを記録するため、詳細な使用について詳しく説明しません。
コアコード
<Dependency> groupId> org.springframework </groupid> <artifactid> spring-context </artifactid> <バージョン> 5.0.2.Release </version> </dependency>
使用法
public class application {public static void main(string [] args){beanDefinitionRegistry beanFactory = new DefaultListableBeanFactory(); XmlbeanDefinitionReader Reader = new XmlbeanDefinitionReader(BeanFactory); classPathResourceリソース= new ClassPathResource( "Bean.xml"); //リソース全体のロードのエントリポイント。 Reader.LoadBeanDefinitions(リソース); }}復号化
DefaultListableBeanFactoryは、春の登録と豆の積み込みのデフォルトの実装です。 Spring IOCテンプレート全体の祖先と呼ぶことができます。
DefaultListableBeanFactoryを追跡すると、次のコードブロックを見つけることができます。このデザインの目的は何ですか?
public AbstractAutowireCapableBeanFactory(){super(); IndedEpendencyInterface(beannameaware.class); IndedEpendencyInterface(BeanFactoryAware.Class); IndedEpendencyInterface(BeanClassLoaderAware.Class);}たとえば、aに属性Bがある場合、Springは属性Bが属性Aを取得するときにインスタンス化されていないことがわかった場合、属性Bを自動的にインスタンス化します。これは春に提供される重要な機能でもあります。場合によっては、Beannameawareインターフェイスの実装など、Bは初期化されません。
Springはこれを紹介します。自動アセンブリの場合、BeanFactoryAwareを介したBeanFactoryの注入またはApplicationContextAwareを介したアプリケーションコンテキストの注入と同様に、アプリケーションコンテキスト登録依存関係を他の方法で解析するなど、指定された依存関係インターフェイスを無視します。
リソース管理
リソースインターフェイスは、ファイル、URL、ClassPath、その他のリソースの管理に使用されます。リソースは、構成ファイルを読み取り、つまり、構成ファイルをリソースにカプセル化し、処理のためにXMLBeanDefinitionReaderに引き渡す責任があります。
XML解析
XmlbeanDefinitionReaderは、Springリソースファイルの読み取り、解析、登録の実装であり、このクラスに焦点を当てる必要があります。
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 Saxingを使用し、inputSourceを使用してXMLファイルの読み方を決定すると結論付けることができます。
最後に、準備されたデータは、パラメーターdoLoadBeanDefinitions(inputSource, encodedResource.getResource())を介して実際のコア処理パーツに渡されます。
ドキュメントを入手してください
1。DoloadbeanDefinitions doLoadBeanDefinitions(inputSource, encodedResource.getResource()); 、いくつかのキャッチとコメントを省略します
保護されたint doloadbeandefinitions(inputSource inputSource、リソースリソース)beandefinitionStoreException {try {document doc = doloaddocument(inputsource、resource); RetultedBeanDefinitions(doc、resource); }} 2。DoloAddocument doLoadDocument(inputSource, resource);
保護されたドキュメントdoloaddocument(inputsource inputsource、resource resource)throws exception {return this.documentloader.loaddocument(inputSource、getEntityReSolver()、this.errorhandler、getValidationModeModeforresource(リソース)、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)throws ioexception {}} EntityResolverパラメーターは、 this.documentLoader.loadDocumentメソッドに関与しています
Public Document LoadDocument(inputSource inputSource、EntityResolver EntityResolver、ErrorHandler ErrorHandler、int validationMode、boolean namespaceaware)をスローする{}EntityResolverとは何ですか?公式説明:SAXアプリケーションが外部エンティティのカスタム処理を実装する必要がある場合、このインターフェイスを実装し、SetentityResolverメソッドを使用してSAXドライブにインスタンスを登録する必要があります。つまり、XMLを解析するために、SAXは最初にXMLドキュメントの宣言を読み取り、宣言に従って対応するDTD定義を検索し、ドキュメントを検証するために、デフォルトの検索ルールを確認します(つまり、ネットワークダウンロード、XMLが宣言されたDTD URIアドレスを介してDTD定義をダウンロードし、認証を実行します。ダウンロードプロセスは長いプロセスであり、ネットワークが利用できない場合、対応するDTDが見つかっていないため、ここでエラーが報告されます。
EntityResolverの機能は、プロジェクト自体がDTD宣言を見つける方法の方法を提供できることです。つまり、プログラムはDTDを見つけるプロセスを実装します。
3.EntityResolverは2つのパラメーターを受け入れます。
パブリックアブストラクトinputSource ResolveEntity(String PublicID、String SystemID)Throws Saxexception、IOException;
3.1 Bean.xmlファイルを次のように定義し、次のように(XSDモード)
<?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.xsd"> </beans>
次の2つのパラメーターに解析されます。
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> </beans>
次の2つのパラメーターに解析されます。
3.3 Springは、EntityResolverを解析するためにDelegatingEntityResolverを使用します
Public Class DelegatingEntityResolver {@Override @Nullable PublicSource ResolveEntity(String PublicID、@Nullable String SystemID)THROWS SAXEXCEPTION、IOEXCEPTION {if(SystemID!= null){if(systemid.endswith(dtd_suffix)){return this.dresolver.ResolveEntity(publicid(publicid); } else if(systemid.endswith(xsd_suffix)){return this.schemaresolver.resolveentity(publicid、systemid); }} nullを返します。 }}さまざまなモードに異なるパーサーが使用されていることがわかります
豆を登録します
XML検証の解析を読んだ後、コードを追跡し続け、Springがドキュメントに基づいてBean情報を登録する方法を確認し続けます
パブリッククラスXMLBEANDEFINITIONREADER {public int RegisterBeanDefinitions(Document Doc、Resource Resource)Throws BeanDefinitionStoreException {// DocumentReader BeanDefinitionDocumentReader documentReader = CreateBeanDefinitionDocumentReader(); //統計の前にbeandefinitionsの数を記録しますint countbefore = getRegistry()。getBeanDefinitionCount(); // beandefinition documentreader.registerbeandefinitions(doc、createreadercontext(resource)); //今回はreturn getRegistry()。getBeanDefinitionCount() - countBefore; }}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)); }} documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); 、Docは、前のコードブロックのLoadDocumentを介して変換されます。この方法の主な目的は、ルートノード(豆)を抽出することです
public class defaultBeanDefinitionDocumentReader {@Override public void RegisterBeanDefinitions(document doc、xmlreadercontext readercontext){this.readercontext = readercontext; logger.debug( "bean定義の読み込み");要素root = doc.getDocumentElement(); doregisterbeandefinitions(root); }} doRegisterBeanDefinitions(root)を追跡すると、次の処理フローが表示されます
保護されたvoid doregisterbeandefinitions(element root){// ... string profilespec = root.getattribute(profile_attribute); // ... //空の実装preprocessxml(root); parsebeandefinitions(root、this.delegate); //空の実装postprocessxml(root); this.delegate = parent;}まず、プロファイルを解析します(より一般的な再生方法は、異なるプロファイルによって初期化されたBeanオブジェクトが異なるため、複数の環境を実装することです)
次の解析では、PreprocessXMLとPostProcessXMLが両方とも空のメソッドであるテンプレートメソッドモードを使用しているため、後続のサブクラスは解析の前後に処理を実行できます。これら2つの方法を無効にします。
BeanDefinitionを分析して登録すると、コードのこの部分は比較的簡単です
public class defaultbeandefinitiondocumentReader { / ***ルートノードインポートの下で他のノードを解決します "、" alias "、" bean "。 rootChildNodes() Delegate.ParseCustomElement(ELE); ImportBeanDefinitionResource(ELE); nested_beans_element)){// doregisterbeandeditions(ele)}}}}}}}}} process beansに登録してから、 * /保護されたvoid beandefinition(要素、beandefinitionparserdelegate delegate) Delegate.ParseBeanDefinitionElement(ELE); } catch(BeanDefinitionStoreExcepted()。要素解析のためにBeanDefinitionParserDelegateクラスのParseBeanDefinitionElementメソッドを委任し、BeanDefinitionHolder Type BDHolderのインスタンスを返します(構成ファイルクラス、名前、ID、エイリアスなどのさまざまな属性を含む)
返されたbdholderが空でない場合、デフォルトラベルの子ノードにカスタム属性がある場合、カスタムラベルが再び解析され、 BeanDefinitionReaderUtils.registerBeanDefinition(); BDHOLDERを登録し、登録イベントを送信し、関連するリスニングビーンに登録が成功していることを通知します。
要約します
数回未知の秋、冬、春、夏の後、すべてがあなたが望む方向に従います...
さて、上記はこの記事のコンテンツ全体です。この記事の内容には、すべての人の研究や仕事に特定の参照値があることを願っています。ご質問がある場合は、メッセージを残してコミュニケーションをとることができます。 wulin.comへのご支援ありがとうございます。
何か言って
全文コード:https://gitee.com/battcn/battcn-spring-source/tree/master/chapter1(ローカルダウンロード)