第五章 spring-connet之bean生命週期與bean監控

前言

javaBean

javaBean是java公共組件的標準。起源於Java GUI的可視化編程實現的,全部的組件都須要支持拖拉,那麼全部的組件的行爲都是一致的。當拖拉組件的時候,就會建立一個改組件的對象,而後進行參數賦值改變組件的屬性。 拖拉一個組件等於建立了這個組件的一個對象,在拖拉的時候是沒法提供參數的。拖拉以後才能給組件賦值,怎麼賦值。java

實例化

實例化那麼必須是一個類,不是接口,也不能是抽象類程序員

無條件實例化

拖拉完成才能獲得真正的座標,你們不會拖拉以前就設定屬性,而是按照原型圖,先拖拉在設定屬性。因此實例化在前,屬性設置在後。若是定義了有參構造函數,那麼須要提供參數才能實例化,等於先設定屬性,不符合Java GUI的可視化編程中拖拉的規則。組件必需要有一個無參構造方法,能夠無條件實例化。spring

無條件實例化必定有一個無參構造方法,不須要關注其餘細節,拉來就可使用。編程

變量私有化

其實這個並非Java GUI的可視化編程裏面必須條件,可是由於面向對象設計與面向對象提供封裝這個特性,並且變量私有化和封裝帶來了不少好處,變量私有化成爲了javaBean中一個重要的特性app

私有化變量經過get/set方法進行操做

當一個組件有不少屬性,多個不一樣屬性能夠組成一個行爲,多個屬性出現N中排列組合,是否須要各類排列組合的有參構造方法。框架

隨着時間的推進,需求發生變化,須要添加一個屬性,是否出現大量的新的排列組合,須要修改和添加大量的有參構造方法ide

因此經過get/set的方式,提升了很大的靈活度,擴展度,方便維護函數

若是某個屬性不是提供對外負責,只提供本類或者子類,同包使用,不用與數據傳遞,能夠不提供get/set方法。post

總結

Java GUI的可視化編程對組件的定義,對維護,擴展等方面十分友好,很大程度提升了可視化編程效率。等到不少程序員的承認,普及率高,普遍。慢慢成爲了javaBean規範。ui

javaBean規範是整個java體系的基石

javaBean規範是整個java體系的基石

javaBean規範是整個java體系的基石

規範細節

  1. 普通類,才能實例化。不是接口,也不是抽象類
  2. 無參構造方法。若是沒有定義無參構造方法,在沒有任何其餘有參構造方法的狀況下,javac會在class文件中生產無參構造方法。這點是Javabean最重要的特性,是不可缺乏的。
  3. 變量私有化
  4. 提供變量操做方法get/set, boolean可使用前綴未is
  5. 變量與方法的命令按照駝峯命名法
public class userInfo{
	
	private long uiId;
	
	private String uiName;
	
	public void setUiId(long uiId){
	 this.uiId = uiId;
	}
	
	public long getUiId(){
		return this.uiId;
	}
	
	public void setUiName(long uiName){
	 this.uiName = uiName;
	}
	
	public long getUiName(){
		return this.uiName;
	}
}

看看這個類

public class niaocai{

	private  int ctl = 1;
	
}

這樣也是一個javabean,只是沒有set/get。可是由於ctl只是給本身用的

spring的bean

spring的bean其實就參照的ejb的bean,二者從出發點,實現等基本一致,因此佔同稱bean。已經有了javaBean,爲何還要bean了。在企業需求愈來愈複雜,形成工程愈來愈龐大,複雜,膿腫。現有的javabean沒法解決問題。因此提出了依賴注入,反轉控制的概念。bean是解決依賴注入,反轉控制中。

一個框架實現ioc,那麼必須提供一個容器,否者沒法實現ioc 有容器了,非容器的bean如何想到容器自己的一些bean

看下面有什麼問題

public class Niaocai{

	private Niao niao;
	
	private Cai cai;
	
	private String daSshen;
	
	public Niaocai(){
		init();
	}

