Spring IoC 學習(2)
前言
知道了IoC的好處和優勢之後,本來應該有的一步是,搞清楚怎麼用。因為前麵我寫的順序是:是什麼,為什麼?下一個part肯定的就是怎麼辦或者怎麼用?但是,按照Spring的官方的Guide,我覺得應該大家是可以寫個Hello World。網上這類的教程也很多,加上其實我這次學習Spring是想更加深入的學習,因此,重點就不放在這個部分了。主要放在學習背後的故事。
這小節的內容就是學習IoC的容器。
兩種容器
概述
整個IoC容器可以分為兩個階段,容器啟動階段和實例化階段。
容器啟動階段
①就是把xml文件裏麵的配置信息弄到BeanDefinition中。那就必須來看一下BeanDefinition
private volatile Object beanClass;
private String scope;
private boolean abstractFlag;
private boolean lazyInit;
private int autowireMode;
private int dependencyCheck;
private String[] dependsOn;
...
這個裏麵的東西也是相當的多,但是總的來說就是記錄一些bean的信息,方便與後麵的實例化。
② 讀完配置文件之後,是得到了很多BeanDefinition。然後通過BeanDefinitionRegistry將這些bean注冊到beanFactory中。下麵看一看具體的實現類DefaultListableBeanFactory裏麵是如何注冊的。
/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap
= new ConcurrentHashMap<String, BeanDefinition>(64);
//... codes ...
//---------------------------------------------------------------------
// Implementation of BeanDefinitionRegistry interface
//---------------------------------------------------------------------
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
// ...codes...
this.beanDefinitionMap.put(beanName, beanDefinition);
// ...codes...
上麵的代碼雖然省略了很多很多的邏輯,但是實際重要的部分是我體現的那部分,首先,DefaultListableBeanFactory中先是new了一個final的ConcurrentHashMap,用來裝BeanDefinition,然後經過一係列的邏輯判斷之後,裝進去。後麵如果要拿出來,想著應該也是用相應的方法拿出來。
不信你看
@Override
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
BeanDefinition bd = this.beanDefinitionMap.get(beanName);
if (bd == null) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("No bean named '" + beanName + "' found in " + this);
}
throw new NoSuchBeanDefinitionException(beanName);
}
return bd;
}
到了這一步,按理,我們的第一步,即容器啟動階段就結束了。然而
Spring還給我們提供了接口,幹什麼呢?如果你想搞些事情呢?那我不能讓你搞,豈不是很不好。開源框架嘛,拓展性非常重要。
接口--BeanFactoryPostProcessor就是做這個工作的,其中有幾個Spring自帶的,挺有用的BeanFactoryPostProcessor。
① PropertyPlaceHolderConfigurer
從這個類圖上就可以看到,PropertyPlaceholderConfigurer間接實現了BeanFactoryPostprocessor。是Spring自帶的搞事情實現類。
【主要功能】
為什麼叫PropertyPlaceHolderConfigurer,PlaceHolder就叫做占位符,所以這個Configurer主要的功能特點,就是占位符相關的。例如,以下我們這種常見的應用。
很常見吧,我們不直接寫值,而是寫占位符,然後在其他地方我們再去寫值。當然,要用它,必須要把它加上
② PropertyOverrideConfigurer
以下代碼說明應用
<bean class ="org.springframework.beans.factory.config.PropertyOverrideConfigurer">
<property name="properties">
<map>
<!-- 不管原來的sex是什麼,最後就是male -->
<entry key="testBean.sex" value="male"/>
</map>
</property>
可以用來覆蓋原來初始化的值。不過其實我有一個問題,為什麼要多此一舉。要不就是隻有一種可能,那個配置文件,我們沒法改,那我們就在這個地方做一個修改。這麼想想的話,還是有些作用的。
③ CustomEditorConfigurer
這家夥的中文名叫自定義屬性編輯器,又一個中文字麵全看懂,不知道幹啥用的典例。
Class Person{
Date birthday;
// setter getter 等默認有【懶】
}
beans.xml
<!-- 實例化直接是個String,人家怎麼知道你是不是Date,怎麼知道怎麼轉換 -->
<bean >
<property name="birthday">
<value>2017-08-29</value>
</property>
</bean>
<!-- 定義屬性編輯器 -->
<bean >
<property name="customEditors">
<map>
<entry key="java.util.Date">
<bean >
<property name="format" value="yyyy-MM-dd"/>
</bean>
</entry>
</map>
</property>
</bean>
自己定義的日期類型編輯器
import java.beans.PropertyEditorSupport;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* java.util.Date屬性編輯器
* @author Administrator
*
*/
public class UtilDatePropertyEditor extends PropertyEditorSupport {
private String format="yyyy-MM-dd";
@Override
public void setAsText(String text) throws IllegalArgumentException {
SimpleDateFormat sdf = new SimpleDateFormat(format);
try {
Date d = sdf.parse(text);
this.setValue(d);
} catch (ParseException e) {
e.printStackTrace();
}
}
public void setFormat(String format) {
this.format = format;
}
}
Bean實例化階段
本來是要把Bean實例化階段也寫完的,但是鑒於現在為止,整個的篇幅已經比較長,再寫下去,怕是有人要煩了。【我才不會說是我累了】
最後更新:2017-08-29 18:03:18