Container life cycle--Lifecycle

Other URL

Lifecycle and SmartLifecycle proper use posture _ Kaka seniors -CSDN blog
Spring container-level lifecycle callbacks --LifeCycle_tinysakura the blog -CSDN blog
[analysis] Source Spring 39-Spring container life cycle callback interface --LifeCycle_ leading to the mysterious road Column -CSDN blog

Introduction

The initialization method and destruction method of the bean are at the Bean life cycle level; and the Lifecycle is at the container life cycle level. If we want to do some work on events in the life cycle of the container itself (such as after the container is started and before it is stopped), we can use the LifeCycle interface.

LifeCycle

Introduction

Source code

public interface Lifecycle {
    void start();
    void stop();
    boolean isRunning();
}

start: if class A is not running (isRunning returns false), then go to this method; otherwise, do not go to this method
stop: if class A is running (isRunning returns true), go to this method; otherwise, do not go to this method
isRunning: return true means class A has been running, return false means class A is not running

Simple example

isRunning returns true

Code

package com.example.config;

import org.springframework.context.Lifecycle;
import org.springframework.stereotype.Component;

@Component
public class MyLifeCycle implements Lifecycle {

	@Override
	public void start() {
		System.out.println("start");
	}

	@Override
	public void stop() {
		System.out.println("stop");
	}

	@Override
	public boolean isRunning() {
		System.out.println("isRunning");
		return true;
	}
}

result

No printing at startup 

When closed:

isRunning
stop

isRunning returns false

package com.example.config;

import org.springframework.context.Lifecycle;
import org.springframework.stereotype.Component;

@Component
public class MyLifeCycle implements Lifecycle {

	@Override
	public void start() {
		System.out.println("start");
	}

	@Override
	public void stop() {
		System.out.println("stop");
	}

	@Override
	public boolean isRunning() {
		System.out.println("isRunning");
		return false;
	}
}

result

No printing at startup

When closed

isRunning

Change isRunning value

I thought that manually changing the return value of isRunning can make it execute both start() and stop(), but I was wrong, as shown below:

package com.example.config;

import org.springframework.context.Lifecycle;
import org.springframework.stereotype.Component;

@Component
public class MyLifeCycle implements Lifecycle {
	private volatile boolean running = false;

	@Override
	public void start() {
		System.out.println("start");
		running = true;
	}

	@Override
	public void stop() {
		System.out.println("stop");
	}

	@Override
	public boolean isRunning() {
		System.out.println("isRunning");
		return running;
	}
}

result

No printing at startup 

When closed:

isRunning

Explicitly call start()

Other website: https://blog.csdn.net/u011624903/article/details/109000785

In the "simple example" above, you can find that no matter how you do it, you can't call the start() method! ! . Some people say that it must be called explicitly, as shown below:

public static void main(String[] args) {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
            "com.example.config.MyLifecycle");
    ctx.start();
    ctx.close();
}

However, I only see the following output:

19:20:23.914 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@3ab39c39
19:20:23.924 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
19:20:23.944 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
19:20:23.944 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
19:20:23.944 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
19:20:23.944 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
19:20:23.964 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'spring.liveBeansView.mbeanDomain' in PropertySource 'systemProperties' with value of type String
19:20:23.974 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@3ab39c39, started on Tue Mar 09 19:20:23 CST 2021
19:20:23.974 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'spring.liveBeansView.mbeanDomain' in PropertySource 'systemProperties' with value of type String

In this regard, there should be a black question mark face. . . Save it to see why this happens later

SmartLifeCycle

Introduction

Description

SmartLifecycle is a sub-interface of Lifecycle, which has more functions than Lifecycle. Among them are the two most important improvements:

  1. You can call back the start() of the SmartLifecycle interface without calling the start() method of the container display
  2. If there are multiple SmartLifecycle instances in the container, it is convenient to control the calling sequence.

method

Method name

description

isAutoStartup ()

Must return true. Otherwise, the start() method will not be called back when the container starts.

true: Let the context in which the Lifecycle class is located can automatically call back when calling `refresh`.
false: indicates that the component intends to be started by an explicit start() call, similar to a normal Lifecycle implementation. This must return true, otherwise it will be the same as Lifecycle.