	public init(){
		if(niao.getxxx == xxxx && cai.getXXXX ==xxxx){
			daSshen = "dashen"
		}else{
			daSshen = "cainiao"
		}
	}

}

上面是否是在實例化的時候會報錯。由於調用init比注入要優選。這個問題怎麼解決,你們都給下面的解決方案

public class Niaocai{

	private Niao niao;
	
	private Cai cai;
	
	private String daSshen;
	
	public Niaocai(Niao niao , Cai cai){
		this.niao = niao;
		this.cai  = cai;
		if(niao.getxxx == xxxx && cai.getXXXX ==xxxx){
			daSshen = "dashen"
		}else{
			daSshen = "cainiao"
		}
	}
}

解決了在實例化的時候,回答javabean的定義中,分析了構造方法弊端。因此須要另外的解決方法

public class Niaocai{

	private Niao niao;
	
	private Cai cai;
	
	private String daSshen;
	
	@PostConstruct
	public init(){
		if(niao.getxxx == xxxx && cai.getXXXX ==xxxx){
			daSshen = "dashen"
		}else{
			daSshen = "cainiao"
		}
	}
	... get/set方法
}

Niaocai niaocai = new Niaocai();
niaocai.setNaio(niao);
niaocai.setCai(cai);
niaocai.init();

從上面的代碼,分析到依賴注入與Aware接口參數注入以後會調用初始化方法。當初始化方法執行完,才標識這個bean完成。實例化完成只是javabean完成的標識。

真確理解bean的生命週期

  1. 實例化
  2. 依賴注入
  3. Aware接口參數注入
  4. 初始化
  5. 銷燬

讀者會問,bean的生命週期,怎麼僅僅有這些啊。不是還有不少接口。 深刻了解下什麼是生命週期。生命週期是指一個個體的生老病死。那些接口只是對bean進行監控而已。好比單一個生命以前,會進行檢測,出生以後會進行戶口登記,死亡會註銷戶口。這些與我的的生命週期沒有關係啊。

bean處理體系

bean處理體系是bean最重要的模塊之一,本節只是大概,簡單讓你們瞭解bean處理系統。在第五章有專門的章節消息的講述

輸入圖片說明

@Component
public class NiaoCaiBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor ,MergedBeanDefinitionPostProcessor ,DestructionAwareBeanPostProcessor{

    public NiaoCaiBeanPostProcessor() {
		System.out.println("NiaoCaiBeanPostProcessor ");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("BeanPostProcessor.postProcessBeforeInitialization   " +  beanName);
	return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("BeanPostProcessor.postProcessAfterInitialization   "  +  beanName);
	return null;
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		// 返回非null,退出鏈式執行,只會調用beanProcessor.postProcessAfterInitialization方法
		// 當 beanProcessor.postProcessAfterInitialization方法返回非null  會中止接下來的流程。構造調用,依賴注入,初始化等等都不會執行
		System.out.println("InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation   "  +  beanName);
	return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
		// 返回false,退出鏈式執行,會中止依賴注入
		System.out.println("InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation   " +  beanName);
	return true;
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean,String beanName) throws BeansException {
		System.out.println("InstantiationAwareBeanPostProcessor.postProcessPropertyValues   " + beanName+ "   pvs : " + pvs.toString() + " pds : " + pds.toString());
	return pvs;
    }

    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		System.out.println("MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition   "  +  beanName);
	
    }

    @Override
    public Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
		//System.out.println("SmartInstantiationAwareBeanPostProcessor.predictBeanType   " +    beanName);
		return null;
    }

    @Override
    public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
	System.out.println("SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors  "  +  beanName);
	return null;
    }

    @Override
    public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
		System.out.println("SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference   "  +  beanName);
	return null;
    }

    @Override
    public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
		System.out.println("DestructionAwareBeanPostProcessor.postProcessBeforeDestruction  "  +  beanName);
	
    }

    @Override
    public boolean requiresDestruction(Object bean) {
		System.out.println("DestructionAwareBeanPostProcessor.requiresDestruction  " + bean.toString());
	return true;
    }
}
@Comonent
public class ProcessorObject implements InitializingBean , DisposableBean, BeanNameAware{

