(轉)spring boot實戰(第三篇)事件監聽源碼分析

原文:http://blog.csdn.net/liaokailin/article/details/48194777java

監聽源碼分析

首先是咱們自定義的main方法:spring

package com.lkl.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.lkl.springboot.listener.MyApplicationStartedEventListener;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Application.class);
        //app.setAdditionalProfiles("dev");
        app.addListeners(new MyApplicationStartedEventListener());
        app.run(args);
    }
}

SpringApplication app = new SpringApplication(Application.class) 建立一個SpringApplication實例;建立實例執行對象構造方法;其構造方法以下:springboot

   public SpringApplication(Object... sources) {
        this.bannerMode = Mode.CONSOLE;
        this.logStartupInfo = true;
        this.addCommandLineProperties = true;
        this.headless = true;
        this.registerShutdownHook = true;
        this.additionalProfiles = new HashSet();
        this.initialize(sources);
    }

調用initialize(),該方法執行若干初始化操做,在後續再繼續深刻該方法。app

app.addListeners(new MyApplicationStartedEventListener()); 調用SpringApplication添加監聽的方法執行操做:less

    public void addListeners(ApplicationListener... listeners) {
        this.listeners.addAll(Arrays.asList(listeners));
    }

this.listenersList<ApplicationListener<?>>類型,是SpringApplication中全部監聽器的持有容器(initialize()方法中也會往該監聽集合中添加初始化的監聽器spring-boot

執行完添加監聽器方法後執行app.run(args)方法工具

    public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        this.configureHeadlessProperty();
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.started();

        try {
            DefaultApplicationArguments ex = new DefaultApplicationArguments(args);
            context = this.createAndRefreshContext(listeners, ex);
            this.afterRefresh(context, (ApplicationArguments)ex);
            listeners.finished(context, (Throwable)null);
            stopWatch.stop();
            if(this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }

            return context;
        } catch (Throwable var6) {
            this.handleRunFailure(context, listeners, var6);
            throw new IllegalStateException(var6);
        }
    }

 

run()方法中完成了spring boot的啓動,方法代碼比較長,本篇重點放在事件監聽上;源碼分析

SpringApplicationRunListeners listeners = this.getRunListeners(args);

經過getRunListeners(args)獲取執行時監聽的集合,其代碼以下:this

    private SpringApplicationRunListeners getRunListeners(String[] args) {
        Class[] types = new Class[]{SpringApplication.class, String[].class};
        return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, new Object[]{this, args}));
    }

重點關注url

 
private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args)
這個方法返回
    private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        LinkedHashSet names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
        List instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
        AnnotationAwareOrderComparator.sort(instances);
        return instances;
    }

 SpringFactoriesLoader.loadFactoryNames(type, classLoader)

   public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
        String factoryClassName = factoryClass.getName();

        try {
            Enumeration ex = classLoader != null?classLoader.getResources("META-INF/spring.factories"):ClassLoader.getSystemResources("META-INF/spring.factories");
            ArrayList result = new ArrayList();

            while(ex.hasMoreElements()) {
                URL url = (URL)ex.nextElement();
                Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
                String factoryClassNames = properties.getProperty(factoryClassName);
                result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
            }

            return result;
        } catch (IOException var8) {
            throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + "META-INF/spring.factories" + "]", var8);
        }
    }

其中

Enumeration ex = classLoader != null?classLoader.getResources("META-INF/spring.factories"):ClassLoader.getSystemResources("META-INF/spring.factories");

經過類加載器獲取resources; "META-INF/spring.factories"; 代碼會去掃描項目工程中/META-INF下的spring.factories文件,獲取org.springframework.boot.SpringApplicationRunListener對應數據 

 


spring-boot-1.3.6.RELEASE中能夠找到以下信息

# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

即經過SpringApplicationRunListeners listeners = this.getRunListeners(args);最終拿到的是EventPublishingRunListener

 (這裏還要作一個詳細的回顧)

在獲取EventPublishingRunListener實例時,執行對應構造方法

    public EventPublishingRunListener(SpringApplication application, String[] args) {
        this.application = application;
        this.args = args;
        this.multicaster = new SimpleApplicationEventMulticaster();
        Iterator var3 = application.getListeners().iterator();

        while(var3.hasNext()) {
            ApplicationListener listener = (ApplicationListener)var3.next();
            this.multicaster.addApplicationListener(listener);
        }

    }

SpringApplication中的監聽器傳遞給SimpleApplicationEventMulticaster實例multicaster

執行

 

        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.started();        
    public void started() {
        Iterator var1 = this.listeners.iterator();

        while(var1.hasNext()) {
            SpringApplicationRunListener listener = (SpringApplicationRunListener)var1.next();
            listener.started();
        }

    }

 

調用EventPublishingRunListener中的started()方法

 

  public void started() {
        this.publishEvent(new ApplicationStartedEvent(this.application, this.args));
    }

在該方法中首先建立一個ApplicationStartedEvent事件,將this.application傳遞過去,所以在執行ApplicationStartedEvent監聽時能夠獲取SpringApplication實例。

執行publishEvent() 方法(這裏就開始執行監聽事件後調用的方法了)

    private void publishEvent(SpringApplicationEvent event) {
        this.multicaster.multicastEvent(event);
    }

(這裏還要分析一下multicaster接口的初始化)

