SpringBoot實戰分析(三)監聽器分析

程序入口(SpringApplication)

SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();

監聽器的過程

-->程序啓動

-->調用getRunListeners(args)獲取SpringApplicationRunListeners實例

-->getSpringFactoriesInstances()獲取Spring工廠實例

-->loadFactoryNames()通過classLoader加載工廠實例

-->loadSpringFactories() 循環加載/META-INF/spring.factories中的類,組成集合返回

-->createSpringFactoriesInstances()根據加載文件返回的類名創建工廠實例,反射

-->listeners.starting()啓動監聽器

-->multicastEvent(ApplicationEvent event)組播ApplicationEvent事件

-->getApplicationListeners()判斷監聽器類型是否與當前監聽器類型相同

-->retrieveApplicationListeners(eventType, sourceType, retriever)檢索給定事件和源類型的應用程序監聽器。

-->supportsEvent(listener, eventType, sourceType)確定給定的監聽器是否支持給定的事件。

-->GenericApplicationListenerAdapter(ApplicationListener<?> delegate)爲給定的委託創建一個新的GenericApplicationListener。

-->resolveDeclaredEventType(ApplicationListener<ApplicationEvent> listener)發佈事件監聽

-->supportsEventType(eventType)從指定類型解析事件

-->結束

斷點跟蹤

1.獲取監聽

private SpringApplicationRunListeners getRunListeners(String[] args) {
    //定義class數組
    Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
    //創建SpringApplicationRunListeners 對象
    return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
        SpringApplicationRunListener.class, types, this, args));
}

2.獲取spring工廠實例

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
    Class<?>[] parameterTypes, Object... args) {
    // 類加載器
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    // Use names and ensure unique to protect against duplicates
    // 這個返回值是 META-INF/spring.factories 中定義的 父節點
    // names的返回值 傳送門7號
    Set<String> names = new LinkedHashSet<>(
    SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    //內部循環初始化 names的構造器
    List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
    classLoader, args, names);
    AnnotationAwareOrderComparator.sort(instances);
    return instances;
}

3.加載工廠

public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
    String factoryClassName = factoryClass.getName();
    return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}

通過加載META-INF/spring.factories文件,掃描文件,文件內容傳送門4號

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
    //從cache 實例的結果集 是Null 因爲當前的cache 是空的。
   //  cache 實現 new ConcurrentReferenceHashMap<>()
    MultiValueMap<String, String> result = cache.get(classLoader);
    if (result != null) {
        return result;
    }

    try {
        // urls 返回值 見傳送門2號
        Enumeration<URL> urls = (classLoader != null ?
               // 獲取 META-INF/spring.factories 中的資源
               //  FACTORIES_RESOURCE_LOCATION = META-INF/spring.factories
                //classLoader 不是null  走getResources方法
                //見傳送門1號
                classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
                ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
        result = new LinkedMultiValueMap<>();
       //循環處理urls中的元素
        while (urls.hasMoreElements()) {
            // 獲取元素
           // 第一個文件url地址 傳送門3號  
           // 第二個文件url地址  傳送門3號
           // 後續文件 同上
            UrlResource resource = new UrlResource(url);
           //解析文件 把文件內容變成配置屬性
           // 傳送門4號
            Properties properties = PropertiesLoaderUtils.loadProperties(resource);
            //循環解析並把結果放到result中
            //傳送門5號
            for (Map.Entry<?, ?> entry : properties.entrySet()) {
                List<String> factoryClassNames = Arrays.asList(
                        StringUtils.commaDelimitedListToStringArray((String) entry.getValue()));
                result.addAll((String) entry.getKey(), factoryClassNames);
            }
        }
       //緩存類加載器和文件解析的結果集
       // map.put
        cache.put(classLoader, result);
        // 結果 爲13條
        return result;
    }
    catch (IOException ex) {
        throw new IllegalArgumentException("Unable to load factories from location [" +
                FACTORIES_RESOURCE_LOCATION + "]", ex);
    }
}

4.創建Spring工廠實例

private <T> List<T> createSpringFactoriesInstances(Class<T> type,
        Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args,
        Set<String> names) {
    List<T> instances = new ArrayList<>(names.size());
   // 循環處理names的值
    for (String name : names) {
        try {
            Class<?> instanceClass = ClassUtils.forName(name, classLoader);
            Assert.isAssignable(type, instanceClass);
            Constructor<?> constructor = instanceClass
                    .getDeclaredConstructor(parameterTypes);
            T instance = (T) BeanUtils.instantiateClass(constructor, args);
            instances.add(instance);
        }
        catch (Throwable ex) {
            throw new IllegalArgumentException(
                    "Cannot instantiate " + type + " : " + name, ex);
        }
    }
    return instances;
}