   // @Autowired
    private Rely rely;
    
    public ProcessorObject() {
	System.out.println("ProcessorObject structure");
    }

    @PostConstruct
    public void postConstruct(){
	System.out.println("javax.annotation.postConstruct  "  + this.getClass().getName());
    }
    
    @PostConstruct
    public void postConstructTwo(){
	System.out.println("javax.annotation.postConstructTwo  "  + this.getClass().getName());
    }
    
    @PreDestroy
    public void preDestroy(){
	System.out.println("javax.annotation.preDestroy  "  + this.getClass().getName());
    }
    
    @Override
    public void destroy() throws Exception {
	System.out.println("DisposableBean destroy  "  + this.getClass().getName());
	
    }

    @Override
    public void afterPropertiesSet() throws Exception {
	System.out.println("InitializingBean.afterPropertiesSet  "  + this.getClass().getName());
    }

    @Override
    public void setBeanName(String name) {
	System.out.println("BeanNameAware : " + name);
	
    }
    
}
public class BeanPostProcessorTest extends SpringContext{
    
    @Test
    public void beanPostProcessorTest(){
	
	this.application.refresh();
	this.application.close();
    }

}

實例化以前

InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation 執行標誌着一個對象生命週期的開始

  1. InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation processorObject
  2. SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors processorObject

實例化與實例化以後

  1. 執行構造方法,實例化對象 ProcessorObject structure()

  2. 執行MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition processorObject

  3. 執行MergedBeanDefinitionPostProcessor.postProcessAfterInstantiation 標識對象實例化操做結束 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation processorObject

參數注入 6. InstantiationAwareBeanPostProcessor.postProcessPropertyValues processorObject pvs : PropertyValues: length=0 pds : 參數注入

  1. 基本Awate對象注入,詳情請看關於Awate深刻解讀章節 BeanNameAware : processorObject
初始化
  1. 先執行@PostConstruct javax.annotation.postConstruct com.niaocaia.blog.spring.connet.beanLife.ProcessorObject javax.annotation.postConstructTwo com.niaocaia.blog.spring.connet.beanLife.ProcessorObject

  2. 在執行BeanPostProcessor.postProcessBeforeInitialization BeanPostProcessor.postProcessBeforeInitialization processorObject

  3. 而後執行InitializingBean的afterPropertiesSet InitializingBean.afterPropertiesSet com.niaocaia.blog.spring.connet.beanLife.ProcessorObject

  4. 在執行BeanPostProcessor.postProcessAfterInitialization BeanPostProcessor.postProcessAfterInitialization processorObject

  5. 最後執行DestructionAwareBeanPostProcessor.requiresDestruction , 執行以後,才能使用。 DestructionAwareBeanPostProcessor.requiresDestruction com.niaocaia.blog.spring.connet.beanLife.ProcessorObject@769e7ee8

銷燬

先執行執行@preDestroy javax.annotation.preDestroy com.niaocaia.blog.spring.connet.beanLife.ProcessorObject

在執行DestructionAwareBeanPostProcessor 對象的postProcessBeforeDestruction DestructionAwareBeanPostProcessor.postProcessBeforeDestruction processorObject

最後執行 DisposableBean接口的destroy實現方法,整個baen生命週期結束 DisposableBean destroy com.niaocaia.blog.spring.connet.beanLife.ProcessorObject

總結
  1. @PostConstruct與@preDestroy的執行優先DisposableBean與InitializingBean
  2. @PostConstruct在BeanPostProcessor.postProcessBeforeInitialization以前執行,而InitializingBean在BeanPostProcessor.postProcessBeforeInitialization以後執行
  3. @preDestroy在DestructionAwareBeanPostProcessor.postProcessBeforeDestruction以前執行,而DisposableBean在DestructionAwareBeanPostProcessor.postProcessBeforeDestruction以後執行
  4. @PostConstruct與@preDestroy在一個類裏面,能夠標識在多個方法上。
相關文章
相關標籤/搜索