Mari kita ambil acara permulaan aplikasi: ApplicationStartingEvent sebagai contoh untuk menggambarkan:
Mengambil kaedah SpringApplication.run kelas permulaan sebagai titik masuk, dan mengikuti dua kaedah dengan nama yang sama dalam SpringApplication, kita akan melihat kaedah larian utama, kaedahnya agak panjang, di sini hanya bahagian utama yang berkait rapat dengan pendengar disiarkan:
SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting();
Kami mengikuti kaedah permulaan, kandungan kaedah adalah seperti berikut:
void starting() { for (SpringApplicationRunListener listener : this.listeners) { listener.starting(); } }
Di sini Pendengar telah dimuatkan dalam kaedah getRunListeners Prinsip pemuatan adalah serupa dengan pemula sistem Mengenai pemuatan pemula sistem, anda boleh merujuk kepada analisis mendalam SpringBoot bagi pemula. >
Logik kaedah permulaan adalah sangat mudah, iaitu memanggil kaedah permulaan SpringApplicationRunListener. Mari teruskan menganalisis kaedah permulaan ini: Kami memasuki kaedah permulaan kelas EventPublishingRunListener (kelas pelaksanaan SpringApplicationRunListener):@Override public void starting() { this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args)); }Penyiar digunakan di sini untuk menyiarkan acara ApplicationStartingEvent baharu. Kami membuat susulan kaedah multicastEvent ini:
@Override public void multicastEvent(ApplicationEvent event) { multicastEvent(event, resolveDefaultEventType(event)); }Teruskan melihat kaedah multicastEvent dengan nama yang sama:
@Override public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); Executor executor = getTaskExecutor(); for (ApplicationListener<?> listener : getApplicationListeners(event, type)) { if (executor != null) { executor.execute(() -> invokeListener(listener, event)); } else { invokeListener(listener, event); } } }ResolvableType di sini membungkus acara, jadi kami menang' t beri perhatian kepadanya; kerana Kami tidak mencipta kumpulan benang, jadi pelaksana kosong. Kami memberi tumpuan kepada dua bahagian: Dapatkan semua pendengar aplikasi mendengar acara ini2 invokeListener --> Aktifkan pendengar getApplicationListeners (kaedah AbstractApplicationEventMulticaster). , kodnya adalah seperti berikut:
protected Collection<ApplicationListener<?>> getApplicationListeners( ApplicationEvent event, ResolvableType eventType) { Object source = event.getSource(); Class<?> sourceType = (source != null ? source.getClass() : null); ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType); // Quick check for existing entry on ConcurrentHashMap... ListenerRetriever retriever = this.retrieverCache.get(cacheKey); if (retriever != null) { return retriever.getApplicationListeners(); } if (this.beanClassLoader == null || (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) { // Fully synchronized building and caching of a ListenerRetriever synchronized (this.retrievalMutex) { retriever = this.retrieverCache.get(cacheKey); if (retriever != null) { return retriever.getApplicationListeners(); } retriever = new ListenerRetriever(true); Collection<ApplicationListener<?>> listeners = retrieveApplicationListeners(eventType, sourceType, retriever); this.retrieverCache.put(cacheKey, retriever); return listeners; } } else { // No ListenerRetriever caching -> no synchronization necessary return retrieveApplicationListeners(eventType, sourceType, null); } }Acara dalam parameter input ialah ApplicationStartingEvent, dan sourceType ialah kelas org.springframework.boot.SpringApplication. Saya menganggap jenis ListenerRetriever sebagai bekas yang menyimpan pendengar. Dapat dilihat bahawa atur cara mula-mula mencari pemulih jenis ListenerRetriever dalam cache. Jika ia tidak ditemui, ia mengunci dan mencarinya semula dalam cache. Tiada kandungan dalam cache kami di sini, jadi ia tidak akan dikembalikan. Kemudian gunakan kaedah retrieveApplicationListeners untuk melintasi pendengar. Kaedah retrieveApplicationListeners agak panjang bukan, membina a Tujuan proksi adalah untuk akhirnya memperoleh peristiwa yang pendengar berminat melalui penghuraian generik. Jika ditentukan bahawa pendengar berminat dengan acara tersebut, pendengar akan ditambahkan ke senarai pendengar.
protected boolean supportsEvent( ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) { GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ? (GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener)); return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType)); }Apabila semua pendengar untuk acara dikumpulkan, kaedah multicastEvent (kelas SimpleApplicationEventMulticaster) akan menyebarkan acara tersebut. Iaitu, panggil kaedah antara muka pencetus umum pendengar: listener.onApplicationEvent(event); Dengan cara ini, penyebaran acara ini selesai.
Atas ialah kandungan terperinci Bagaimana untuk melaksanakan mod pendengar SpringBoot. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!