一文了解Spring--Bean生命週期

Bean獲取和實例化

ApplicationContext與BeanFactory關係
在這裏插入圖片描述
ApplicationContext它是擴展BeanFactory接口。
BeanFactory它採取延遲加載的方案,只有真正在getBean時纔會實例化Bean

在開發中我們一般使用的是ApplicationContext,真正使用的是其實現類,
FileSystemXmlAppliCationContext 根據文件路徑獲取
ClassPathXmlApplicationContext 根據類路徑獲取

AppliCationContext它會在配置文件加載時,就會初始化Bean,並且ApplicationContext它提供不同的應用層的Context實現。例如在web開發中可以使用WebApplicationContext.

IOC獲取Bean實例化對象

  • 在applicationContext.xml文件中配置bean
<bean id="userService" class="com.test.userServiceImpl"/>
  • 創建一個AppliCationContext對象
    ApplicationContext它是BeanFactory的一個子接口,我們在使用時使用的是AppliCationContext的實現類ClassPathXmlApplicationContext,獲取Spring配置上下文對象
//使用Spring的IOC容器;IOC本質是XML配置文件+反射+BeanFactory來實現
//Soring提供一個BeanFactory工廠統一管理Bean,使用其子接口ApplicationContext
//ClassPathXmlApplicationContext:在類路徑下根據參數文件名查找ApplicationContext.xml對象
ApplicationContext application=new ClassPathXmlApplicationContext("ApplicationContext");
UserService userService=(UserService)application.getBean("userService");

Bean的生命週期流程

在這裏插入圖片描述

  1. instantiate bean 構造方法實例化Bean對象
  2. populate properties 封裝屬性,di依賴注入
  3. 如果Bean實現BeanNameAware,執行setBeanName,也就是bean的id值
  4. 如果Bean實現BeanFactoryAwar或ApplicationContextAwar,需要設置工廠setBeanFactory或上下文對象setApplicationContext
  5. 如果存在類實現BeanPostProcessor(後處理Bean),執行postProcessBeforeInitialization,可以在初始化之前執行一些方法
  6. 如果Bean實現InitializingBean(初始化)接口,執行afterPropertiesSet方法(相當於自定義init-method),執行屬性設置之後的操作
  7. 調用自定義的< bean init-method=" " >初始化方法
  8. 如果存在類實現BeanPostProcessor(處理Bean),執行postProcessAfterInitialization,執行初始化之後的操作
  9. 執行業務處理(Bean可用)
  10. 如果Bean實現DisposableBean執行destroy
  11. 調用自定義的< bean destroy-method=’’ >銷燬方法

對於bean的生命週期方法:
第三步與第四步是讓Bean瞭解spring容器。

第五步與第八步 可以針對指定的Bean進行功能增強(在初始化前後執行),這時一般會使用動態代理.

第六步與第十步:通過實現指定的接口來完成init與destroy操作
但是在開發中一般不使用第6步與第10步,原因是我們可以使用第7步與第11步來完成。
第7步與第11步的初始化與銷燬操作它無耦合,推薦使用的。但是必須在配置文件中指定初始化與銷燬的方法

代碼實例:

在xml配置文件中配置相關的bean

<!-- 自定義bean -->
	<bean id="testBean" name="bean1" class="com.dubbox.bean.TestBean" init-method="myInit" destroy-method="myDestroy">
	 <property name="beanStr" value="張三的歌"/>
	 <property name="beanInt" value="123"></property>
	</bean>
	<!-- 實現BeanPostProcessor接口的bean,spring ioc容器擴展 -->
	<bean id="postProcessor" class="com.dubbox.bean.PostProcessor"></bean>
	
	<!-- spring 註解掃描 -->
	<context:component-scan base-package="com.dubbox"></context:component-scan>

Bean分別實現 BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean


/**
 * 
 * @author 張江豐 
 * BeanNameAware: 
 *      實現setBeanName方法 設置Bean的id 
 * ApplicationContextAware/BeanFactoryBean:
 *         實現setApplicationContext/setBeanFactory方法 設置ApplicationComtext上下文對象/BeanFactory
 * BeanPostProcessor: 
 *         實現 postProcessBeforeInitialization 和   postProcessAfterInitialization 分別執行初始化執行之前和之後的方法
 * InitializingBean:
 *         實現afterPropertiesSet方法,進行Bean初始化,在屬性封裝之後執行
 * DisposableBean: 
 *         實現destroy方法 銷燬執行
 *
 */