public static Class<?> forName(String name, @Nullable ClassLoader classLoader)
        throws ClassNotFoundException, LinkageError {

    Assert.notNull(name, "Name must not be null");

    Class<?> clazz = resolvePrimitiveClassName(name);
    if (clazz == null) {
       // 緩存值爲空 無緩存    new HashMap<>(64);
        clazz = commonClassCache.get(name);
    }
    if (clazz != null) {
        return clazz;
    }
  //3個if判斷
    。。。。。。
 //通過加載器加載name值對應的類
    ClassLoader clToUse = classLoader;
    if (clToUse == null) {
        clToUse = getDefaultClassLoader();
    }
    try {
       //反射
        return (clToUse != null ? clToUse.loadClass(name) : Class.forName(name));
    }
    catch (ClassNotFoundException ex) {
        int lastDotIndex = name.lastIndexOf(PACKAGE_SEPARATOR);
        if (lastDotIndex != -1) {
            String innerClassName =
                    name.substring(0, lastDotIndex) + INNER_CLASS_SEPARATOR + name.substring(lastDotIndex + 1);
            try {
                return (clToUse != null ? clToUse.loadClass(innerClassName) : Class.forName(innerClassName));
            }
            catch (ClassNotFoundException ex2) {
                // Swallow - let original exception get through
            }
        }
        throw ex;
    }
}

5.加載監聽器類

listeners.starting();斷點進入

獲取EventPublishingRunListener調用構造方法
public EventPublishingRunListener(SpringApplication application, String[] args) {
    this.application = application;
    this.args = args;
    this.initialMulticaster = new SimpleApplicationEventMulticaster();
   // 給initialMulticaster 添加listener
    for (ApplicationListener<?> listener : application.getListeners()) {
        this.initialMulticaster.addApplicationListener(listener);
    }
}

6.啓動監聽

添加完監聽器之後,調用listeners.starting();

調用的是SpringApplicationRunListeners中的:

public void starting() {
    for (SpringApplicationRunListener listener : this.listeners) {
        listener.starting();
    }
}

實現類調用EventPublishingRunListener的方法:

@Override
public void starting() {
   //這個位置版本不同,寫法可能不一樣
    this.initialMulticaster.multicastEvent(
            new ApplicationStartingEvent(this.application, this.args));
}

在上面代碼中創建了一個ApplicationStartingEvent事件,將springapplicationthis.application傳入,因此監聽的時候獲取的是SpringApplication實例。

執行SimpleApplicationEventMulticaster中的multicastEvent()方法:

@Override
public void multicastEvent(ApplicationEvent event) {
    multicastEvent(event, resolveDefaultEventType(event));
}

執行SimpleApplicationEventMulticaster中的multicastEvent方法:

@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
   //注意getApplicationListeners獲取對應的事件監聽器
    for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
        Executor executor = getTaskExecutor();
        if (executor != null) {
            executor.execute(() -> invokeListener(listener, event));
        }
        else {
            invokeListener(listener, event);
        }
    }
}

執行AbstractApplicationEventMulticaster中的getApplicationListeners()

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...
    // 快速檢查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);
    }
}

//實際上檢索給定事件和源類型的應用程序監聽器是否匹配。

private Collection<ApplicationListener<?>> retrieveApplicationListeners(
        ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable ListenerRetriever retriever) {

    LinkedList<ApplicationListener<?>> allListeners = new LinkedList<>();
    Set<ApplicationListener<?>> listeners;
    Set<String> listenerBeans;
    synchronized (this.retrievalMutex) {
        //這個listeners集合就是前文提到的從配置中過濾的10個監聽器類
       //傳送門8號
        listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
       //空值
        listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
    }
   //循環10個listeners調用supportsEvent方法
    for (ApplicationListener<?> listener : listeners) {
        if (supportsEvent(listener, eventType, sourceType)) {
            if (retriever != null) {
                retriever.applicationListeners.add(listener);
            }
            allListeners.add(listener);
        }
    }

    省略。。。

    AnnotationAwareOrderComparator.sort(allListeners);
    return allListeners;
}
protected boolean supportsEvent(
        ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
   //判斷listener的類型是否是GenericApplicationListener的一個實例
    GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
            (GenericApplicationListener) listener :
//適配模式
 new GenericApplicationListenerAdapter(listener));
    return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
}

調用newGenericApplicationListenerAdapter()

@SuppressWarnings("unchecked")
public GenericApplicationListenerAdapter(ApplicationListener<?> delegate) {
    Assert.notNull(delegate, "Delegate listener must not be null");
    this.delegate = (ApplicationListener<ApplicationEvent>) delegate;
    this.declaredEventType = resolveDeclaredEventType(this.delegate);
}

