Mengapa mulai melihat kode sumber musim semi
Saya telah menulis kode di tengah karier selama hampir satu setengah tahun. Saya telah menggunakan kerangka kerja musim semi sejak saya mulai bekerja. Meskipun saya dapat menggunakannya dan membangunnya, saya sering tidak memahami prinsip -prinsip di baliknya, seperti: Bagaimana Spring mengontrol transaksi, bagaimana SpringMVC menangani permintaan, dan bagaimana AOP diimplementasikan ... ini membuat orang merasa sangat tidak nyaman, jadi mulailah untuk secara perlahan mempelajari kode sumber musim semi saat membaca buku !!!
Cara melihat kode sumber secara efisien
Jawaban saya adalah melihat kode sumber dengan pertanyaan spesifik, jika tidak, sangat mudah terjebak dalam detail kode sumber dan kemudian Anda akan pingsan. Akhirnya, Anda mengetahui apa yang telah Anda baca sejak lama.
perkenalan
Spring adalah kerangka kerja tingkat desain open source yang memecahkan masalah kopling longgar antara lapisan logika bisnis dan lapisan lainnya, dan mengintegrasikan ide pemrograman berorientasi antarmuka di seluruh aplikasi sistem. Ini juga salah satu keterampilan penting dalam pekerjaan Java ...
Karena mencatat proses analisis kode sumber pegas, saya tidak akan menguraikan penggunaan terperinci.
Kode inti
<dependency> <GroupId> org.springframework </groupId> <ArTifactId> Spring-Context </artifactid> <version> 5.0.2.release </version> </dependency>
penggunaan
aplikasi kelas publik {public static void main (string [] args) {beandefinitionregistry beanfactory = new DefaultListableBeanFactory (); XmlbeandefinitionReader reader = xmlbeandefinitionReader baru (beanfactory); ClassPathResource Resource = new ClassPathResource ("bean.xml"); // Titik masuk untuk seluruh pemuatan sumber daya. reader.loadBeandefinitions (sumber daya); }}Dekripsi
DefaultListableBeanFactory adalah implementasi default dari registrasi pegas dan memuat kacang. Itu bisa disebut leluhur di seluruh templat IOC musim semi.
Melacak DefaultListableBeanFactory, Anda dapat menemukan blok kode berikut. Apa tujuan dari desain ini?
public abstractAutowIrecAbleBeanFactory () {super (); abvoredependencyInterface (beannameaware.class); pengabdian dependencyInterface (beanfactoryAware.class); abvoredependencyInterface (beansclassloaderaware.class);}Misalnya, ketika ada atribut B dalam A, pegas akan secara otomatis membuat atribut B jika ditemukan bahwa atribut B tidak dipakai saat memperoleh atribut A. Ini juga merupakan fitur penting yang disediakan di musim semi. Dalam beberapa kasus, B tidak akan diinisialisasi, seperti mengimplementasikan antarmuka Beannameaware.
Spring memperkenalkan hal ini: Ketika auto-assembly, abaikan antarmuka ketergantungan yang diberikan, seperti parsing ketergantungan pendaftaran konteks aplikasi melalui metode lain, mirip dengan injeksi beanfactory melalui beanfactoryAware atau injeksi ApplicationContext melalui ApplicationContextAware.
Manajemen Sumber Daya
Antarmuka sumber daya digunakan untuk mengelola file, URL, ClassPath, dan sumber daya lainnya. Sumber Daya bertanggung jawab untuk membaca file konfigurasi, yaitu merangkum file konfigurasi ke dalam sumber daya, dan kemudian menyerahkannya ke XMLBeAndefinitionReader untuk diproses.
XML Parsing
XMLBeandefinitionReader adalah implementasi pembacaan file sumber daya, parsing, dan mendaftar, dan kita harus fokus pada kelas ini.
Track reader.loadBeanDefinitions(resource); , kita dapat melihat kode inti berikut (mengecualikan komentar dan melempar pengecualian)
public int loadBeandefinitions (encodedResource encodedResource) melempar BeandefinitionStoreException {try {inputStream inputStream = encodedResource.getResource (). getInputStream (); coba {inputSource inputsource = new InputSource (inputStream); if (encodedResource.getEncoding ()! = null) {inputSource.setencoding (encodedResource.getEncoding ()); } return doloadbeandefinitions (inputsource, encodedResource.getResource ()); } akhirnya {inputStream.close (); }}}Kode di atas pertama kali melakukan operasi pengkodean pada sumber daya, dengan tujuan mengkhawatirkan masalah pengkodean di XML
Jika Anda mengamati InputSource inputSource = new InputSource(inputStream); , Nama paketnya sebenarnya org.xml.sax, sehingga kita dapat menyimpulkan bahwa Spring menggunakan penguraian saksofon dan menggunakan inputsource untuk memutuskan cara membaca file XML.
Akhirnya, data yang disiapkan diteruskan ke bagian pemrosesan inti nyata melalui parameter doLoadBeanDefinitions(inputSource, encodedResource.getResource())
Dapatkan dokumen
1. doLoadBeanDefinitions(inputSource, encodedResource.getResource()); , menghilangkan beberapa tangkapan dan komentar
DoloadBeandefinitions (InputSource InputSource, sumber daya InputSource, sumber daya) melempar BeandefinitionStoreException {try {document doc = doloaddocument (inputSource, sumber daya); return registerBeandefinitions (doc, sumber daya); }} 2. doLoadDocument(inputSource, resource);
Dokumen yang Dilindungi DoloadDocument (InputSource InputSource, Resource Resource) melempar Exception {return this.documentloader.LoadDocument (inputSource, getEntityResolver (), this.errorHandler, getValidationModeforRource (sumber daya), iSnamespacea ();););); iSnamespacea ();););); iSnamespacea ();););); iSnamespacea (););); iSnamespacea (););); iSnamespacea ();); iSnamespacea ();); iSnamespacea (););), ISNAMESPACAA (););Pertama, Anda bisa mendapatkan mode verifikasi (DTD atau XSD) dari file XML melalui getValidationModeforReSource. Anda dapat mengatur metode verifikasi sendiri. Secara default, validation_auto diaktifkan, yaitu, mode verifikasi secara otomatis diperoleh. Baca file XML melalui InputStream dan periksa apakah itu berisi kata -kata Doctype. Jika mengandungnya, itu adalah DTD, jika tidak, ia akan mengembalikan XSD.
Pola verifikasi file XML umum adalah:
Kelas Publik XMLValidationModedEtector { /*** menunjukkan bahwa validasi DTD harus digunakan (kami menemukan deklarasi "Doctype"). */ Public Static Int Validation_DTD = 2; /*** menunjukkan bahwa validasi XSD harus digunakan (tidak menemukan deklarasi "Doctype"). */ public static int int validation_xsd = 3; public int detectValidationMode (inputStream inputStream) melempar ioException {}} Parameter EntityResolver terlibat dalam this.documentLoader.loadDocument Metode
Dokumen Publik LoadDocument (InputSource InputSource, EntityResolver EntityResolver, ErrorHandler errorHandler, int validationMode, boolean namespaceaware) melempar pengecualian {}Apa itu EntityResolver? Penjelasan Resmi: Jika aplikasi SAX perlu mengimplementasikan pemrosesan khusus entitas eksternal, ia harus mengimplementasikan antarmuka ini dan mendaftarkan instance dengan drive SAX menggunakan metode SetEntityResolver. Dengan kata lain, untuk mem -parsing XML, Sax pertama -tama akan membaca deklarasi pada dokumen XML, dan mencari definisi DTD yang sesuai sesuai dengan deklarasi, untuk memverifikasi dokumen, aturan pencarian default (mis., Unduh jaringan, unduh Definisi DTD melalui alamat DTD URI yang dinyatakan oleh XML), dan kinerja. Proses pengunduhan adalah proses yang panjang, dan ketika jaringan tidak tersedia, kesalahan akan dilaporkan di sini karena DTD yang sesuai belum ditemukan.
Fungsi EntityResolver adalah bahwa proyek itu sendiri dapat memberikan metode bagaimana menemukan deklarasi DTD, yaitu program mengimplementasikan proses menemukan DTD, yang menghindari menemukan deklarasi yang sesuai melalui jaringan.
3.entityResolver menerima dua parameter:
InputSource ResolveStity abstrak publik (String publicId, String SystemID) melempar SaxException, ioException;
3.1 Tentukan file bean.xml, dengan konten sebagai berikut (mode XSD)
<? XML Versi = "1.0" encoding = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://www.w3.org/2001/xmls XSI: schemalocation = "http://www.springframework.org/schema/beans.xsd"> </tobel>
Diurai ke dua parameter berikut:
3.2 Tentukan file bean.xml, dengan konten sebagai berikut (mode DTD)
<? Xml Version = "1.0" encoding = "UTF-8"?> <! Doctype Beans Public "-// Spring // DTD Bean 2.0 // en" "http://www.springframework.org/dtd/spring-seans.dtd"> <beans> </beans>
Diurai ke dua parameter berikut:
3.3 Musim Semi Menggunakan DelegatingEntityResolver untuk Mengurai EntityResolver
DelegatingEntityResolver kelas publik {@Override @nullable Public InputSource ReseVolEntity (String publicId, @nullable string systemid) melempar SAXException, ioException {if (SystemId! = NULL) {if (SystemId.endswith (dtd_suffix)) {return this.dtdres.dres.desol (dtd_suffix)) {return this. } lain if (systemid.endswith (xsd_suffix)) {return this.schemaresolver.resolveTentity (publicId, systemid); }} return null; }}Kita dapat melihat bahwa parser yang berbeda digunakan untuk mode yang berbeda
Daftarkan kacang
Setelah membaca verifikasi XML parsing, terus melacak kode dan lihat bagaimana Spring Registers Information berdasarkan dokumen
kelas publik xmlbeandefinitionReader {public int registerbeandefinitions (dokumen dokumen, sumber daya sumber daya) melempar beandefinitionstoreException {// DocumentReader BeandefinitionDocumentReader DocumentReader = createBeAdefinitionDocumentReader (); // Catat jumlah beandefinitions sebelum statistik int countbefore = getRegistry (). GetBeandefinitionCount (); // Daftar Beandefinition DocumentReader.RegisterBeandefinitions (DOC, CREATEREADERCONTEXT (sumber daya)); // Catat jumlah lefinisi beandeded yang dimuat kali ini kembali getRegistry (). GetBeandefinitionCount () - countbefore; }}Saat mendaftarkan kacang, pertama -tama gunakan kelas BeandefinitionParserDelegate untuk menentukan apakah itu namespace default. Implementasinya adalah untuk menentukan apakah URI namespace sama dengan URI default:
kelas publik 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)); , di mana DOC dikonversi melalui LoadDocument di blok kode sebelumnya. Tujuan utama dari metode ini adalah untuk mengekstrak node root (kacang)
kelas publik defaultBeandefinitionDocumentReader {@Override public void registerBeandefinitions (dokumen dokumen, xmlreaderContext readerContext) {this.readerContext = readerContext; logger.debug ("memuat definisi kacang"); Elemen root = doc.getDocumentElement (); doregisterbeandefinitions (root); }} Lacak doRegisterBeanDefinitions(root) dan kita akan melihat aliran pemrosesan berikut
Protected void doregisterbeandefinitions (elemen root) {// ... string profilespec = root.getAttribute (profile_attribute); // ... // implementasi kosong preprocessxml (root); parsebeandefinitions (root, this.delegate); // implementasi kosong postprocessxml (root); this.delegate = parent;}Pertama, parse profil (cara yang lebih umum untuk bermain adalah bahwa objek kacang yang diinisialisasi oleh profil yang berbeda berbeda, sehingga mereka menerapkan beberapa lingkungan)
Parsing berikut menggunakan mode metode templat, di mana preprocessxml dan postprocessxml keduanya adalah metode kosong, sehingga subkelas berikutnya dapat melakukan beberapa pemrosesan sebelum dan sesudah penguraian. Hanya mengesampingkan kedua metode ini.
Menganalisis dan mendaftar beandefinition, bagian kode ini relatif sederhana
Kelas Publik DefaultBeandefinitionDocumentReader { / *** Selesaikan node lain di bawah simpul root impor "," alias "," bean ".* @param root name* / void parsebeand {ifel {nod -nod) {nod) {nod) {nod) {nod) {nod) {nod) {nod) {nod) root.getChildNodes (); untuk (int i = 0; i <nl.getLength (); i ++) {node node = nl.item (i); delegate.parsecustomelement (ELE); ImportBandefinitionResource (ELE); (delegate.nodenameequals (ELE, Nested_Beans_element)) {// Recurse DoregisterBeandefinitions (ELE); bdholder = delegate.parsebeandefinitionElement (ELE); getReaderContext (). GetRegistry ()); BeanComponentDefinition (BDHolder));}} Delegasikan metode parsebeandefinitionElement dari kelas beandefinitionparserdelegate untuk parsing elemen, dan mengembalikan contoh tipe beandefinition pemegang BDHolder (termasuk berbagai atribut kelas file konfigurasi, nama, ID, alias, dll.)
Ketika BDHolder yang dikembalikan tidak kosong, jika ada atribut khusus di simpul anak dari label default, label kustom diuraikan dan diuraikan lagi, dan kemudian BeanDefinitionReaderUtils.registerBeanDefinition(); Register BDHolder dan mengirimkan acara pendaftaran, memberi tahu kacang mendengarkan yang relevan bahwa pendaftaran telah berhasil.
Meringkaskan
Setelah beberapa musim gugur, musim dingin, musim semi, dan musim panas yang tidak diketahui, semuanya akan mengikuti arah yang Anda inginkan ...
Oke, di atas adalah seluruh konten artikel ini. Saya berharap konten artikel ini memiliki nilai referensi tertentu untuk studi atau pekerjaan semua orang. Jika Anda memiliki pertanyaan, Anda dapat meninggalkan pesan untuk berkomunikasi. Terima kasih atas dukungan Anda ke wulin.com.
Katakan sesuatu
Kode Teks Lengkap: https://gitee.com/battcn/battcn-spring-source/tree/master/chapter1 (unduhan lokal)