@Scope(value = "singleton")
public class TestBean implements BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean {

	private String beanStr;

	private Integer beanInt;

	public String getName() {
		return "zhangsan";
	}

	public String getBeanStr() {
		return beanStr;
	}

	public void setBeanStr(String beanStr) {
		this.beanStr = beanStr;
	}

	public Integer getBeanInt() {
		return beanInt;
	}

	public void setBeanInt(Integer beanInt) {
		this.beanInt = beanInt;
	}

	@Override
	public void setBeanName(String name) {
		// TODO Auto-generated method stub
		System.out.println("調用setBeanName方法:" + name);

	}

	private ApplicationContext applicationContext;

	@Override
	public void setApplicationContext(ApplicationContext arg0) throws BeansException {
		// TODO Auto-generated method stub
		this.applicationContext = arg0;
		// TestBean bean = (TestBean) applicationContext.getBean("testBean");
		System.out.println("調用setApplicationContext方法,獲取Spring容器ApplicationContext對象:" + applicationContext);

	}

	@Override
	public void destroy() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("調用destroy方法,bean被銷燬了");

	}

	@Override
	public void afterPropertiesSet() throws Exception {
		// TODO Auto-generated method stub
		try {
			System.out.println("調用afterPropertiesSet方法,bean初始化執行了");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println("bean初始化異常" + e.getMessage());
		}

	}

	//@PostConstruct // 相當於在bean中配置了 init-method="myInit"
	public void myInit() {
		System.out.println("自定義init執行");
	}

	//@PreDestroy // 相當與在bean中配置了 destory-method="myDestroy"
	public void myDestroy() {
		System.out.println("自定義Destory執行");
	}

}

自定義類實現BeanPostProcessor接口,分別實現postProcessBeforeInitialization和postProcessAfterInitialization方法,可以在bean初始化前後執行,需要在xml配置文件中配置,是springIOC容器的擴展
BeanPostProcessor接口也叫後置處理器,作用是在Bean對象在實例化和依賴注入完畢後,在顯示調用初始化方法的前後添加我們自己的邏輯。注意是Bean實例化完畢後及依賴注入完成後觸發的。

/**
 * BeanPostProcessor是Spring IOC容器給我們提供的一個擴展接口
 * 
 * @author 張江豐
 *
 */
public class PostProcessor implements BeanPostProcessor {

	@Override // 在bean初始化之前執行
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if (bean instanceof TestBean) {
			System.out.println("調用postProcessBeforeInitialization方法,在初始化init之前執行:" + beanName + "開始實例化");
		}
		// 從spring IOC容器中取出bean,使用後必須返回bean對象
		return bean;
	}

	@Override // 在bean初始化之後執行
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean instanceof TestBean) {
			System.out.println("調用postProcessAfterInitialization方法,在初始化init之後執行:" + beanName + "實例化完成");
		}
		// 從spring IOC容器中取出bean,使用後必須返回bean對象
		return bean;
	}

}

junit測試

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring/applicationContext.xml" })
public class Test1 {

	@Test
	public void demo1() throws Exception {
		ApplicationContext app = new ClassPathXmlApplicationContext("spring/applicationContext.xml");
		TestBean tb = (TestBean) app.getBean("testBean");
		// TestBean tb = new TestBean();
		System.out.println(tb.getBeanStr());
	}

}

控制檯輸出內容

調用setBeanName方法:testBean
調用setApplicationContext方法,獲取Spring容器ApplicationContext對象:org.springframework.context.support.ClassPathXmlApplicationContext@63611043: startup date [Fri Feb 07 12:20:13 CST 2020]; root of context hierarchy
調用postProcessBeforeInitialization方法,在初始化init之前執行:testBean開始實例化
調用afterPropertiesSet方法,bean初始化執行了
自定義init執行
調用postProcessAfterInitialization方法,在初始化init之後執行:testBean實例化完成
張三的歌
調用destroy方法,bean被銷燬了
自定義Destory執行

由此可見控制檯輸出順序和springbean生命週期流程一致,首先執行實例化bean對象,設置對象屬性,檢查Aware相關接口,如果有類實現BeanPostProcessor接口,在bean初始化init前後執行擴展方法,bean可用狀態.

碼字不易,看過的同學請點贊~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章