getPhase()

Control the callback sequence of multiple SmartLifecycles: the smaller: the start() method is forward, and the stop() method is backward

isRunning()

Like the functions in the Lifecycle interface, it is used to judge whether your broken component is running.

start()

If class A is not running (isRunning returns false), then this method is used; otherwise, this method is not used.

Called when the container is refreshed (startup is complete). Same as Lifecycle interface.

stop(Runnable callback)

When the container is stopped, the method is called back.

After executing your custom logic, be sure to call callback.run(); This is to tell the container that you have stopped your component to complete.
Many source code will only write two lines of code in this method, refer to the following example. One line is stop(): forward the real logic to the stop() method. The other line is callback.run(), which must be called;

This method has a timeout period, the default is 30s. The timeout period can be set in the following ways

stop()

You need to call it yourself. Will not be called by the Spring framework

stop(Runnable callback)

Other websites: Introduction to Spring 5.0.0 Framework_Chinese Version_3.6

The stop method defined in SmartLifecycle receives a callback function. Any implementation must call the callback run() method after the shutdown process is complete. This can be closed asynchronously when needed, because the default implementation of the LifecycleProcessor interface and the DefaultLifecycleProcessor interface will wait for the object group at each stage until the timeout value is reached, and then call the callback function. The default timeout value for each stage is 30 seconds . You can override the default lifecycle processor instance by defining a bean named "lifecycleProcessor" in the context. If you only want to modify the timeout value, just change it like this:

<bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor">
    <!-- timeout value in milliseconds -->
    <property name="timeoutPerShutdownPhase" value="10000"/>
</bean>

Simple example

Code

package com.example.config;

import org.springframework.context.SmartLifecycle;
import org.springframework.stereotype.Component;

@Component
public class MySmartLifecycle implements SmartLifecycle {
    private volatile boolean running = false;

    /**
     * true:让Lifecycle类所在的上下文在调用`refresh`时,能够自己自动进行回调
     * false:表明组件打算通过显式的start()调用来启动,类似于普通的Lifecycle实现。
     */
    @Override
    public boolean isAutoStartup() {
        return true;
    }

    /**
     * 很多框架中,把真正逻辑写在stop()方法内。比如quartz和Redis的spring支持包
     */
    @Override
    public void stop(Runnable callback) {
        System.out.println("stop(callback)");
        stop();
        callback.run();
    }

    @Override
    public void start() {
        System.out.println("start()");
        running = true;
    }

    @Override
    public void stop() {
        System.out.println("stop()");
        running = false;
    }

    @Override
    public boolean isRunning() {
        System.out.println("isRunning()");
        return running;
    }

    /**
     * 阶段值。越小:start()方法越靠前,stop()方法越靠后
     */
    @Override
    public int getPhase() {
        System.out.println("getPhase()");
        return 0;
    }
}

test

At startup:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.0.RELEASE)

2021-03-09 19:30:57.138  INFO 6600 --- [           main] com.example.DemoApplication              : Starting DemoApplication on DESKTOP-QI6B9ME with PID 6600 (E:\work\Idea_proj\demo_JAVA\demo_SpringBoot\target\classes started by Liu in E:\work\Idea_proj\demo_JAVA\demo_SpringBoot)
2021-03-09 19:30:57.143  INFO 6600 --- [           main] com.example.DemoApplication              : No active profile set, falling back to default profiles: default
2021-03-09 19:30:57.899  INFO 6600 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2021-03-09 19:30:57.907  INFO 6600 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-03-09 19:30:57.907  INFO 6600 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.35]
2021-03-09 19:30:57.986  INFO 6600 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-03-09 19:30:57.986  INFO 6600 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 808 ms
2021-03-09 19:30:58.135  INFO 6600 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
getPhase()
isRunning()
start()
2021-03-09 19:30:58.260  INFO 6600 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2021-03-09 19:30:58.268  INFO 6600 --- [           main] com.example.DemoApplication              : Started DemoApplication in 1.442 seconds (JVM running for 2.44)

When closed:

getPhase()
isRunning()
stop(callback)
stop()

 

 

Guess you like

Origin blog.csdn.net/feiying0canglang/article/details/114558690