一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Spring中SmartLifecycle和Lifecycle的作用和區別

Spring中SmartLifecycle和Lifecycle的作用和區別

2021-08-23 11:32brucelwl Java教程

這篇文章主要介紹了Spring中SmartLifecycle和Lifecycle的作用和區別,本文通過實例代碼給大家介紹的非常詳細對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

本文基于SpringBoot 2.5.0-M2講解Spring中LifecycleSmartLifecycle的作用和區別,以及如何控制SmartLifecycle的優先級。
并講解SpringBoot中如何通過SmartLifecycle來啟動/停止web容器.

 SmartLifecycle和Lifecycle作用

都是讓開發者可以在所有的bean都創建完成(getBean) 之后執行自己的初始化工作,或者在退出時執行資源銷毀工作

SmartLifecycle和Lifecycle區別

 1.SmartLifecycle接口繼承Lifecycle接口,同時繼承了org.springframework.context.Phased接口用于控制多個SmartLifecycle實現之間的優先級。

2.在SpringBoot應用中,或在Spring應用中沒有調用AbstractApplicationContext#start方法,如果一個Bean只是實現了Lifecycle接口的情況下:

不會執行Lifecycle接口中的啟動方法,包括Lifecycle#isRunning方法也不會被執行。

但是在應用 退出時 會執行Lifecycle#isRunning方法判斷該Lifecycle是否已經啟動,如果返回true則調用Lifecycle#stop()停止方法

3. 如果一個Bean實現了SmartLifecycle接口,則會執行啟動方法。先會被根據Phased接口優先級分組,封裝在LifecycleGroup,然后循環調用LifecycleGroup#start()方法,SmartLifecycle#isRunning判斷是否已經執行,返回false表示還未執行,則調用SmartLifecycle#start()執行。Phased返回值越小,優先級越高。

4.SmartLifecycle中還有個isAutoStartup方法,如果返回false,在啟動時也不會執行start方法,默認返回true

源碼分析

SmartLifecycleLifecycle都是在org.springframework.context.support.DefaultLifecycleProcessor中被調用,
DefaultLifecycleProcessor#onRefresh方法在執行AbstractApplicationContext#finishRefresh時會被調用,調用棧如下:

?
1
2
3
4
5
6
7
8
9
10
11
startBeans:142, DefaultLifecycleProcessor (org.springframework.context.support)
onRefresh:123, DefaultLifecycleProcessor (org.springframework.context.support)
finishRefresh:934, AbstractApplicationContext (org.springframework.context.support)
refresh:585, AbstractApplicationContext (org.springframework.context.support)
refresh:144, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
refresh:755, SpringApplication (org.springframework.boot)
refreshContext:426, SpringApplication (org.springframework.boot)
run:326, SpringApplication (org.springframework.boot)
run:1299, SpringApplication (org.springframework.boot)
run:1288, SpringApplication (org.springframework.boot)
main:31, DemoApplication (com.example.demo)

DefaultLifecycleProcessor#onRefresh源碼:

?
1
2
3
4
5
@Override
public void onRefresh() {
    startBeans(true); //autoStartupOnly = true
    this.running = true;
}

DefaultLifecycleProcessor#startBeans源碼如下:
autoStartupOnly 在onRefresh時傳入的是true,表示只執行可以自動啟動的bean,即為:SmartLifecycle的實現類,并且SmartLifecycle#isAutoStartup返回值必須為true。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void startBeans(boolean autoStartupOnly) {
    Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
    Map<Integer, LifecycleGroup> phases = new TreeMap<>();
 
    lifecycleBeans.forEach((beanName, bean) -> {
        if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
            int phase = getPhase(bean);
            phases.computeIfAbsent(phase, p ->
             new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly)
            ).add(beanName, bean);
        }
    });
    if (!phases.isEmpty()) {
        phases.values().forEach(LifecycleGroup::start);
    }
}

