How does Spring initialize under the hood ? — Part 3
If you have not read Part 1, Part 2, please take a look at it before read this article. Because they are related to some events which are the solid based for the process in Part 3. In this part, i will discuss about ContextLoaderListener
.
I appreciate every comments which build this topic up. It would be my honor when this topic brings to you some valuable knowledges. And if you observe something interesting about Spring, just inbox or comment below, people are getting smarter by learning, sharing and communicating. It is always the best to learn from each other.
To keep every thing as simple as possible and also keep you out of distraction, i have removed some lines of codes as well as methods. However, it will not affect to our simple demo.
My Contact
- LinkedIn: Phan Hoang Minh Luan
- Facebook: Phan Hoang Minh Luan
- Email: phanhoangminhluan@gmail.com
Warm up
AbstractAnnotationConfigWebApplicationContext
Swing back to part 1. We have familiared to class AbstractAnnotationConfigWebApplicationContext
. Having a look at its parents is very important. The red one is representated for interface
and the black is class
(or abstract class
)
AbstractContextLoaderInitializer
In registerContextLoaderListener(ServletContext)
, a ContextLoaderListener
is instantiated with an argument that is WebApplicationContext
(actually, it is AbstractAnnotationConfigWebApplicationContext
), this is the reason why i have mentioned its hierarchy above.
Main Discussion
ContextLoaderListener
- contextInitialized(ServletContextEvent):
ContextLoaderListener
implementServletContextListener
which take the responsibility for receiving notification whenServletContext
initialize or destroy. WhenServletContext
will be initialized when first request from client comes to our application (first request happened immediately after the process in Part 1). You can see from the snippet above,initWebApplicationContext(ServletContext)
will be invoked - initWebApplicationContext(ServletContext): this method is to cast our application context from
AnnotationConfigWebApplicationContext
toConfigurableWebApplicationContext
because this interface has some setters such asServletContext
,ServletConfig
,nameSpace
,themeSource
. If you want to config something, thesesetters
must be call beforerefresh()
(this method is our main disscussion today) get call. Then,configureAndRefreshWebApplicationContext()
will be called. - configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext, ServletContext): in this method,
ServletContext
andID
of this application context will be set beforereresh()
, all the property source (.properties files) will be load eagerly to ensure servlet property sources are in place for use in any post-processing or initialization that occurs below priorrefresh()
. When everything has been done, it's gonnarefresh()
. We will dive into this method below.
AbstractApplicationContext.refresh()
There are 3 phases in this method: pre-initialize (line 14–23), initialize (line 26–44) and post-initialize (line 47–51)
- prepareReresh(): this method is to set startup date, initialize file .properties (again) and validate it.
- obtainFreshBeanFactory(): this method is to create
BeanFactory
(to manage Beans) and load Beans (AnnotatedClass) was registered ingetRootConfigClasses()
(check Part 1 to know about this method).
- prepareBeanFactory(ConfigurableListableBeanFactory): this method is to add
BeanPostProcessor
, register Singleton Bean and configureClassLoader
.
- postProcessBeanFactory(ConfigurableListableBeanFactory): this method is to register web-specific scopes: request, session, global session, application, to register web-specific environment bean such as “servletContext”, “servletConfig”, “contextParameters” (take from
servletContext.getInitParameter(String)
,servletConfig.getInitParameter(String)
), “contextAttributes” (take fromservletContext.getAttribute(String)
)
- invokeBeanFactoryPostProcessor(ConfigurableListableBeanFactory): to invoke
BeanFactoryPostProcessor
(if any). Normally,List<BeanFactoryPostProcessor>
will empty, however, developer can useaddBeanFactoryPostProcessor(BeanFactoryPostProcessor)
to add. BeanFactoryPostProcessor provide a facility which allow modifying the BeanFactory after its standard initialization. At this time, all bean definitions will have loaded (you can find it inbeanFactory.beanDefinitionNames
), but no bean have been instantiate yet.
- registerBeanPostProcessors(ConfigurableListableBeanFactory): like
BeanFactoryPostProcessor
,interface BeanPostProcessor
facilitates for modifyingBean
before it initializes or after it destroys. There are many ways to gain access to lifecycle of a bean such as using@PostConstruct
,@PreDestroy
or justinit()
,destroy()
to be more consistent.
There are 5 BeanPostProcessors (by default) that are registered in this methods:
- AutowiredAnnotationBeanPostProcessor: for detecting @Autowire
field and also provide “context:annotation-config” and “context:component-scan”
- RequiredAnnotationBeanPostProcessor: for using @Required
annotation which is decorated on setter method.
- CommonAnnotationBeanPostProcessor: supports common Java annotations out of the box, it also support @PostConstruct
and @PreDestroy
to gain access to bean lifecycle.
- PersistenceAnnotationBeanPostProcessor: that processes PersistenceUnit
and PersistenceContext
annotations, for injection of the corresponding JPA resources EntityManagerFactory
and EntityManager
- InfrastructureAdvisorAutoProxyCreator: for Aspect Oriented Programming
- initMessageSource():
MessageSource
is a strategy interface for resolving message such as translating from a specifice language to a specific language. There are 2 classes implement interface MessageSource.
- initApplicationEventMulticaster(): interface to be implemented by objects that can manage a number of ApplicationListener object and published event to them.
- registerListeners(): add bean that implement ApplicationListener
- finishBeanFactoryInitialization(ConfigurableListableBeanFactory):instantiate all Singleton bean in your WebApplicationContext.
- finishRefresh(): clear resource cache, apply a lifecycle processor into this context. Publish event
ContextRefreshEvent
. This is an event that will be invoked when application context get init or refreshed.Actually, it just settimestamp
and asource
object (AnnotationConfigWebApplicationContext
)
LiveBeanView: just a feature which support developer to view beans in IDE, it’s not affect to WebApplicationContext.
- resetCommonCaches(): to clear all cache
Sum Up
There is pseudocode about what was happened throught out this demo. Just for keeping you on track.