迄今爲止,所接觸到的Bean都是「無知覺」的,就像黑客帝國中機械工廠裏面「養殖」的人類,他們雖然能完成必定的功能,可是根本不知道本身在工廠(BeanFactory)中的代號(id),或者本身是在哪一個工廠(BeanFactory的引用)中沉睡。因此,本節的目的就是要創造出一個尼奧同樣的Bean,讓他知道本身在工廠中的id和本身原來躺在哪一個工廠中。這裏,稱之爲,Bean對Spring有知覺。程序員
可是有言在先,若是要在Spring容器中作到這兩點,固然,能夠本身經過某些方法實現,代價是大量冗餘代碼,好處是跟Spring解耦。若是使用Spring提供的接口,好處固然減小代碼的規模,「缺點」(若是算的話)是與Spring耦合。總之,不管採起那種辦法仍是要看實際須要。this
/////////////////////
讓Bean對Name有知覺
/////////////////////spa
做用:讓Bean獲取本身在BeanFactory配置中的名字(根據狀況是id或者name)。接口
實現:經過實現BeanNameAware接口,接口中就一個方法setBeanName()生命週期
例程以下(P100,代碼清單5-11,部分)
public class LogginBean implements BeanNameAware {
private String beanName = null;
public void setBeanName(String beanName) {
this.beanName = beanName;
}
}內存
額外說明:
Spring自動調用。而且會在Spring自身完成Bean配置以後,且在調用任何Bean生命週期回調(初始化或者銷燬)方法以前就調用這個方法。換言之,在程序中使用BeanFactory.getBean(String beanName)以前,Bean的名字就已經設定好了。因此,程序中能夠盡情的使用BeanName而不用擔憂它沒有被初始化。get
固然,Bean之中必定要有個String類型變量來保存BeanName的值,這個是在編寫Bean代碼時有程序員手工完成的,而不是經過什麼特殊的餓配置。io
一般都是爲了更好的餓配置Log,可是請注意,不要只是由於配合Log就把bean那麼中添加任何業務含義,不然會讓你本身的類關聯到某個Spring特性上去,而它帶來的好處倒是微不足道的。若是確實須要Bean帶有某種內部名稱,那麼最好讓Bean本身實現某個方法,例如setName(),而後使用DI給每一個Bean注入一個名字,這樣技能保持配置Bean的名字仍然可以簡潔,且你也無需修改本身的配置文件,好讓Bean的名字帶有業務含義。class
////////////////////////////////
讓Bean對工廠有知覺
////////////////////////////////容器
做用:讓Bean獲取配置他們的BeanFactory的引用。
實現:實現BeanFactoryAware接口,其中只有一個方法即setFactory(BeanFactory factory)。使用上與BeanNameAware接口無異,只不過BeanFactoryAware注入的是個工廠,BeanNameAware注入的是個Bean的名字。
額外說明:
雖然原書中並未說起setFactory()方法的調用時機,可是能夠猜測到,這個方法多是在根據某個配置文件建立了一個新工廠以後,Spring才調用這個方法,並把BeanFactory注入到Bean中。
讓bean獲取配置本身的工廠以後,固然能夠在Bean中使用這個工廠的getBean()方法,可是,實際上很是不推薦這樣作,由於結果是進一步加大Bean與Spring的耦合,並且,能經過DI注入進來的儘可能經過DI來注入。
固然,除了查找bean,BeanFactory能夠提供大量其餘的功能,例如銷燬singleton模式的Bean。
補充說明: factory.preInstantiateSingletons();方法。preInstantiateSingletons()方法當即實例化全部的Bean實例,有必要對這個方法和Spring加載bean的機制作個簡單說明。 方法自己的目的是讓Spring當即處理工廠中全部Bean的定義,而且將這些Bean所有實例化。由於Spring默認實例化Bean的狀況下,採用的是lazy機制,換言之,若是不經過getBean()方法(BeanFactory或者ApplicationContext的方法)獲取Bean的話,那麼爲了節省內存將不實例話Bean,只有在Bean被調用的時候才實例化他們。