一、BeanFactory輕量級
三種通路ApplicationContext.xml方式:
1、Resource resource = new ClassPathResource(“application.xml”);
BeanFactory factory = new XmlBeanFactory(resource);
HelloWorld hello = factory.getBean(“fileHelloWorld”);
2、基于檔案找到application.xml
InputStream is = new FileInputStream(“src/application.xml”);
BeanFactory factory = new XmlBeanFactory(is);
3、基于ApplicationContext
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(new String[]{“application.xml”});
BeanFactory factory = (BeanFactory)appContext;
Bean的生命周期
1、執行個體化JavaBean
2、JavaBean執行個體初始化,即通過IOC注入其依賴性。這一階段将完成JavaBean執行個體初始化
3、基于Spring應用對JavaBean執行個體的使用
4、IOC容器銷毀JavaBean執行個體
Bean的建立
<bean name="fileHelloWorld" class="com.jader.FileHelloWorld">
HelloWorld執行個體将使用無參數建構器建立出來
<bean name="fileHelloWorld" class="com.jader.FileHelloWorld" factory-method="createHelloWorldInstance">
HelloWorld必須提供createHelloWorldInstance的靜态方法
<bean name="helloWorldFactory" class="com.jader.FileHelloWorldFactory" />
<bean name="fileHelloWorld" class="com.jader.FileHelloWorld" factory-bean="helloWorldFactory' factory-method="createFileHelloWorldInstance">
此種情況類不需要提供靜态方法,命名為fileHelloWorld的JavaBean執行個體将通過helloWorldFactory工廠類的createFileHelloWorldInstance方法獲得
<bean name="fileHelloWorld" class="com.jader.FileHelloWorld">
<constructor-arg>
<ref bean="fileHello"/>
</constructor>
</bean>
通過ref元素引用Spring配置檔案中的fileHello,ref有以下幾個屬性:
1、bean:在目前Spring XML配置檔案中,或者在同一個BeanFactory(applicationContext)中的其他JavaBean中
2、local:在目前Spring XML配置檔案中,其依賴的JavaBean必須存在于目前Spring XML配置檔案中,
3、parent:用于指定其依賴的父JavaBean定義
初始化JavaBean
1、如果開發者使用了元素的autowire屬性,Spring能夠自動将目标JavaBean需要注入的JavaBean找到并注入進來。
2、如果開發者指定了元素的dependency-check屬性,則能夠保證各個Spring配置檔案中各個JavaBean之間的互相關系。
3、借助于setter方法能夠将JavaBean的屬性值注入進來,這些屬性可以是Java原型(primitive)、對象類型,甚至可以是null
例如:
<bean id="helloWorld" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref local="transactionManager"/>
</property>
<property name="transactionAttributers">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="set*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
Spring架構能夠注入TransactionProxyFactoryBean中的transactionManager、target、transactionAttributes所需的屬性值。比如:transactionManager屬性取值通過ref引用了transactionManager的POJO服務。如果Spring配置檔案中不存在事務管理器,開發者有兩種做法:
單獨定義新的transactionManager,例如:
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransactionName">
<value>java:comp/UserTransaction</value>
</property>
</bean>
ref會引用transactionManager
定義内部JavaBean方法:
<propery name="transactionManager">
<bean class="org.springframework.transaction.jat.JtaTransactionManager">
<property name="userTransactionName">
<value>java:comp/UserTransaction</value>
</property>
</bean>
</property>
通過定義内部JavaBean,其他JavaBean便不能夠引用到他,而且開發者再也不能夠重用JtaTransactionManager。現實場合存在這種需求,存在即是合理。
4、如果JavaBean實作了如下接口,還需要調用setBeanFactory方法
org.springframework.beans.factory.BeanFactoryAware
其定義了方法如下:
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
5、Spring架構提供了若幹接口,供開發者改變配置再BeanFactory中JavaBean的行為适用,其中InitializingBean接口介紹如下:
org.springframework.beans.factory.InitializingBean在BeanFactory初始化JavaBean時,BeanFactory會調用那些實作了InitializingBean接口的JavaBean中包含的方法:
void afterPropertiesSet() throws Exception;// InitializingBean定義的方法
6、最後通過在元素中包含init-method屬性能夠達到同InitializingBean一樣的目的,即:
<bean name="fileHelloWorld" class="com.openv.spring.HelloWorld" init-method="init">
HelloWorld将實作init方法
通過以上6步,完成JavaBean執行個體的初始化工作
使用JavaBean
借助于getBean方法,開發者就能夠在應用中使用他了
銷毀JavaBean
一旦将基于Spring的應用停止,Spring架構将調用那些JavaBean執行個體中存在的生命周期方法,比如:DisposableBean接口的JavaBean或者那些在Spring配置檔案中指定了destory-method屬性的JavaBean。
最終Spring将銷毀JavaBean執行個體。
注意:這些内容隻适合于那些通過singleton方法建立的JavaBean執行個體,對于那些以prototype方式建立的JavaBean執行個體,Spring并不能夠控制器生命周期,因為這種JavaBean執行個體建立成功,整個JavaBean将傳遞給Spring應用去管理。
其中,DisposableBean介紹如下:
org.springframework.beans.factory.DisposableBean:在BeanFactory銷毀JavaBean時,BeanFactory會調用那些實作了DisposableBean接口的JavaBean中包含的如下方法:
void destory() throws Exception;
其中,destroy是DisposableBean定義的方法。
當然,通過在元素中包含destroy-method屬性能夠達到同DisposableBean一樣的目的,即:
如果應用同僚實作了兩種方法,Spring先執行DisposableBean中的的destroy方法。
抽象Bean和子Bean定義
将公共内容放置在抽象bean中,子Bean能夠重用抽象Bean中定義的内容,而且還能夠“重載”他們。
PropertyPlaceholderConfigurer和PropertyOverrideConfigurer
對于PropertyPlaceholderConfigurer而言,他能夠在Spring配置檔案外部配置其他應用使用到的屬性,比如:通過Java屬性檔案配置資料庫連接配接資訊、LDAP(目錄通路協定)、活動目錄連接配接資訊。
例如:Apache DBCP資料源執行個體:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName"
<value>${jdbc.driverClassName}</value>
</property>
<property name="url">
<value>${jdbc.url}</value>
</property>
<property name="username">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
</bean>
其中$裡面的驅動名、url、使用者名、密碼的實際值通過Java屬性檔案獲得。
<bean id="propertyConfigurer" class="org.springframework.bean.factory.config.ProperryPlaceholderConfigurer">
<property name="location">
<value>jdbc.properties</value>
</property>
</bean>
BeactoryAware與BeanNameAware
對于某些基于Spring的應用而言,有一些将應用的BeanFactory執行個體注入到JavaBean執行個體中。比如:為在某JavaBean執行個體中動态獲得BeanFactory建立的某單例JavaBean,但是該單例JavaBean并沒有顯式的使用它,此時借助于BeanFactoryAware能夠滿足開發者要求,例如:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:/MysqlDS</value>
</property>
</bean>
<bean id="exampleServiceTarget" class="com.openv.spring.service.impl.ExampleManagerImpl">
<property name="userInfo">
<ref local="userInfoDao" />
</property>
</bean>
如果在exampleServiceTarget中需要使用dataSource,但是在Spring配置檔案中并沒有顯式的配置對dataSource的引用。此時,需要借助于BeanFactoryAware,即ExampleManagerImpl需要實作BeanFactoryAware接口。
如果需要在JavaBean執行個體中獲悉其配置的名字,可以考慮實作BeanNameAware接口:
org.springframework.beans.factory.BeanNameAware
其定義了如下方法:
void setBeanName(String name);
其執行時間在調用InitializingBean afterPropertiesSet或者自定義init-method之前,而在JavaBean屬性正常指派之後。
二、ApplicationContext
Spring架構引入了ApplicationContext接口,開發者不需要手工建立ApplicationContext執行個體,便可以聲明的方式使用它。例如:
org.springframework.web.context.ContextLoaderServlet或者
org.springframework.web.context.ContextLoaderListener
能夠在web應用啟動的時候自動執行個體化ApplicationContext對象,對于SpringBeanFactory而言,如果使用者沒有調用getBean()方法,則使用到的JavaBean執行個體将會被建立。是以在BeanFactory中使用了延遲裝載的機制,這主要是同BeanFactory的應用場合有關。對于Spring ApplicationContext而言,一旦ContextLoaderServlet或ContextLoaderListener初始化成功所有的JavaBean執行個體将會被建立(除非開發者改變了ApplicationContext的預設行為,比如顯式的設定延遲裝載行為)
開發者應該注意到Log4jConfigServlet,供配置Spring應用的日志使用,使用方法同ContextLoaderServlet,如下:
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j.properties</param-value>
</context-param>
<servlet>
<serlvet-name>log4jConfigServlet</servlet-name>
<serlvet-class>
org.springframework.web.util.Log4jConfigServlet
</servlet-class>
<load-on-startup></load-on-startup>
</servlet>
(>0表示容器在應用啟動時就加載并初始化這個servlet,
當值小于0或者沒有指定時,則表示容器在該servlet被選擇時才會去加載,
正數的值越小,該servlet的優先級越高,應用啟動時就越先加載)
開發者應該注意到Log4jConfigListener類供配置Spring應用的日志使用,由于ApplicationContext含有BeanFactory的所有功能,是以對于開發J2EE應用場合推薦使用ApplicationContext。
1、Web應用中建立ApplicationContext
Web應用自動過程中将自動初始化監聽器,而ContextLoaderListener就是監聽器,例如:
<context-param>
<param-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
2、ApplicationContextAware
在為某JavaBean執行個體動态獲得ApplicationContext建立的某單例JavaBean,但是該單例JavaBean并沒有顯式的使用(在Spring配置檔案沒有顯式的給出對單例JavaBean的引用,例如未使用元素),借助于ApplicationContextAware能夠滿足開發者的要求
介紹如下:
org.springframework.context.ApplicationContextAware
其定義了如下方法:
void setApplicationContext(ApplicationContext applicationContext);
現有如下示例代碼:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean" >
<property name="jndiName">
<value> java:/MySqlDS</value>
</property>
</bean>
<bean id="exampleServiceTarget" class="com.openv.spring.service.impl.ExampleManagerImpl">
<property name="userInfo">
<ref local="userInfoDao" />
</property>
</bean>
如果在exampleServiceTarget需要使用到dataSource,但是Spring配置檔案中沒有顯式的配置對dataSource的引用,此時可以借助ApplicationContextAware接口。
示例代碼:
public class ExampleManagerImpl implements ApplicationContextAware{
private ApplciationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext){
this.applicationContext = applicationContext;
}
pubic DataSource getDataSource(){
DataSource ds = null;
ds = (DataSource)applicationContext.getBean("dataSource");
retrun ds;
}
}
這同BeanFactoryAware類似。
3、ApplicationContext接口實作
ClassPathXmlApplicationContext:在Web應用中,開發者可以從其classpath中,即WEB-INF/classes或WEB-INF/lib的jar中裝載Spring配置檔案
FileSystemXMLApplicationContext:開發者可以從檔案系統中裝載Spring配置檔案
XMLWebApplicationContext:供ContextLoaderListener或ContextLoaderServlet内部裝載Spring配置檔案使用。