Directory
1. Environment
Two, examples
2.1. Description
3. Execution process
3.1 Source code analysis
One, environment
- jdk: 1.8
- spring-boot: 2.7.1
Second, Example
@Component public class TestInit implements InitializingBean { @Override public void afterPropertiesSet() throws Exception { System.out.println("call TestInit.afterPropertiesSet method"); } }
operation result:
2.1, Description
- springboot provides the InitializingBean interface, which users can implement to customize initialization operations
- Implement the InitializingBean interface to rewrite the afterPropertiesSet method and register it in the spring container. After the instance is created, it can trigger the execution of the custom initialization operation
3. Execution process
I have been curious and want to figure out when to call the extension point afterPropertiesSet() method? How to call it?
To satisfy curiosity, start a simple springboot project to track the source code execution process as follows:
3.1 Source Code Analysis
1. Springboot project startup entry SpringApplication.run
public ConfigurableApplicationContext run(String... args) { // record start time long startTime = System. nanoTime(); DefaultBootstrapContext bootstrapContext = createBootstrapContext(); // Prepare the ApplicationContext ConfigurableApplicationContext context = null; configureHeadlessProperty(); // Get the listener from spring.factories SpringApplicationRunListeners listeners = getRunListeners(args); // publish event listeners.starting(bootstrapContext, this.mainApplicationClass); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); // Environmental parameters ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments); // Configure settings into system parameters configureIgnoreBeanInfo(environment); // output banner Banner printedBanner = printBanner(environment); // Create applicationContext IOC container context = createApplicationContext(); context.setApplicationStartup(this.applicationStartup); // Prepare the context IOC container, set a series of attribute values prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner); // Line 308, start the spring container refreshContext(context); // processing after refresh afterRefresh(context, applicationArguments); Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime); if (this. logStartupInfo) { new StartupInfoLogger(this. mainApplicationClass). logStarted(getApplicationLog(), timeTakenToStartup); } // publish event listeners.started(context, timeTakenToStartup); // Call the runner, which implements the interface of ApplicationRunner or CommandLineRunner callRunners(context, applicationArguments); } catch (Throwable ex) { handleRunFailure(context, ex, listeners); throw new IllegalStateException(ex); } try { Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime); listeners.ready(context, timeTakenToReady); } catch (Throwable ex) { handleRunFailure(context, ex, null); throw new IllegalStateException(ex); } return context; }
Here focus on adjusting refreshContext(context) to start the container
2. SpringApplication.refreshContext starts the container
protected void refresh(ConfigurableApplicationContext applicationContext) { // 734 lines applicationContext. refresh(); }
Then call AbstractApplicationContext.refresh() to start the Spring container
3. AbstractApplicationContext.refresh() starts the Spring container
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh"); // Prepare before starting the container. Startup time, status and environment, etc. prepareRefresh(); // Tell the subclass to refresh the internal bean factory ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare to use the bean factory in the context prepareBeanFactory(beanFactory); try { // Allows postprocessing of bean factories in context subclasses. postProcessBeanFactory(beanFactory); StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process"); // call the factory handler registered as a bean in the context invokeBeanFactoryPostProcessors(beanFactory); // Register the bean handler that intercepts bean creation. registerBeanPostProcessors(beanFactory); beanPostProcess. end(); // Initialize the message source for this context. initMessageSource(); // Initialize the event broadcaster initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // register event listener registerListeners(); // Line 583, instantiate all remaining (non lazy-init) singletons finishBeanFactoryInitialization(beanFactory); // Complete the boot operation finishRefresh(); } catch (BeansException ex) { ... } finally { resetCommonCaches(); contextRefresh.end(); } } }
Lists the entire process of Spring container startup. This example focuses on the InitializingBean extension point, and other content will not be explained in detail. Instantiate all remaining (non lazy-init) singletons finishBeanFactoryInitialization(beanFactory);
4. AbstractApplicationContext.finishBeanFactoryInitialization(…) initialization (non-lazy-init) singleton
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { ... // Line 918, instantiate all remaining (non lazy-init) singletons. beanFactory. preInstantiateSingletons(); }
Call the preInstantiateSingletons method of the bean factory class to instantiate the bean
5. ConfigurableListableBeanFactory.preInstantiateSingletons() instantiates beans
@Override public void preInstantiateSingletons() throws BeansException { ... // Line 955, get bean getBean(beanName); ... }
Here the bean is obtained by adjusting the parent class AbstractBeanFactory.getBean
6.AbstractBeanFactory.getBean(beanName) gets bean
public Object getBean(String name) throws BeansException { // line 208 return doGetBean(name, null, null, false); }
Then call the doGetBean(…) method of this class to get the bean
7. AbstractBeanFactory.doGetBean gets bean
protected <T> T doGetBean( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { ... // Line 332, create a bean instance if (mbd. isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { ... } }); ... } ... } return adaptBeanInstance(name, beanInstance, requiredType); }
Then tune the createBean of the subclass to create an instance
8.AbstractAutowireCapableBeanFactory.createBean(…) creates an instance
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { ... //line 542 doCreateBean(beanName, mbdToUse, args); ... }
Call this class doCreateBean
9.AbstractAutowireCapableBeanFactory.doCreateBean(…) executes creating beans
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { ... // instantiate the bean // Solve the problem of circular dependency, whether circular dependency is allowed, etc. ... // Attribute assembly, that is, automatic injection populateBean(beanName, mbd, instanceWrapper); // Line 620, application factory callbacks and initialization methods and bean post-handlers. // such as init-method, InitializingBean interface, BeanPostProcessor interface exposedObject = initializeBean(beanName, exposedObject, mbd); ... }
10. AbstractAutowireCapableBeanFactory.initializeBean processing initialization completed processing
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { ... // method callback invokeInitMethods(beanName, wrappedBean, mbd); ... }
11. Method callback processing of AbstractAutowireCapableBeanFactory.invokeInitMethods instance
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); // It is judged as the implementation class of InitializingBean, and the afterPropertiesSet method is rewritten, then the afterPropertiesSet method is called if (isInitializingBean & amp; & amp; (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("afterPropertiesSet"))) { ... ((InitializingBean) bean). afterPropertiesSet(); ... } ... }
At this point, the implementation and triggering time of the InitializingBean extension point is over.
ps: The above is a summary of reading the source code and reading a lot of literature. If there are any mistakes or deficiencies, please point them out and leave a message for exchange. I will continue to work hard to learn and share more content with dry goods.