而Spring AbstractApplicationContext#doClose退出時,無論是SmartLifecycleLifecycle都會執行isRunning方法,判斷是否已經啟動,返回true表示已經啟動,則執行SmartLifecycleLifecyclestop方法。
源碼見:org.springframework.context.support.DefaultLifecycleProcessor#doStop方法。

而執行AbstractApplicationContext#doClose一般是應用進程退出,通過jvm注冊的鉤子方法,或者應用程序編碼調用。
AbstractApplicationContext#registerShutdownHook源碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
public void registerShutdownHook() {
    if (this.shutdownHook == null) {
        // No shutdown hook registered yet.
        this.shutdownHook = new Thread(SHUTDOWN_HOOK_THREAD_NAME) {
            @Override
            public void run() {
                synchronized (startupShutdownMonitor) {
                    doClose();
                }
            }
        };
        Runtime.getRuntime().addShutdownHook(this.shutdownHook);
    }
}

自定義LifecycleProcessor處理Lifecycle

在源碼分析中提到了DefaultLifecycleProcessor,其實現了LifecycleProcessor接口。然而我們自己也可以實現該接口,替換默認的DefaultLifecycleProcessor。SpringBoot中則是自己配置了DefaultLifecycleProcessor,我們可以按照同樣的方式,覆蓋默認的實現。例如可以讓Lifecycle中的start()方法在onRefresh()時也能被執行。

org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration源碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
 * {@link EnableAutoConfiguration Auto-configuration} relating to the application
 * context's lifecycle.
 *
 * @author Andy Wilkinson
 * @since 2.3.0
 */
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(LifecycleProperties.class)
public class LifecycleAutoConfiguration {
 
    @Bean(name = AbstractApplicationContext.LIFECYCLE_PROCESSOR_BEAN_NAME)
    @ConditionalOnMissingBean(name = AbstractApplicationContext.LIFECYCLE_PROCESSOR_BEAN_NAME,
            search = SearchStrategy.CURRENT)
    public DefaultLifecycleProcessor defaultLifecycleProcessor(LifecycleProperties properties) {
        DefaultLifecycleProcessor lifecycleProcessor = new DefaultLifecycleProcessor();
        lifecycleProcessor.setTimeoutPerShutdownPhase(properties.getTimeoutPerShutdownPhase().toMillis());
        return lifecycleProcessor;
    }
}

SpringBoot中內嵌web容器啟動時機

SpringBoo中就是通過實現SmartLifecycle來啟動內嵌的web容器,實現類為WebServerStartStopLifecycle

ServletWebServerApplicationContextonRefresh方法中調用createWebServercreateWebServer方法中創建org.springframework.boot.web.server.WebServer實例,該對象則包含了控制web容器(tomcatjetty)的啟動與停止方法。

?
1
2
3
4
5
6
7
8
9
@Override
protected void onRefresh() {
    super.onRefresh();
    try {
        createWebServer();
    }catch (Throwable ex) {
        throw new ApplicationContextException("Unable to start web server", ex);
    }
}

ServletWebServerApplicationContext#createWebServer源碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private void createWebServer() {
    WebServer webServer = this.webServer;
    ServletContext servletContext = getServletContext();
    if (webServer == null && servletContext == null) {
        StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");
        ServletWebServerFactory factory = getWebServerFactory();
        createWebServer.tag("factory", factory.getClass().toString());
        this.webServer = factory.getWebServer(getSelfInitializer());
        createWebServer.end();
        getBeanFactory().registerSingleton("webServerGracefulShutdown",
                new WebServerGracefulShutdownLifecycle(this.webServer));
        getBeanFactory().registerSingleton("webServerStartStop",
                new WebServerStartStopLifecycle(this, this.webServer));
    }
    else if (servletContext != null) {
        try {
            getSelfInitializer().onStartup(servletContext);
        }
        catch (ServletException ex) {
            throw new ApplicationContextException("Cannot initialize servlet context", ex);
        }
    }
    initPropertySources();
}

