Spring框架裏面誰來充當這個assembler的角色呢?是BeanFactory。Spring提供了品種繁多的BeanFactory,共用戶在不同場合下使用。我們通常更多的是使用它的子接口ApplicationContext。大致上分了三類:Java Application,Web Application 和 Portlet Application。
本文通過一個簡單的例子([url]http://svn.springbyexample.org/core/basic-dependency-injection/[/url])來看看ClassPathXmlApplicationContext的調用和執行順序圖(用MaintainJ生成的):
[img]http://dl.iteye.com/upload/attachment/0067/6260/08825bef-0faa-308f-9146-090846fbc648.png[/img]
上圖的init代表執行構造函數。上圖表達了下面這句話:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/application-context.xml");
再看看類圖:
[img]http://dl.iteye.com/upload/attachment/0067/6262/23e28826-c3f9-32cb-9990-ed024647b8d0.png[/img]
再細緻的看下去,分解StandardEnvironment的構建過程(可以看出是解析各種屬性的過程):
[img]http://dl.iteye.com/upload/attachment/0067/6271/d72f5189-9247-3179-816b-71ff3c4d4da6.png[/img]
屬性都load好了,環境也構建好了,那麼Bean的實例在哪裏創建的呢?關鍵得看DefaultListableBeanFactory:
[img]http://dl.iteye.com/upload/attachment/0067/6275/3f2f55d9-8da9-3b20-a641-8494365431b8.png[/img]
這裏面關鍵是看registerSingleton函數,它負責把bean緩存到singletonObjects (private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>();)
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
Object oldObject = this.singletonObjects.get(beanName);
if (oldObject != null) {
throw new IllegalStateException("Could not register object [" + singletonObject +
"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
}
addSingleton(beanName, singletonObject);
}
}
/**
* Add the given singleton object to the singleton cache of this factory.
* <p>To be called for eager registration of singletons.
* @param beanName the name of the bean
* @param singletonObject the singleton object
*/
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
從上面的邏輯上可以看出,同名的類是不能被緩存進去的,會拋出異常。
好了,後的程序想getBean的時候只需要從這個緩存中獲取就好了。