@Nullable
private static ResolvableType resolveDeclaredEventType(ApplicationListener<ApplicationEvent> listener) {
    ResolvableType declaredEventType = resolveDeclaredEventType(listener.getClass());
    //判斷declaredEventType是否是ApplicationEvent事件
    if (declaredEventType == null || declaredEventType.isAssignableFrom(
            ResolvableType.forClass(ApplicationEvent.class))) {
        //獲取傳入的監聽器類
        Class<?> targetClass = AopUtils.getTargetClass(listener);
        if (targetClass != listener.getClass()) {
            declaredEventType = resolveDeclaredEventType(targetClass);
        }
    }
    return declaredEventType;
}

調用resolveDeclaredEventType()方法獲取指定類繼承的父類或實現接口時傳遞的泛型對應的類型

@Nullable
static ResolvableType resolveDeclaredEventType(Class<?> listenerType) {
    ResolvableType resolvableType = ResolvableType.forClass(listenerType).as(ApplicationListener.class);
    return (resolvableType.hasGenerics() ? resolvableType.getGeneric() : null);
}

調用supportsEventType方法

@Override
@SuppressWarnings("unchecked")
public boolean supportsEventType(ResolvableType eventType) {
    if (this.delegate instanceof SmartApplicationListener) {
        Class<? extends ApplicationEvent> eventClass = (Class<? extends ApplicationEvent>) eventType.resolve();
        return (eventClass != null && ((SmartApplicationListener) this.delegate).
//調用supportsEventType(),實際是調用自己
supportsEventType(eventClass));
    }
    else {
        return (this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType));
    }
}

遍歷所有的監聽器,如果該監聽器監聽的事件爲傳遞的事件或傳遞事件的父類則表示該監聽器支持指定事件。


傳送門1

// name =  META-INF/spring.factories
public Enumeration<URL> getResources(String name) throws IOException {
    @SuppressWarnings("unchecked")
    Enumeration<URL>[] tmp = (Enumeration<URL>[]) new Enumeration<?>[2];
    if (parent != null) {
        tmp[0] = parent.getResources(name);
    } else {
        tmp[0] = getBootstrapResources(name);
    }
    tmp[1] = findResources(name);

    return new CompoundEnumeration<>(tmp);
}

全路徑(本地路徑,根據配置不同路徑不同)

jar:file:/D:/maven/package/org/springframework/boot/spring-boot/2.0.2.RELEASE/spring-boot-2.0.2.RELEASE.jar!/META-INF/spring.factories

傳送門2

傳送門3





傳送門4

value爲當前key對應的屬性值以逗號分隔字符串。


文件內容

# PropertySource Loaders

org.springframework.boot.env.PropertySourceLoader=\

org.springframework.boot.env.PropertiesPropertySourceLoader,\

org.springframework.boot.env.YamlPropertySourceLoader


# Run Listeners

org.springframework.boot.SpringApplicationRunListener=\

org.springframework.boot.context.event.EventPublishingRunListener


# Error Reporters

org.springframework.boot.SpringBootExceptionReporter=\

org.springframework.boot.diagnostics.FailureAnalyzers


# Application Context Initializers

org.springframework.context.ApplicationContextInitializer=\

org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\

org.springframework.boot.context.ContextIdApplicationContextInitializer,\

org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\

org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer


# Application Listeners

org.springframework.context.ApplicationListener=\

org.springframework.boot.ClearCachesApplicationListener,\

org.springframework.boot.builder.ParentContextCloserApplicationListener,\

org.springframework.boot.context.FileEncodingApplicationListener,\

org.springframework.boot.context.config.AnsiOutputApplicationListener,\

org.springframework.boot.context.config.ConfigFileApplicationListener,\

org.springframework.boot.context.config.DelegatingApplicationListener,\

org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\

org.springframework.boot.context.logging.LoggingApplicationListener,\

org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener


# Environment Post Processors

org.springframework.boot.env.EnvironmentPostProcessor=\

org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\

org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\

org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor


# Failure Analyzers

org.springframework.boot.diagnostics.FailureAnalyzer=\

org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\

org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\

org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\

org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer,\

org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer,\

org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\

org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\

org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\

org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\

org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\

org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer


# FailureAnalysisReporters

org.springframework.boot.diagnostics.FailureAnalysisReporter=\

org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter

傳送門5




傳送門6



傳送門7


names的值經過下面函數處理

default V getOrDefault(Object key, V defaultValue) {
    V v;
    return (((v = get(key)) != null) || containsKey(key))
        ? v
        : defaultValue;
}

傳送門8號






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章