createWebServer方法會將創建的webServer封裝在WebServerStartStopLifecycle對象中,并注冊到Spring容器中。

org.springframework.boot.web.servlet.context.WebServerStartStopLifecycle源碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class WebServerStartStopLifecycle implements SmartLifecycle {
 
    private final ServletWebServerApplicationContext applicationContext;
    private final WebServer webServer;
    private volatile boolean running;
 
    WebServerStartStopLifecycle(ServletWebServerApplicationContext applicationContext, WebServer webServer) {
        this.applicationContext = applicationContext;
        this.webServer = webServer;
    }
 
    @Override
    public void start() {
        this.webServer.start();
        this.running = true;
        this.applicationContext
                .publishEvent(new ServletWebServerInitializedEvent(this.webServer, this.applicationContext));
    }
 
    @Override
    public void stop() { this.webServer.stop(); }
 
    @Override
    public boolean isRunning() {    return this.running; }
 
    @Override
    public int getPhase() { return Integer.MAX_VALUE - 1; }
}

WebServerStartStopLifecycle則實現了SmartLifecycle接口,當Spring回調到SmartLifecycle接口方法時則調用this.webServer.start();啟動web容器,web容器啟動完成之后會通過applicationContext發布ServletWebServerInitializedEvent事件,表示web容器啟動成功,可以接收http請求。

和SmartInitializingSingleton區別

相同點:SmartInitializingSingletonLifecycleSmartLifecycle都是在所有的單實例bean創建(getBean方法)之后執行。

不同點:

  • SmartInitializingSingleton優先于LifecycleSmartLifecycle執行。
  • SmartInitializingSingleton只有一個afterSingletonsInstantiated方法。而Lifecyclestart,stop,isRunning等方法。
  • 多個SmartInitializingSingleton實現之間無法排序控制執行的順序,而SmartLifecycle實現了Phased接口,可以通過int getPhase()控制執行循序。
  • SmartInitializingSingleton之間可以通過@DependsOn來控制執行順序,但這是由Spring中@DependsOn注解的作用及原理來實現的. 并不是對SmartInitializingSingleton做了排序。

到此這篇關于Spring中SmartLifecycle和Lifecycle的作用和區別的文章就介紹到這了,更多相關Spring中SmartLifecycle和Lifecycle內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/u013202238/article/details/114489001

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 波多野结衣在线免费观看 | 亚洲国产精品综合久久一线 | 国产欧美精品一区二区三区 | 亚洲成人中文 | 幻女free性俄罗斯第一次摘花 | 99操视频| 放荡警察巨r麻麻出轨小说 范冰冰特黄xx大片 饭冈加奈子在线播放观看 法国老妇性xx在线播放 | 欧美午夜精品久久久久久黑人 | 人性本色 | 国产91影院| 五月激情丁香婷婷综合第九 | 久久内在线视频精品mp4 | 全程粗语对白视频videos | 精品国产免费 | 大ji巴好好爽好深网站 | 欧美日韩亚洲高清不卡一区二区三区 | 精品一区二区三区高清免费不卡 | 末代皇帝无删减版在线观看 | 京东热dj6666 | 91精品国产免费久久 | 亚洲精品久久久久AV无码 | 欧美性一级交视频 | 色综合图片| 亚洲第一色网站 | 妇伦小说 | 国产精品成人免费观看 | 亚洲 欧美 中文字幕 在线 | 亚洲人成激情在线播放 | 奇米网狠狠网 | 色哟哟在线观看 | 美女机巴| 日韩精品1 | 欧美成人在线影院 | 99久久精品久久久久久清纯 | 亚洲码和乱人伦中文一区 | 日韩中文字幕在线不卡 | 成人欧美一区二区三区黑人 | 国产伦精品一区二区 | 亚洲国产美女精品久久久久 | 69午夜影院| 毛片网在线观看 |