Sometimes we need to perform some initialization actions automatically after the system is started, such as loading custom resources, starting business-related timers, or performing some other registration actions after the bean is initialized. A core element of this is method execution timing. To summarize, there are two main categories of method execution timing in Spring:

  1. The lifecycle callback is triggered.
  2. springThe event is triggered.

Triggered by a lifecycle callback

Lifecycle callbacks are summarized on the Spring website in three ways:

  1. Methods annotated with @PostConstruct
  2. afterPropertiesSet() as defined by the InitializingBean callback interface
  3. A custom configured init()Method, usually used inxmlIn configuration, configure one in the bean labelinit-methodimplementation

There are three corresponding logout callback methods:

  1. Methods annotated with @PreDestroy
  2. destroy() as defined by the DisposableBean callback interface
  3. A custom configured destroy()Method, usually used inxmlIn configuration, configure one in the bean labeldestroy-methodimplementation

The execution timing of these three methods is in the order above.

PostConstructExecution timing of

afterPropertiesSetExecution timing of

AfterPropertiesSet is in AbstractAutowireCapableBeanFactory initializeBean calls, which is the initialization of the bean bean instantiation process, At this point spring has finished proxying, dependency injection, and started performing some initialization methods on the bean.

To do this, note invokeInitMethods, which is the entry to afterPropertiesSet, This method of execution time is executive postProcessBeforeInitialization and applyBeanPostProcessorsAfterInitialization post processor.

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		if(System.getSecurityManager() ! =null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null| |! mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); }try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw newBeanCreationException( (mbd ! =null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null| |! mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); }return wrappedBean;
	}
Copy the code

Look again at the concrete implementation of invokeInitMethods

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {

		boolean isInitializingBean = (bean instanceof InitializingBean);
		if(isInitializingBean && (mbd == null || ! mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
			if(System.getSecurityManager() ! = null) { try { AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { ((InitializingBean) bean).afterPropertiesSet();returnnull; }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); }}else{ ((InitializingBean) bean).afterPropertiesSet(); }}}Copy the code

Triggered by a Spring event

This is triggered by using the @EventListener annotation to listen for events published by Spring and perform some business operations upon receipt of the event. For example, if we want to start our business logic after the Spring container initialization is complete, here is an example code:

@EventListener(classes = ContextRefreshedEvent.class)
public void enableSchedule(a) {  
    this.scheduleFlag = true;
}
Copy the code

Spring’s built-in events are mentioned in 1.15.2 Standard and Custom Events.

ontextRefreshedEvent Published when the ApplicationContext is initialized or refreshed (for example, by using the refresh() method on the ConfigurableApplicationContextInterface). Here, “initialized” means that all beans are loaded, post-processor beans are detected and activated, singletons are pre-instantiated, and theApplicationContext object is ready for use. As long as the context has not been closed, a refresh can be triggered multiple times, provided that the chosen ApplicationContextActually supports such “hot” refreshes. For example,XmlWebApplicationContext supports hot refreshes, but GenericApplicationContext does not.
ContextStartedEvent Published when the ApplicationContext is started by using the start() method on the ConfigurableApplicationContextInterface. Here, “started” means that allLifecycle beans receive an explicit start signal. Typically, this signal is used to restart beans after an explicit stop, but it may also be used to start components that have not been configured for autostart (for example, components that have not already started on initialization).
ContextStoppedEvent Published when the ApplicationContext is stopped by using the stop() method on the ConfigurableApplicationContextInterface. Here, “stopped” means that allLifecycle beans receive an explicit stop signal. A stopped context may be restarted through a start() call.
ContextClosedEvent Published when the ApplicationContext is being closed by using the close() method on the ConfigurableApplicationContext interface or via a JVM shutdown hook. Here, “closed” means that all singleton beans will be destroyed. Once the context is closed, it reaches its end of life and cannot be refreshed or restarted.
RequestHandledEvent A web-specific event telling all beans that an HTTP request has been serviced. This event is published after the request This event is only applicable to Web applications that use Spring’sDispatcherServlet.
ServletRequestHandledEvent A subclass of RequestHandledEvent that adds Servlet-specific context information.

Spring application context start event —ontextRefreshedEvent

This event is in AbstractApplicationContext# finishRefresh method, to perform here when the spring container initialization, instantiation (singleton) has been completed, specific code is as follows:

	protected void finishRefresh(a) {...// Publish the final event.
		publishEvent(new ContextRefreshedEvent(this));

		// Participate in LiveBeansView MBean, if active.
		LiveBeansView.registerApplicationContext(this);
	}
Copy the code

If you have an application system that needs to do something immediately after the container has been initialized (and has dependencies on the application bean), you can listen for this event and never have a problem with the dependent bean not being initialized.