調用SimpleApplicationEventMulticaster#multicastEvent(event)

    public void multicastEvent(ApplicationEvent event) {
        this.multicastEvent(event, this.resolveDefaultEventType(event));
    }

    public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
        ResolvableType type = eventType != null?eventType:this.resolveDefaultEventType(event);
        Iterator var4 = this.getApplicationListeners(event, type).iterator();

        while(var4.hasNext()) {
            final ApplicationListener listener = (ApplicationListener)var4.next();
            Executor executor = this.getTaskExecutor();
            if(executor != null) {
                executor.execute(new Runnable() {
                    public void run() {
                        SimpleApplicationEventMulticaster.this.invokeListener(listener, event);
                    }
                });
            } else {
                this.invokeListener(listener, event);
            }
        }

    }

在該代碼中須要注意的是for循環中獲取監聽器集合方getApplicationListeners(event),因爲傳遞的事件爲ApplicationStartedEvent,所以該方法須要獲取到ApplicationStartedEvent對應的監聽器

    protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {
        Object source = event.getSource();
        Class sourceType = source != null?source.getClass():null;
        AbstractApplicationEventMulticaster.ListenerCacheKey cacheKey = new AbstractApplicationEventMulticaster.ListenerCacheKey(eventType, sourceType);
        AbstractApplicationEventMulticaster.ListenerRetriever retriever = (AbstractApplicationEventMulticaster.ListenerRetriever)this.retrieverCache.get(cacheKey);
        if(retriever != null) {
            return retriever.getApplicationListeners();
        } else if(this.beanClassLoader == null || ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader))) {
            Object var7 = this.retrievalMutex;
            synchronized(this.retrievalMutex) {
                retriever = (AbstractApplicationEventMulticaster.ListenerRetriever)this.retrieverCache.get(cacheKey);
                if(retriever != null) {
                    return retriever.getApplicationListeners();
                } else {
                    retriever = new AbstractApplicationEventMulticaster.ListenerRetriever(true);
                    Collection listeners = this.retrieveApplicationListeners(eventType, sourceType, retriever);
                    this.retrieverCache.put(cacheKey, retriever);
                    return listeners;
                }
            }
        } else {
            return this.retrieveApplicationListeners(eventType, sourceType, (AbstractApplicationEventMulticaster.ListenerRetriever)null);
        }
    }

retrieveApplicationListeners(event, sourceType, null)方法;

    private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType, Class<?> sourceType, AbstractApplicationEventMulticaster.ListenerRetriever retriever) {
        LinkedList allListeners = new LinkedList();
        Object beanFactory = this.retrievalMutex;
        LinkedHashSet listeners;
        LinkedHashSet listenerBeans;
        synchronized(this.retrievalMutex) {
            listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners);
            listenerBeans = new LinkedHashSet(this.defaultRetriever.applicationListenerBeans);
        }

        Iterator beanFactory1 = listeners.iterator();

        while(beanFactory1.hasNext()) {
            ApplicationListener listener = (ApplicationListener)beanFactory1.next();
            if(this.supportsEvent(listener, eventType, sourceType)) {
                if(retriever != null) {
                    retriever.applicationListeners.add(listener);
                }

                allListeners.add(listener);
            }
        }

        if(!listenerBeans.isEmpty()) {
            BeanFactory beanFactory2 = this.getBeanFactory();
            Iterator listener2 = listenerBeans.iterator();

            while(listener2.hasNext()) {
                String listenerBeanName = (String)listener2.next();

                try {
                    Class listenerType = beanFactory2.getType(listenerBeanName);
                    if(listenerType == null || this.supportsEvent(listenerType, eventType)) {
                        ApplicationListener listener1 = (ApplicationListener)beanFactory2.getBean(listenerBeanName, ApplicationListener.class);
                        if(!allListeners.contains(listener1) && this.supportsEvent(listener1, eventType, sourceType)) {
                            if(retriever != null) {
                                retriever.applicationListenerBeans.add(listenerBeanName);
                            }

                            allListeners.add(listener1);
                        }
                    }
                } catch (NoSuchBeanDefinitionException var13) {
                    ;
                }
            }
        }

        AnnotationAwareOrderComparator.sort(allListeners);
        return allListeners;
    }

調用supportsEvent方法判斷對應的監聽器是否支持指定的事件

    protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, Class<?> sourceType) {
        Object smartListener = listener instanceof GenericApplicationListener?(GenericApplicationListener)listener:new GenericApplicationListenerAdapter(listener);
        return ((GenericApplicationListener)smartListener).supportsEventType(eventType) && ((GenericApplicationListener)smartListener).supportsSourceType(sourceType);
    }

執行 GenericApplicationListenerAdapter#supportsEventType(eventType)

    public boolean supportsEventType(ResolvableType eventType) {
        if(this.delegate instanceof SmartApplicationListener) {
            Class eventClass = eventType.getRawClass();
            return ((SmartApplicationListener)this.delegate).supportsEventType(eventClass);
        } else {
            return this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType);
        }
    }

GenericTypeResolver泛型解析工具類功能強大,咱們在實際開發中一樣能夠利用。

至此getApplicationListeners(event)調用完成,大致思路爲:遍歷全部的監聽器,若是該監聽器監聽的事件爲傳遞的事件或傳遞事件的父類則表示該監聽器支持指定事件。

獲取完指定事件對應監聽器後,經過Executor執行一個子線程去完成監聽器listener.onApplicationEvent(event)方法。

相關文章
相關標籤/搜索