Spring之Core模組
Core模組主要的功能是實現了控制反轉與依賴注入、Bean配置以及載入。Core模組中有Beans、BeanFactory、BeanDefinitions、ApplicationContext等概念
BeanFactory
BeanFactory是例項化、配置、管理眾多bean的容器
在Web程式中使用者不需要例項化Beanfactory,Web程式載入的時候會自動例項化BeanFactory,並載入所欲的Beans,將各個Bean設定到Servlet、Struts的Action中或者Hibernate資源中
在Java桌面程式中,需要從BeanFactory中獲取Bean,因此需要例項化BeanFactory,例如,載入ClassPath下的配置檔案:
ClassPathResource res = new ClassPathResource("applicationContext.xml"); XmlBeanFactory factory = new XmlBeanFactory (res); Iservice service= factory.getBean("service"); …… factory.destroySingletons();
或者使用檔案流載入任意位置的配置檔案
InputStream in = new FileInputStream("C:\\ApplicationContext.xml"); XmlBeanFactory factory = new XmlBeanFactory (in);
或者用ClassPathXmlApplicationContext載入多個配置檔案(以字串形式傳入)ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext( new String [] {"applicationContext.xml","applicationContext-part2.xml"} ); BeanFactory factory = (BeanFactory) appContext; //ApplicationContext繼承自BeanFactory介面
配置Bean
工廠模式
如果一個bean不能通過new直接例項化,而是通過工廠類的某個方法建立的,需要把<bean>的class屬性配置為工廠類(或者吧factory-bean屬性配置為工廠類物件)
<bean id="examBean" class = "examples.MyBeanFactory" method="createInstance" /> <!--等價於下面的配置--> <bean id="examBean2" factory-bean = "examples.MyBeanFactory" method="createInstance" />
建構函式
如果Bean的建構函式帶有引數,需要指定建構函式的引數
<bean id = "examBean" class=" examples.ExampleBean"> <constructor-args><ref bean="anotherBeanId"/></constructor-args> <constructor-args><ref bean="anotherBeanId2"/></constructor-args> <constructor-args><value>1</value></constructor-args> </bean>
引數又先後順序,要與建構函式引數的順序相同單態模式
Bean可以定義是否為單態模式,在非單態模式下,每次請求該Bean都會生成一個新的物件
像資料來源等一般配置為單態模式
<bean id="exampleBean" class="examples.ExamleBean" singleton="false"/>
property屬性
destroy-method屬性配置關閉方法,如果有配置,在丟棄Java物件時會呼叫該方法,某些資料來源、SessionFactory物件都需要用destroy-method配置關閉方法
<property name="examProperty" value="pValue" />
等價於<property name="examProperty"> <value>pValue</value> </property>
注意:
<property name="password"> <value></value> </property>
會將password設定為"",而不是null,如果想設定為null應該為
<property name="password"> <null/> </property>
<ref>屬性
Spring配置檔案的Bean之間可以相互引用,引用時用<ref>標籤配合Bean的id屬性使用
也可以使用內部配置
<bean id="dao" class = "com.clf.DaoImpl"></bean> <bean id="serviceImpl" class="com.clf. serviceImpl"> <property name="dao"> <ref bean="dao"/> </property> </bean>
等價於內部配置<property name="dao"> <bean class="com.clf.DaoImpl"/> </property>
除了使用<ref>的bean屬性,還可以使用local、parent,它們與bean屬性的作用是一樣的,但是,local只能使用本配置檔案中的bean,parent只能使用父配置檔案中的bean
<list>屬性
<property name="propName"> <list> <value>String、Integer、Double等型別資料</value> <ref bean="dataSource"/> </list> </property>
<set>屬性
<property name="propName"> <set> <value>String、Integer、Double等型別資料</value> <ref bean="dataSource"/> </set> </property>
<map>屬性
<property name="propName"> <map> <entry key="key1"> <value>String、Integer、Double等型別資料</value> </entry> <entry key-ref="key2"> <ref bean="dataSource"/> </entry> </map> </property>
<props>屬性
<property name="propName"> <props> <prop key="url">http://localhost:8080/clf</prop> <prop key="name">clf</prop> </ props > </property>
<destroy-method>和<init-method>屬性
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> …… </bean>
Spring在登出這些資源時會呼叫close方法
有些物件在例項化之後需要執行某些初始化程式碼,但是這些程式碼不能寫進建構函式,這時候可以把初始化程式碼寫進某個方法中,並用<init-method>指定該方法
<bean id="c" class="com.clf.SpringExample" init-method="init">
depends-on屬性
Spring會預設按照配置檔案裡的Bean順序地例項化Bean,但是有時候例項化A物件之前需要先例項化後面的B物件,這時候可以使用depends-on屬性強制先例項化B物件
<bean id="a" clas="com.clf.A" depends-on="b"></bean> <bean id="b" clas="com.clf.B"></bean>
<idref>與<ref>的區別
<idref>與<ref>的作用是一樣的,都是配置Java物件的,不同的是,<idref>只有bean與local屬性,沒有parent屬性
Spring載入XML配置檔案時,會檢查<idref>配置的Bean在不在,而<ref>只會在第一次呼叫時才會檢查,換句話說,如果Bean不存在,<idref>在啟動程式時就會丟擲錯誤,而<ref>只會在執行中丟擲錯誤
<autowire>
可以通過Bean的autowire屬性設定自動裝配規則。使用autowire後不需要再用<propertyname="" value="" />顯式地設定該Bean的屬性、依賴關係,Spring會根據反射,自動尋找符合條件的屬性,設定到該Bean上
autowire屬性定義的不是需要自動裝配的屬性名,而是自動裝配的規則,一旦配置,所有的屬性都會遵循autowire定義的規則
No:即不啟用自動裝配。Autowire預設的值。
byName:通過屬性的名字的方式查詢JavaBean依賴的物件併為其注入。比如說類Computer有個屬性printer,指定其autowire屬性為byName後,Spring IoC容器會在配置檔案中查詢id/name屬性為printer的bean,然後使用Setter方法為其注入。
byType:通過屬性的型別查詢JavaBean依賴的物件併為其注入。比如類Computer有個屬性printer,型別為Printer,那麼,指定其autowire屬性為byType後,Spring IoC容器會查詢Class屬性為Printer的bean,使用Setter方法為其注入。
constructor:通byType一樣,也是通過型別查詢依賴物件。與byType的區別在於它不是使用Setter方法注入,而是使用構造子注入。
autodetect:在byType和constructor之間自動的選擇注入方式。
default:由上級標籤<beans>的default-autowire屬性確定。
dependency-check
有時候某些Bean的屬性配置有錯誤,這種錯誤在程式啟動的時候不會有任何異常,會一直潛伏到Spring呼叫該Bean時才會被發現
依賴檢查能夠檢查屬性是否被設定,如果配置了依賴檢查,程式啟動是會進行配置校驗,以便及時地發現錯誤。
但是需要注意的是,依賴檢查是很生硬的,例如設定為object,將會檢查所有的Java物件屬性,只要有一個屬性沒有設定,就會丟擲異常
no或default:不做任何檢查,預設
simple:僅檢查基本型別、集合屬性
object:僅檢查Java物件屬性
all:檢查所有屬性
Bean的高階特性
BeanNameAware介面幫助Bean知道自己在配置檔案中的id
import org.springframework.beans.factory.BeanNameAware; public class BeanNameTest implements BeanNameAware{ private String beanName; //Spring會呼叫該方法 public void setBeanName(String beanName){ this.beanName = beanName; } }
BeanFactoryAware介面幫助Bean知道哪個BeanFactory例項化了自己
public interface BeanFactoryAware{ void setBeanFactoryAware(BeanFactory beanFactory) throws BeanException; }
用法同BeanNameAware
此外還有一下常用的方法
boolean containsBean(String)判定指定名稱的Bean是否存在
Object getBean(String)返回指定名稱,如果沒有該Bean會丟擲異常
Object getBean(String,Class)返回指定名稱的Bean,並轉化為指定的類物件
boolean isSingleton(String)判斷指定名稱的Bean是否被配置為單態模式
String []getAliases(String)返回指定名稱的Bean的別名
InitializingBean介面會在Bean例項化後、所有屬性被設定後呼叫初始化方法。但是使用該介面會與Spring程式碼發生耦合,因此不推薦使用,Spring推薦使用init-method配置
public interface InitializingBean{ public void afterPropertiesSet(); //初始化時呼叫此方法 }
DisposableBean介面會在Bean物件丟棄時呼叫銷燬方法
public interface DisposableBean{ public void destroy(); //銷燬時呼叫此方法 }
屬性覆蓋器
對於一些引數,更實用更簡單的方法是使用properties配置,而不是配置在Spring的配置檔案中
PropertyPlaceholderConfigurer允許把XML配置的某些引數配置到properties檔案中
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc. username}"/> <property name="password" value="${jdbc. password}"/> </bean> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="loaction" value="classpath:jdbc.properties"> </bean>
jdbc.properties
jdbc.driverClassName= com.mysql.jdbc.Driver jdbc.url =jdbc:mysql://localhost:3306/clf?characterEncoding=UTF-8 jdbc.username =clf jdbc.password =admin