{"id":5812,"date":"2019-08-20T22:29:28","date_gmt":"2019-08-21T02:29:28","guid":{"rendered":"http:\/\/springframework.guru\/?p=5812"},"modified":"2020-07-12T09:42:19","modified_gmt":"2020-07-12T13:42:19","slug":"spring-bean-lifecycle","status":"publish","type":"post","link":"https:\/\/springframework.guru\/spring-bean-lifecycle\/","title":{"rendered":"Spring Bean Lifecycle"},"content":{"rendered":"<p>The Spring IoC (Inversion of Control) container manages Spring beans. A &#8220;Spring bean&#8221; is just a Spring managed instantiation of a Java class.<\/p>\n<p>The Spring IoC container is responsible for instantiating, initializing, and wiring beans. The container also manages the life cycle of beans.<\/p>\n<p>Spring provides several ways through which you can tap into the bean lifecycle. For example, once a bean is instantiated, you might need to perform some initialization to get the bean into a usable state. Similarly, you might need to clean up resources before a bean is removed from the container.<\/p>\n<p>In this post, we will examine the steps of Spring bean lifecycle. This is how the Spring Framework creates and destroys Spring beans.<\/p>\n<h2>Spring Bean Lifecycle Overview<\/h2>\n<p>This Figure shows two parts of the Spring bean lifecycle:<\/p>\n<p><a href=\"http:\/\/springframework.guru\/wp-content\/uploads\/2019\/08\/lifecycle.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-5857\" src=\"http:\/\/springframework.guru\/wp-content\/uploads\/2019\/08\/lifecycle-1024x442.png\" alt=\"\" width=\"1024\" height=\"442\" srcset=\"https:\/\/springframework.guru\/wp-content\/uploads\/2019\/08\/lifecycle-1024x442.png 1024w, https:\/\/springframework.guru\/wp-content\/uploads\/2019\/08\/lifecycle-300x129.png 300w, https:\/\/springframework.guru\/wp-content\/uploads\/2019\/08\/lifecycle-768x331.png 768w, https:\/\/springframework.guru\/wp-content\/uploads\/2019\/08\/lifecycle-848x366.png 848w, https:\/\/springframework.guru\/wp-content\/uploads\/2019\/08\/lifecycle-410x177.png 410w, https:\/\/springframework.guru\/wp-content\/uploads\/2019\/08\/lifecycle.png 1303w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/p>\n<p><strong>Part 1:<\/strong> Shows the different stages a bean goes through after instantiation until it is ready for use.<br \/>\n<strong>Part 2:<\/strong> Shows what happens to a bean once the Spring IoC container shuts down.<\/p>\n<p>As you can see in Part 1 of the preceding figure, the container instantiates a bean by calling its constructor and then populates its properties.<\/p>\n<p>This is followed by several calls to the bean until the bean is in the ready state.<\/p>\n<p>Similarly, as shown in Part 2, when the container shuts down, the container calls the bean to enable it to perform any required tasks before the bean is destroyed.<\/p>\n<h2>Aware interfaces<\/h2>\n<p>Spring provides several aware interfaces. These are used to access the Spring Framework infrastructure. The aware interfaces are largely used within the framework and rarely used by Spring programmers.<\/p>\n<p>You as Spring programmers should be familiar with the following three aware interfaces.<\/p>\n<ul>\n<li><code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">BeanFactoryAware<\/code>: Provides <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">setBeanFactory()<\/code>, a callback that supplies the owning factory to the bean instance.<\/li>\n<li><code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">BeanNameAware<\/code>: The<code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">setBeanName()<\/code> callback of this interface supplies the name of the bean.<\/li>\n<li><code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ApplicationContextAware<\/code>: The<code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">setApplicationContext()<\/code> method of this interface provides the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ApplicationContext<\/code> object of this bean.<\/li>\n<\/ul>\n<p>The code to use the preceding aware interfaces is this.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.springbeanlifecycle.awareinterfaces.domain;\r\n\r\nimport org.springframework.beans.BeansException;\r\nimport org.springframework.beans.factory.BeanFactory;\r\nimport org.springframework.beans.factory.BeanFactoryAware;\r\nimport org.springframework.beans.factory.BeanNameAware;\r\nimport org.springframework.context.ApplicationContext;\r\nimport org.springframework.context.ApplicationContextAware;\r\n\r\nimport java.util.Arrays;\r\n\r\npublic class AwareBeanImpl implements ApplicationContextAware, BeanNameAware, BeanFactoryAware {\r\n@Override\r\npublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {\r\nSystem.out.println(\"setBeanFactory method of AwareBeanImpl is called\");\r\nSystem.out.println(\"setBeanFactory:: AwareBeanImpl singleton= \"\r\n+ beanFactory.isSingleton(\"awareBean\"));\r\n}\r\n\r\n@Override\r\npublic void setBeanName(String beanName) {\r\nSystem.out.println(\"setBeanName method of AwareBeanImpl is called\");\r\nSystem.out.println(\"setBeanName:: Bean Name defined in context= \"\r\n+ beanName);\r\n}\r\n\r\n@Override\r\npublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\r\nSystem.out.println(\"setApplicationContext method of AwareBeanImpl is called\");\r\nSystem.out.println(\"setApplicationContext:: Bean Definition Names= \"\r\n+ Arrays.toString(applicationContext.getBeanDefinitionNames()));\r\n}\r\n}\r\n<\/pre>\n<p>The preceding bean implements the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ApplicationContextAware<\/code>, <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">BeanNameAware<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">BeanFactoryAware<\/code> interfaces. In the preceding code:<\/p>\n<p><strong>Line 13 &#8211; Line 18<\/strong>: The code overrides the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">setBeanFactory()<\/code> method of the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">BeanFactoryAware<\/code> interface. During runtime, Spring passes the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">BeanFactory<\/code> object that created the bean. The code uses the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">BeanFactory<\/code> object to print whether or not this bean is a singleton.<br \/>\n<strong>Line 20 &#8211; Line 25<\/strong> overrides the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">setBeanName()<\/code> method of the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">BeanNameAware<\/code> interface. During runtime, Spring passes the name of the bean as a String that the code prints out. The code uses the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">beanName<\/code> to print the bean name defined in context.<br \/>\nIn <strong>Line 27 &#8211; Line 32<\/strong>, the code overrides the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">setApplicationContext()<\/code> method of the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ApplicationContextAware<\/code> interface. During runtime, Spring passes the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ApplicationContext<\/code> object that created the bean. The code uses the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ApplicationContext<\/code> object to print the bean definition names.<\/p>\n<p>Next, we will write the bean configuration to define the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">AwareBeanImpl<\/code>.<br \/>\nThe code of the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">beans.xml<\/code> is this.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\r\n\r\n&lt;beans xmlns=\"http:\/\/www.springframework.org\/schema\/beans\"\r\n      xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\r\n      xsi:schemaLocation=\"http:\/\/www.springframework.org\/schema\/beans\r\n    http:\/\/www.springframework.org\/schema\/beans\/spring-beans-3.0.xsd\"&gt;\r\n\r\n   &lt;!--    awareinterfaces--&gt;\r\n   &lt;bean id=\"awareBean\" class=\"guru.springframework.springbeanlifecycle.awareinterfaces.domain.AwareBeanImpl\"&gt;\r\n   &lt;\/bean&gt;\r\n\r\n&lt;\/beans&gt;\r\n<\/pre>\n<p>Finally, let us write the main class which will load the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">beans.xml<\/code> and test the aware interface methods.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.springbeanlifecycle;\r\n\r\nimport guru.springframework.springbeanlifecycle.awareinterfaces.domain.AwareBeanImpl;\r\nimport org.springframework.boot.SpringApplication;\r\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\r\nimport org.springframework.context.ApplicationContext;\r\nimport org.springframework.context.support.AbstractApplicationContext;\r\nimport org.springframework.context.support.ClassPathXmlApplicationContext;\r\n\r\n@SpringBootApplication\r\npublic class SpringBeanLifecycleApplication {\r\n\r\npublic static void main(String[] args) {\r\n\r\nSpringApplication.run(SpringBeanLifecycleApplication.class, args);\r\n\r\n\/\/ -------awareinterfaces---------\r\nApplicationContext context1 =\r\nnew ClassPathXmlApplicationContext(\"beans.xml\");\r\nAwareBeanImpl awareBeanImpl = (AwareBeanImpl) context1.getBean(\"awareBean\");\r\n((AbstractApplicationContext) context1).registerShutdownHook();\r\n\r\n}\r\n\r\n}\r\n<\/pre>\n<p>The output on running the main class is this:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\"> \r\nsetBeanName method of AwareBeanImpl is called\r\nsetBeanName:: Bean Name defined in context= awareBean\r\nsetBeanFactory method of AwareBeanImpl is called\r\nsetBeanFactory:: AwareBeanImpl singleton= true\r\nsetApplicationContext method of AwareBeanImpl is called\r\nsetApplicationContext:: Bean Definition Names= [awareBean]\r\n<\/pre>\n<h2>Bean Post Processor<\/h2>\n<p>Spring provides the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">BeanPostProcessor<\/code> interface that gives you the means to tap into the Spring context life cycle and interact with beans as they are processed.<\/p>\n<p>The <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">BeanPostProcessor<\/code> interface contains two methods.<\/p>\n<ul>\n<li><code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">postProcessBeforeInitialization<\/code>: Spring calls this method after calling the methods of the aware interfaces and before any bean initialization callbacks, such as InitializingBean&#8217;s <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">afterPropertiesSet<\/code> or a custom init-method.<\/li>\n<li><code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">postProcessAfterInitialization<\/code>: Spring calls this method after any bean initialization callbacks.<\/li>\n<\/ul>\n<p>Let us start by creating a bean, named <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">BookBean<\/code>.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.springbeanlifecycle.beanpostprocessor.domain;\r\n\r\npublic class BookBean {\r\nprivate String bookName;\r\n\r\npublic BookBean() {\r\nSystem.out.println(\"Constructor of BookBean called !! \");\r\n\r\n}\r\n\r\npublic BookBean(String bookName) {\r\nthis.bookName = bookName;\r\n}\r\n\r\npublic String getBookName() {\r\nreturn bookName;\r\n}\r\n\r\npublic void setBookName(String bookName) {\r\nthis.bookName = bookName;\r\n}\r\n\r\n@Override\r\npublic String toString() {\r\nreturn \"BookBean{\" +\r\n\"bookName='\" + bookName + '\\'' +\r\n'}';\r\n}\r\n}\r\n<\/pre>\n<p>Next, we will create the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">BookBeanPostProcessor<\/code>.<\/p>\n<p>The code for <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">BookBeanPostProcessor<\/code> is this.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.springbeanlifecycle.beanpostprocessor.domain;\r\n\r\nimport guru.springframework.springbeanlifecycle.beanpostprocessor.domain.BookBean;\r\nimport org.springframework.beans.BeansException;\r\nimport org.springframework.beans.factory.config.BeanPostProcessor;\r\n\r\npublic class BookBeanPostProcessor implements BeanPostProcessor {\r\n\r\n@Override\r\npublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {\r\nSystem.out.println(\"Post Process Before Initialization method is called : Bean Name \" + beanName);\r\nreturn bean; }\r\n\r\n@Override\r\npublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {\r\nSystem.out.println(\"Post Process After Initialization method is called : Bean Name \" + beanName);\r\n\r\nreturn bean;\r\n}\r\n}\r\n<\/pre>\n<p>The preceding code implements the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">BeanPostProcessor<\/code> interface and overrides the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">postProcessBeforeInitialization()<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">postProcessAfterInitialization()<\/code> methods.<\/p>\n<p>Spring calls the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">postProcessBeforeInitialization()<\/code> method after calling the methods of the aware interfaces.<\/p>\n<p>Spring calls the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">postProcessAfterInitialization()<\/code> method after any bean initialization callbacks, such as InitializingBean&#8217;s <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">afterPropertiesSet<\/code> or a custom init-method. We will discuss both going ahead.<\/p>\n<p>At runtime, Spring will inject the new bean instance and the name of the bean to both the methods.<\/p>\n<p>Next, we will define <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">BookBean<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">BookBeanProcessor<\/code> as beans in the XML configuration.<\/p>\n<p>The configuration code is this.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\r\n\r\n&lt;beans xmlns=\"http:\/\/www.springframework.org\/schema\/beans\"\r\n      xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\r\n      xsi:schemaLocation=\"http:\/\/www.springframework.org\/schema\/beans\r\n    http:\/\/www.springframework.org\/schema\/beans\/spring-beans-3.0.xsd\"&gt;\r\n\r\n   &lt;bean id=\"bookBeanPost\" class=\"guru.springframework.springbeanlifecycle.beanpostprocessor.domain.BookBean\"&gt;\r\n       &lt;property name=\"bookName\" value=\"Gone with the Wind\"&gt;&lt;\/property&gt;\r\n   &lt;\/bean&gt;\r\n   &lt;bean id=\"bookBeanPostProcessor\"\r\n         class=\"guru.springframework.springbeanlifecycle.beanpostprocessor.domain.BookBeanPostProcessor\"\/&gt;\r\n&lt;\/beans&gt;\r\n<\/pre>\n<p>The main class to test our <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">BeanPostProcessor<\/code> is this.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.springbeanlifecycle;\r\n\r\nimport guru.springframework.springbeanlifecycle.beanpostprocessor.domain.BookBean;\r\nimport org.springframework.boot.SpringApplication;\r\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\r\nimport org.springframework.context.ApplicationContext;\r\nimport org.springframework.context.support.AbstractApplicationContext;\r\nimport org.springframework.context.support.ClassPathXmlApplicationContext;\r\n\r\n@SpringBootApplication\r\npublic class SpringBeanLifecycleApplication {\r\n\r\npublic static void main(String[] args) {\r\n\r\nSpringApplication.run(SpringBeanLifecycleApplication.class, args);\r\n\/\/ -------beanpostprocessor------\r\nApplicationContext context4 =\r\nnew ClassPathXmlApplicationContext(\"beans.xml\");\r\nBookBean bookBean = (BookBean) context4.getBean(\"bookBeanPost\");\r\n((AbstractApplicationContext) context4).registerShutdownHook();\r\n}\r\n}\r\n<\/pre>\n<p>The output on running the main class is this.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\"> \r\nConstructor of BookBean called !!\r\nPost Process After Initialization method is called: Bean Name bookBeanPost\r\nPost Process Before Initialization method is called: Bean Name bookBeanPost\r\n<\/pre>\n<h2>InitializingBean and DisposableBean Callback Interfaces<\/h2>\n<p>Spring provides the following two callback interfaces:<\/p>\n<ul>\n<li><code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">InitializingBean<\/code>: Declares the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">afterPropertiesSet()<\/code> method which can be used to write the initialization logic. The container calls the method after properties are set.<\/li>\n<li><code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">DisposableBean<\/code>: Declares the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">destroy()<\/code> method which can be used to write any cleanup code. The container calls this method during bean destruction in shutdown.<\/li>\n<\/ul>\n<p>Let&#8217;s write a bean that implements the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">InitalizingBean<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">DisposableBean<\/code> interfaces.<\/p>\n<p>The code of the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">Book<\/code> bean is this.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.springbeanlifecycle.callbackinterfaces.domain;\r\nimport org.springframework.beans.factory.DisposableBean;\r\nimport org.springframework.beans.factory.InitializingBean;\r\npublic class Book implements InitializingBean, DisposableBean {\r\nprivate String bookName;\r\npublic Book() {\r\nSystem.out.println(\"Constructor of Book bean is called !! \");\r\n}\r\n\r\n@Override\r\npublic void destroy() throws Exception {\r\nSystem.out.println(\"Destroy method of Book bean called !! \");\r\n}\r\n@Override\r\npublic void afterPropertiesSet() throws Exception {\r\nSystem.out.println(\"afterPropertiesSet method of Book bean is called !! \");\r\n}\r\npublic Book(String bookName) {\r\nthis.bookName = bookName;\r\n}\r\npublic String getBookName() {\r\nreturn bookName;\r\n}\r\npublic void setBookName(String bookName) {\r\nthis.bookName = bookName;\r\n}\r\n@Override\r\npublic String toString() {\r\nreturn \"Book{\" +\r\n\"bookName='\" + bookName + '\\'' +\r\n'}';\r\n}\r\n}\r\n<\/pre>\n<p>The preceding Book bean implements the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">InitializingBean<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">DisposableBean<\/code> interfaces and overrides their <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">afterPropertiesSet()<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">destroy()<\/code> method.<\/p>\n<p>Next, we will write the bean configuration to define the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">Book<\/code> bean.<\/p>\n<p>The code of the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">beans.xml<\/code> file is this.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\r\n\r\n&lt;beans xmlns=\"http:\/\/www.springframework.org\/schema\/beans\"\r\n      xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\r\n      xsi:schemaLocation=\"http:\/\/www.springframework.org\/schema\/beans\r\n    http:\/\/www.springframework.org\/schema\/beans\/spring-beans-3.0.xsd\"&gt;\r\n\r\n   &lt;!--     callbackinterfaces--&gt;\r\n   &lt;bean id=\"bookBean\" class=\"guru.springframework.springbeanlifecycle.callbackinterfaces.domain.Book\"&gt;\r\n       &lt;property name=\"bookName\" value=\"Believe in Yourself\"\/&gt;\r\n   &lt;\/bean&gt;\r\n&lt;\/beans&gt;\r\n<\/pre>\n<p>The main class is this.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.springbeanlifecycle;\r\n\r\nimport guru.springframework.springbeanlifecycle.callbackinterfaces.domain.Book;\r\nimport org.springframework.boot.SpringApplication;\r\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\r\nimport org.springframework.context.ApplicationContext;\r\nimport org.springframework.context.support.AbstractApplicationContext;\r\nimport org.springframework.context.support.ClassPathXmlApplicationContext;\r\n\r\n@SpringBootApplication\r\npublic class SpringBeanLifecycleApplication {\r\n\r\npublic static void main(String[] args) {\r\n\r\nSpringApplication.run(SpringBeanLifecycleApplication.class, args);\r\n\r\n\/\/ -------callbackinterfaces-------\r\nApplicationContext context =\r\nnew ClassPathXmlApplicationContext(\"beans.xml\");\r\nBook book = (Book) context.getBean(\"bookBean\");\r\nSystem.out.println(book.getBookName());\r\n((AbstractApplicationContext) context).registerShutdownHook();\r\n\r\n}\r\n\r\n}\r\n<\/pre>\n<p>The preceding code retrieves the Book bean from the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ApplicationContext<\/code> and prints out the value of the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">bookName<\/code> property.<\/p>\n<p>The output on running the main class is this.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\"> \r\nConstructor of Book bean is called !!\r\nafterPropertiesSet method of Book bean is called !!\r\nBelieve in Yourself\r\ndestroy method of Book bean is called !!\r\n<\/pre>\n<p>As you can note in the output the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">afterPropertiesSet()<\/code> method got called first.<\/p>\n<h2>Custom Init and Destroy Method<\/h2>\n<p>While declaring bean in XML configuration, you can specify the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">init-method<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">destroy-method<\/code> attributes in the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\"><\/code> tag. Both the attributes specify custom methods in the bean class.<\/p>\n<p>The method declared in the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">init-method<\/code> attribute is called after Spring initializes bean properties through setter or constructor arguments. You can use this method to validate the injected properties or perform any other tasks.<\/p>\n<p>Spring calls the method declared in the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">destroy-method<\/code> attribute just before the bean is destroyed.<\/p>\n<p>Let\u2019s use the custom init and destroy methods in a bean, named <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">BookCustomBean<\/code>.<\/p>\n<p>The code for <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">BookCustomBean<\/code>; is this.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.springbeanlifecycle.custominitanddestroy.domain;\r\n\r\npublic class BookCustomBean {\r\nprivate String bookName;\r\n\r\npublic BookCustomBean() {\r\nSystem.out.println(\"Constructor of BookCustomBean bean is called !! \");\r\n}\r\n\r\npublic void customDestroy() throws Exception {\r\n\r\nSystem.out.println(\"Custom destroy method of BookCustomBean called !! \");\r\n}\r\n\r\npublic void customInit() throws Exception {\r\nSystem.out.println(\"Custom Init method of BookCustomBean called !! \");\r\n}\r\n\r\npublic BookCustomBean(String bookName) {\r\nthis.bookName = bookName;\r\n}\r\n\r\npublic String getBookName() {\r\nreturn bookName;\r\n}\r\n\r\npublic void setBookName(String bookName) {\r\nthis.bookName = bookName;\r\n}\r\n\r\n@Override\r\npublic String toString() {\r\nreturn \"Book{\" +\r\n\"bookName='\" + bookName + '\\'' +\r\n'}';\r\n}\r\n\r\n}\r\n<\/pre>\n<p>In the preceding code, <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">customInit<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">customDestroy<\/code> are regular methods that prints output messages.<\/p>\n<p>Next, we\u2019ll write the bean configuration, <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">beans.xml<\/code>.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\r\n\r\n&lt;beans xmlns=\"http:\/\/www.springframework.org\/schema\/beans\"\r\n      xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\r\n      xsi:schemaLocation=\"http:\/\/www.springframework.org\/schema\/beans\r\n    http:\/\/www.springframework.org\/schema\/beans\/spring-beans-3.0.xsd\"&gt;\r\n\r\n   &lt;!--    Declare custom init and destroy methods--&gt;\r\n   &lt;bean id=\"customLifeCycleBookBean\"\r\n         class=\"guru.springframework.springbeanlifecycle.custominitanddestroy.domain.BookCustomBean\"\r\n         init-method=\"customInit\"\r\n         destroy-method=\"customDestroy\"&gt;\r\n       &lt;property name=\"bookName\" value=\"Life and Laughing\"&gt;&lt;\/property&gt;\r\n   &lt;\/bean&gt;\r\n\r\n&lt;\/beans&gt;<\/pre>\n<p>In the preceding code, Line 11 &#8211; Line 12 uses the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">init-method<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">destroy-method<\/code> attributes with the values, <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">customInit<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">customDestroy<\/code>.<\/p>\n<p>The code of the main class is this.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.springbeanlifecycle;\r\n\r\nimport guru.springframework.springbeanlifecycle.custominitanddestroy.domain.BookCustomBean;\r\nimport org.springframework.boot.SpringApplication;\r\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\r\nimport org.springframework.context.ApplicationContext;\r\nimport org.springframework.context.support.AbstractApplicationContext;\r\nimport org.springframework.context.support.ClassPathXmlApplicationContext;\r\n\r\n@SpringBootApplication\r\npublic class SpringBeanLifecycleApplication {\r\n\r\npublic static void main(String[] args) {\r\n\r\nSpringApplication.run(SpringBeanLifecycleApplication.class, args);\r\n\/\/ -------custominitanddestroy------\r\nApplicationContext context3 =\r\nnew ClassPathXmlApplicationContext(\"beans.xml\");\r\n\r\nBookCustomBean bookCustomBean = (BookCustomBean) context3.getBean(\"customLifeCycleBookBean\");\r\n((AbstractApplicationContext) context3).registerShutdownHook();\r\n}\r\n}\r\n<\/pre>\n<p>The preceding code loads the XML configuration and tests the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">init-method<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">destroy-method<\/code>.<\/p>\n<p>The output on running the preceding code is this.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\"> \r\nConstructor of BookCustomBean bean is called !!\r\nCustom Init method of BookCustomBean called !!\r\nCustom destroy method of BookCustomBean called !!\r\n<\/pre>\n<h2>Summary<\/h2>\n<p>All Spring beans go through a specific life cycle, and as we have seen, there&#8217;s<br \/>\nactually, a lot goes on under the hood. Most of this is handled by the framework and as a Spring developer, you will seldom require to get into it that often. However, as you get into more and more complex applications with the Spring framework, at times you have to be aware of what goes on during a bean lifecycle.<\/p>\n<p>I personally don&#8217;t prefer using the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">InitializingBean<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">DisposableBean<\/code> interfaces. Primarily because it tight couples your code to Spring. A better approach is specifying the init-method and destroy-method attributes in your bean configuration file.<br \/>\nThe source code for this post can be found here on <a href=\"https:\/\/github.com\/spring-framework-guru\/sfg-blog-posts\/tree\/master\/springbeanlifecycle\" target=\"_blank\" rel=\"noopener noreferrer\">GitHub<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Spring IoC (Inversion of Control) container manages Spring beans. A &#8220;Spring bean&#8221; is just a Spring managed instantiation of a Java class. The Spring IoC container is responsible for instantiating, initializing, and wiring beans. The container also manages the life cycle of beans. Spring provides several ways through which you can tap into the [&hellip;]<a href=\"https:\/\/springframework.guru\/spring-bean-lifecycle\/\" class=\"df-link-excerpt\">Continue reading<\/a><\/p>\n","protected":false},"author":111,"featured_media":4588,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"","_lmt_disable":"","_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[21,6,182,1],"tags":[245,246],"class_list":["post-5812","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-spring","category-spring-core","category-spring-framework-5","category-uncategorized","tag-bean-lifecycle","tag-spring-bean-lifecycle"],"jetpack_publicize_connections":[],"aioseo_notices":[],"modified_by":"Simanta","jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/springframework.guru\/wp-content\/uploads\/2015\/03\/Banner560x292_05aweb.jpg","jetpack_shortlink":"https:\/\/wp.me\/p5BZrZ-1vK","_links":{"self":[{"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/posts\/5812"}],"collection":[{"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/users\/111"}],"replies":[{"embeddable":true,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/comments?post=5812"}],"version-history":[{"count":10,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/posts\/5812\/revisions"}],"predecessor-version":[{"id":6348,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/posts\/5812\/revisions\/6348"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/media\/4588"}],"wp:attachment":[{"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/media?parent=5812"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/categories?post=5812"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/tags?post=5812"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}