Begini Ternyata, Daur Hidup Bean di Dalam Spring Container
Memahami daur hidup bean pada Spring dan mengaplikasikannya di dalam program
Sebagaimana yang pernah dibahas dalam Seri Tutorial Spring Framework Dasar. Bahwa Spring Container menampung object –object yang disebut sebagai bean. Di dalam aplikasi java tradisional, daur hidup object – object pada aplikasi java sangat sederhana. Keyword new
digunakan untuk membuat instance object baru dan object siap untuk digunakan. Ketika object tidak lagi digunakan, garbage collector akan otomatis membersihkannya.
Baca Juga :
Berbeda dengan object yang dikelola di dalam Spring Container. Bean memiliki daur hidupnya sendiri, sehingga programmer yang ingin membangun aplikasi menggunakan framework Spring dipandang perlu untuk memahami bagaimana daur hidup bean.
Terkadang dalam bebeberapa kasus, programmer perlu melakukan manipulasi bean yang dibuat oleh Spring. Bahkan terkadang subject pembahasan ini, sering tema interview kala sebuah perusahaan ingin mengukur pengetahuan seorang programmer apakah cukup memahami dasar dari Spring Framework ataukah hanya seorang code monkey saja.
- Diagram Daur Hidup
Berikut adalah daur hidup dari bean di dalam spring container yang dapat diilustrasikan dalam bagan berikut
Saat proses inisialisasi dan sebelum bean dapat digunakan, ia akan memulai beberapa fase sebagai berikut. Programmer dapat mengimplementasikan beberapa interface yang akan dipanggil oleh BeanFactory
sebelum bean dapat digunakan
- Spring menginisiasi bean
- Spring menginjeksi (inject) value dan reference dari bean ke dalam properti bean (populate properties)
- Jika bean tersebut meng-implement
BeanNameAware
, Spring akan memasukanid
dari bean ke methodsetBeanName()
- Jika bean tersebut meng-implement
BeanFactoryAware
, Spring akan memanggil methodsetBeanFactory()
- Jika bean tersebut meng-implement
ApplicationContextAware
Spring akan memanggil methodsetApplicationContext()
- Sebelum dinisialisasi, Spring akan memanggil method callback
postProcessBeforeInitialization()
dari interfaceBeanPostProcessor
- Jika bean tersebut meng-implement interface
InitializingBean
, Spring akan memanggil methodafterPropertiesSet()
- Spring akan memanggil custom method yang didefinisikan pada konfigurasi di tag
init-method
atau anotasi@PostConstruct
- Setelah selesei inisialisasi, interface, Spring akan memanggil method callback
postProcess-AfterInitialization()
dari interfaceBeanPostProcessor
Sedangkan ketika proses pre-dekonstruksi, fasenya akan jauh lebih sederhana, dimana bean akan melewati tahapan sebagai berikut
- Jika bean meng-implement interface
DisposableBean
, Spring akan memanggil methoddestroy()
- Berikutnya Spring akan memanggil method custom yang telah didefinisikan pada tag
destroy-method
atau anotasi@PreDestroy
- Hands On
Misalnya sebuah class Employee yang mengimplementasikan interface sebagai berikut
BeanNameAware
,BeanFactoryAware
,ApplicationContextAware
,InitializingBean
,DisposableBean
public class Employee implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean { private String id; private String fullName; private String address; @Override public void setBeanName(String name) { System.out.println("1. bean name aware called"); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("2. bean factory aware called"); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("3. ApplicationContextAware - ApplicationContext called"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("5. InitializingBean - afterPropertiesSet called"); } public void customInit() { System.out.println("6. custom-init"); } public void customDestroy() { System.out.println("10. custom-destroy"); } @Override public void destroy() throws Exception { System.out.println("9. destroy"); } // getter setter diabaikan }
Sedangkan interface BeanPostProcessor
bersifat global, artinya, digunakan oleh semua bean, sehingga harus dipisah menjadi class sendiri sebagai berikut
package com.subrutin.lifecycle; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class CustomBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("4 Called postProcessBeforeInitialization() for :" + beanName); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("7 Called postProcessAfterInitialization() for :" + beanName); return bean; } }
Untuk konfigurasinya, ada pada applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context-4.3.xsd"> <bean id="customBeanPostProcessor" class="com.subrutin.lifecycle.CustomBeanPostProcessor"> </bean> <bean id="employee" class="com.subrutin.lifecycle.Employee" init-method="customInit" destroy-method="customDestroy"> <property name="id" value="2"></property> <property name="fullName" value="Silvie"></property> <property name="address" value="Jalan Merdeka"></property> </bean> </beans>
Perhatikan pada init-method
dan destroy-method
pada bean employee
telah didefiniskan dengan method customInit
dan method customDestroy
Sekarang tinggal panggil konfigurasi applicationContext.xml
menggunakan ClassPathXmlApplicationContext
pada App
package com.subrutin.lifecycle; import org.springframework.context.ApplicationContext; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Hello world! * */ public class App { public static void main( String[] args ) { AbstractApplicationContext appCtx = new ClassPathXmlApplicationContext("applicationContext.xml"); Employee employeeBean = (Employee) appCtx.getBean("employee"); System.out.println("8 Object employee telah siap digunakan :"+ employeeBean.toString()); appCtx.registerShutdownHook(); } }
Pada baris 19, appCtx.registerShutdownHook()
ditambahkan untuk mentrigger container melakukan proses destroy semua bean yang ada di dalam container.
Jalankan program, jika berhasil, pada konsol akan muncul tampilan sebagai berikut