1、Bean Wrapper
?????? 這個(gè)BeanWrapper類很簡(jiǎn)單,提供了一套Bean的操作方法,如apache -BeanUtils一樣。通過BeanWrapper,我們可以無需在編碼時(shí)就指定JavaBean的實(shí)現(xiàn)類和屬性值,通過在配置文件
加以設(shè)定,就可以在運(yùn)行期動(dòng)態(tài)創(chuàng)建對(duì)象并設(shè)定其屬性(依賴關(guān)系)。 一個(gè)簡(jiǎn)單的例子:
????public?static?void?testBeanWrapper(){
????????try?{
????????????Object?obj=Class.forName("com.spring.UpperAction").newInstance();
????????????BeanWrapper?bw=new?BeanWrapperImpl(obj);
????????????bw.setPropertyValue("message","peidw");
????????????System.out.println(bw.getPropertyValue("message"));
????????}?catch?(InstantiationException?e)?{
????????????//?TODO?Auto-generated?catch?block
????????????e.printStackTrace();
????????}?catch?(IllegalAccessException?e)?{
????????????//?TODO?Auto-generated?catch?block
????????????e.printStackTrace();
????????}?catch?(ClassNotFoundException?e)?{
????????????//?TODO?Auto-generated?catch?block
????????????e.printStackTrace();
????????}
????????
????}
????????try?{
????????????Object?obj=Class.forName("com.spring.UpperAction").newInstance();
????????????BeanWrapper?bw=new?BeanWrapperImpl(obj);
????????????bw.setPropertyValue("message","peidw");
????????????System.out.println(bw.getPropertyValue("message"));
????????}?catch?(InstantiationException?e)?{
????????????//?TODO?Auto-generated?catch?block
????????????e.printStackTrace();
????????}?catch?(IllegalAccessException?e)?{
????????????//?TODO?Auto-generated?catch?block
????????????e.printStackTrace();
????????}?catch?(ClassNotFoundException?e)?{
????????????//?TODO?Auto-generated?catch?block
????????????e.printStackTrace();
????????}
????????
????}
2、Bean Factory
????? BeanFactory負(fù)責(zé)根據(jù)配置配置文件創(chuàng)建Bean實(shí)例,可以配置的項(xiàng)目有:
????? 1 、Bean屬性值及依賴關(guān)系
????? 2、Bean創(chuàng)建模式(是否單態(tài)模式)
????? 3、Bean初始化及銷毀
????? 4、Bean的依賴關(guān)系
<beans>
<description>Spring?Bean?Configuration?Sample</description>
<bean
id="TheAction"?⑴
class="net.xiaxin.spring.qs.UpperAction"?⑵
singleton="true"?⑶
init-method="init"?⑷
destroy-method="cleanup"?⑸
depends-on="ActionManager"?⑹
>
<property?name="message">
<value>HeLLo</value>?⑺
</property>
<property?name="desc">
<null/>
</property>
<property?name="dataSource">
<ref?local="dataSource"/>?⑻
</property>
</bean>
<bean?id="dataSource"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property?name="jndiName">
<value>java:comp/env/jdbc/sample</value>
</property>
</bean>
這是一個(gè)比較完整的Bean配置,id表示一個(gè)類在BeanFactory中的唯一標(biāo)識(shí)<description>Spring?Bean?Configuration?Sample</description>
<bean
id="TheAction"?⑴
class="net.xiaxin.spring.qs.UpperAction"?⑵
singleton="true"?⑶
init-method="init"?⑷
destroy-method="cleanup"?⑸
depends-on="ActionManager"?⑹
>
<property?name="message">
<value>HeLLo</value>?⑺
</property>
<property?name="desc">
<null/>
</property>
<property?name="dataSource">
<ref?local="dataSource"/>?⑻
</property>
</bean>
<bean?id="dataSource"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property?name="jndiName">
<value>java:comp/env/jdbc/sample</value>
</property>
</bean>
class 是java類名,singleton 為true表示使用單態(tài),init-method初始化方法在BeanFactory創(chuàng)建Bean后執(zhí)行的初始化方法。destroy-method銷毀方法,在bean銷毀時(shí)執(zhí)行,一般用于資源釋放。depends-on? Bean的依懶關(guān)系。<value>節(jié)點(diǎn)用于指定一個(gè)屬性值,ref節(jié)點(diǎn)用于引用另一個(gè)bean的屬性。
?????? 聯(lián)合上面關(guān)于BeanWrapper的內(nèi)容,我們可以看到,BeanWrapper實(shí)現(xiàn)了針對(duì)單個(gè)Bean的屬性設(shè)定操作。而BeanFactory則是針對(duì)多個(gè)Bean的管理容器,根據(jù)給定的配置文件,BeanFactory從中讀取類名、屬性名/值,然后通過Reflection機(jī)制進(jìn)行Bean加載和屬性設(shè)定。
3、ApplicationContext
BeanFactory提供了針對(duì)Java Bean的管理功能,而ApplicationContext提供了一個(gè)更為框架化的
實(shí)現(xiàn)(從上面的示例中可以看出,BeanFactory的使用方式更加類似一個(gè)API,而非Framework style)。
ApplicationContext覆蓋了BeanFactory的所有功能,并提供了更多的特性。此外,
ApplicationContext為與現(xiàn)有應(yīng)用框架相整合,提供了更為開放式的實(shí)現(xiàn)(如對(duì)于Web應(yīng)用,我們可以在
web.xml中對(duì)ApplicationContext進(jìn)行配置)。
相對(duì)BeanFactory而言,ApplicationContext提供了以下擴(kuò)展功能:
1. 國際化支持
我們可以在Beans.xml文件中,對(duì)程序中的語言信息(如提示信息)進(jìn)行定義,將程序中的提示
信息抽取到配置文件中加以定義,為我們進(jìn)行應(yīng)用的各語言版本轉(zhuǎn)換提供了極大的靈活性。
2. 資源訪問
支持對(duì)文件和URL的訪問。
3. 事件傳播
事件傳播特性為系統(tǒng)中狀態(tài)改變時(shí)的檢測(cè)提供了良好支持。
4. 多實(shí)例加載
可以在同一個(gè)應(yīng)用中加載多個(gè)Context實(shí)例。
一個(gè)國際化支持例子
public?static?void?testLanguage(){
????????ApplicationContext?ac=new?FileSystemXmlApplicationContext("src/bean.xml");
????????Object[]?arg=new?Object[]{"kkui",Calendar.getInstance().getTime()};
????????//以系統(tǒng)默認(rèn)的Locale加載信息(對(duì)winxp而言默認(rèn)的是zh_CN)
????????String?zhmsg=ac.getMessage("userinfo",arg,?Locale.CHINA);
????????String?usmsg=ac.getMessage("userinfo",arg,?Locale.US);
????????System.out.println(zhmsg);
????????System.out.println(usmsg);
????}
需要在beans.xml文件配置使用多資源????????ApplicationContext?ac=new?FileSystemXmlApplicationContext("src/bean.xml");
????????Object[]?arg=new?Object[]{"kkui",Calendar.getInstance().getTime()};
????????//以系統(tǒng)默認(rèn)的Locale加載信息(對(duì)winxp而言默認(rèn)的是zh_CN)
????????String?zhmsg=ac.getMessage("userinfo",arg,?Locale.CHINA);
????????String?usmsg=ac.getMessage("userinfo",arg,?Locale.US);
????????System.out.println(zhmsg);
????????System.out.println(usmsg);
????}
????<bean?id="messageSource"?class="org.springframework.context.support.ResourceBundleMessageSource">
????????<property?name="basenames">
????????????<list>
????????????????<value>messages</value>
????????????</list>
????????</property>
????</bean>
這里聲明了一個(gè)名為messageSource的Bean(注意對(duì)于Message定義,Bean ID必須為????????<property?name="basenames">
????????????<list>
????????????????<value>messages</value>
????????????</list>
????????</property>
????</bean>
messageSource,這是目前Spring的編碼規(guī)約),對(duì)應(yīng)類為ResourceBundleMessageSource,
目前Spring中提供了兩個(gè)MessageSource接口的實(shí)現(xiàn),即
ResourceBundleMessageSource和ReloadableResourceBundleMessageSource,后
者提供了無需重啟即可重新加載配置信息的特性。
資源文件message_zh.properties
userinfo=登陸用戶:[{0}]?登陸時(shí)間[{1}]
國際化支持在實(shí)際開發(fā)中可能是最常用的特性。對(duì)于一個(gè)需要支持不同語言環(huán)境的應(yīng)用而言,我們所采取的最常用的策略一般是通過一個(gè)獨(dú)立的資源文件(如一個(gè)properties文件)完成所有語言信息(如界面上的提示信息)的配置,Spring對(duì)這種傳統(tǒng)的方式進(jìn)行了封裝,并提供了更加強(qiáng)大的功能.
資源訪問例子
Resource?rs?=?ctx.getResource("classpath:config.properties");
File?file?=?rs.getFile();
事件傳播機(jī)制例子File?file?=?rs.getFile();
ApplicationContext基于Observer模式(java.util包中有對(duì)應(yīng)實(shí)現(xiàn)),提供了針對(duì)Bean的事件傳播功能。通過Application. publishEvent方法,我們可以將事件通知系統(tǒng)內(nèi)所有的ApplicationListener。下面是一個(gè)例子:
package?com.spring;
import?org.springframework.beans.BeansException;
import?org.springframework.context.ApplicationContext;
import?org.springframework.context.ApplicationContextAware;
import?org.springframework.context.ApplicationEvent;
public?class?LoginAction?implements?ApplicationContextAware{
????private?ApplicationContext?ac;
????public?void?setApplicationContext(ApplicationContext?arg0)?throws?BeansException?{
????????//?TODO?Auto-generated?method?stub
????????this.ac=arg0;
????}
????public?int?login(String?username,String?password){
????????ActionEvent?ae=new?ActionEvent(username);
????????this.ac.publishEvent(ae);
????????return?0;
????}
????
}
import?org.springframework.beans.BeansException;
import?org.springframework.context.ApplicationContext;
import?org.springframework.context.ApplicationContextAware;
import?org.springframework.context.ApplicationEvent;
public?class?LoginAction?implements?ApplicationContextAware{
????private?ApplicationContext?ac;
????public?void?setApplicationContext(ApplicationContext?arg0)?throws?BeansException?{
????????//?TODO?Auto-generated?method?stub
????????this.ac=arg0;
????}
????public?int?login(String?username,String?password){
????????ActionEvent?ae=new?ActionEvent(username);
????????this.ac.publishEvent(ae);
????????return?0;
????}
????
}
package?com.spring;
import?org.springframework.context.ApplicationEvent;
public?class?ActionEvent?extends?ApplicationEvent?{
????public?ActionEvent(Object?source)?{
????????super(source);
????}
}
import?org.springframework.context.ApplicationEvent;
public?class?ActionEvent?extends?ApplicationEvent?{
????public?ActionEvent(Object?source)?{
????????super(source);
????}
}
package?com.spring;
import?org.springframework.context.ApplicationEvent;
import?org.springframework.context.ApplicationListener;
public?class?ActionListener?implements?ApplicationListener{
????public?void?onApplicationEvent(ApplicationEvent?event)?{
????????if(event?instanceof?ActionEvent){
????????????System.out.println(event.toString());
????????}
????????
????}
????
}
需要在beans.xml文件里添加以下配置import?org.springframework.context.ApplicationEvent;
import?org.springframework.context.ApplicationListener;
public?class?ActionListener?implements?ApplicationListener{
????public?void?onApplicationEvent(ApplicationEvent?event)?{
????????if(event?instanceof?ActionEvent){
????????????System.out.println(event.toString());
????????}
????????
????}
????
}
<bean?id="loginaction"?class="net.xiaxin.beans.LoginAction"/>
<bean?id="listener"?class="net.xiaxin.beans.ActionListener"/>
測(cè)試方法:<bean?id="listener"?class="net.xiaxin.beans.ActionListener"/>
????public?static?void?testListener(){
????????ApplicationContext?ac=new?FileSystemXmlApplicationContext("src/bean.xml");
????????LoginAction?la=(LoginAction)ac.getBean("loginaction");
????????la.login("peidw",?"123456");
????}
Struts in Spring????????ApplicationContext?ac=new?FileSystemXmlApplicationContext("src/bean.xml");
????????LoginAction?la=(LoginAction)ac.getBean("loginaction");
????????la.login("peidw",?"123456");
????}
Struts和Spring是如何整合,為了在struts加加載Spring Context;在struts-config.xml文件中添加以下配置
<struts-config>
<plug-in
className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property?property="contextConfigLocation"
value="/WEB-INF/applicationContext.xml"?/>
</plug-in>
</struts-config>
通過plug-in我們實(shí)現(xiàn)了Spring Context的加載,不過僅僅加載Context并沒有什么實(shí)際意義,我們還需要修改配置,將Struts Action交給Spring容器進(jìn)行管理:<plug-in
className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property?property="contextConfigLocation"
value="/WEB-INF/applicationContext.xml"?/>
</plug-in>
</struts-config>