javascript
Spring实战(前言:Spring容器)
Spring容器,顧名思義是用來容納東西的,裝的就是Bean。Spring容器負(fù)責(zé)創(chuàng)建、配置、管理Bean。spring容器有兩個(gè)核心接口:BeanFactory和ApplicationContext接口,后者是前者的子接口。在基于spring的Java EE程序中,所有的組件都被當(dāng)成Bean來處理,包括數(shù)據(jù)源對(duì)象、hibernate的sessionFactory、事務(wù)管理等,程序中的所有Java類都可以被當(dāng)成spring容器中的bean。
1、spring容器
spring容器的核心接口是BeanFactory,它有一個(gè)子接口就是ApplicationContext。ApplicationContext也被稱為spring上下文。
調(diào)用者只需要使用getBean()方法即可獲得指定bean的引用。對(duì)于大部分的Java程序而言,使用ApplicationContext作為spring容易更為方便。其常用的實(shí)現(xiàn)類有FileSystemXmlApplicationContext、ClassPathXmlApplicationContext和AnnotationConfigXmlApplicationContext。如果Java web中使用spring容器,則通常有XmlWebApplicationContext、AnnotationConfigWebApplicationContext兩個(gè)容器。
創(chuàng)建spring容器的實(shí)例時(shí),必須提供spring容器管理的bean的配置文件,也就是我們常說的spring.xml配置文件。因此在創(chuàng)建beanFactory時(shí)配置文件作為參數(shù)傳入。xml配置文件一般以resource對(duì)象傳入。resource是spring提供的資源訪問接口,通過該接口spring更簡(jiǎn)單、透明的訪問磁盤,網(wǎng)絡(luò)系統(tǒng)和類路徑上的相關(guān)資源。
對(duì)于獨(dú)立的Java EE應(yīng)用程序,可以通過如下方法來實(shí)例化BeanFactory。
//在當(dāng)前項(xiàng)目類路徑下搜索配置文件
ApplicationContext appContext = new ClassPathXmlApplicationContext("beans_7_3_3.xml");
//在文件系統(tǒng)搜索配置文件
appContext = new FileSystemXmlApplicationContext("D:\\spring-tool-workspace\\myspring\\src\\beans_7_3_3.xml");
//獲取chinese的Bean,并且返回的類型為Chinese
Person chinese = appContext.getBean("chinese", Chinese.class);
chinese.useAxe();
2、使用ApplicationContext
大部分時(shí)間,都不會(huì)使用beanFactory實(shí)例作為spring容器,而是使用ApplicationContext作為spring容器,因此spring容器也被稱為spring上下文。ApplicationContext增強(qiáng)了beanFactory的功能,提供了很多有用、方便開發(fā)的功能。
在web中可以利用如contextLoader的支持類,在web應(yīng)用啟動(dòng)的時(shí)候自動(dòng)創(chuàng)建ApplicationContext。
除了提供beanFactory所支持的全部功能外,application還額外的提供如下功能:
① ApplicationContext會(huì)默認(rèn)初始化所有的singleton bean(單例bean),也可以通過配置取消。
② ApplicationContext繼承了messageSource接口,因此提供國(guó)際化支持。
③ 資源訪問,比如URL和文件。
④ 事件機(jī)制。
⑤ 同時(shí)加載多個(gè)配置文件。
⑥ 以聲明式方式啟動(dòng)并創(chuàng)建spring容器。
ApplicationContext包括beanFactory的所有功能,并提供了一些額外的功能,優(yōu)先使用ApplicationContext。對(duì)于在內(nèi)存消耗的才使用beanFactory。
當(dāng)系統(tǒng)創(chuàng)建ApplicationContext容器時(shí),會(huì)默認(rèn)初始化singleton bean,包括調(diào)用構(gòu)造器創(chuàng)建該bean的實(shí)例,通過元素驅(qū)動(dòng)spring調(diào)用setting方法注入所依賴的對(duì)象。這就意味著,系統(tǒng)前期創(chuàng)建ApplicationContext會(huì)有很大的開銷,但是一旦初始化完成后面獲取bean實(shí)例就會(huì)擁有較好的性能。為了阻止在使用ApplicationContext作為spring容器初始化singleton bean可以在元素添加lazy-init="true"屬性。
3、ApplicationContext的國(guó)際化支持
ApplicationContext接口繼承了MessageSource接口,因此具備國(guó)際化功能。
//MessageSource接口提供的國(guó)際化的兩個(gè)方法
String getMessage(String code, Object [] args, Locale loc){
}
String getMessage(String code, Object[]args, String default, Locale loc){
}
spring國(guó)際化的支持,其實(shí)是建立在Java國(guó)際化的基礎(chǔ)上的。其核心思路將程序中需要國(guó)際化的消息寫入資源文件,而代碼中僅僅使用國(guó)際化信息響應(yīng)的key。
4、ApplicationContext的事件機(jī)制
ApplicationContext的事件機(jī)制是觀察者設(shè)計(jì)模式的實(shí)現(xiàn)。通過ApplicationEvent和ApplicationListener接口實(shí)現(xiàn),前者是被觀察者,后者是觀察者。
spring事件框架有兩個(gè)核心的接口:
ApplicationEvent(事件):必須由ApplicationContext來發(fā)布。
ApplicationListener(監(jiān)聽器):實(shí)現(xiàn)了此接口就可以擔(dān)任容器中的監(jiān)聽器bean。
實(shí)際上,spring的事件機(jī)制是由事件(實(shí)現(xiàn)ApplicationEvent接口的類)、事件源(也就是spring容器,并且有Java代碼顯示的觸發(fā))、監(jiān)聽器(ApplicationListener接口實(shí)現(xiàn)類)。這就像我們?cè)陧?yè)面點(diǎn)擊一個(gè)button。button是事件源,單機(jī)的這個(gè)動(dòng)作就是事件,處理函數(shù)就是監(jiān)聽器。
以下代碼演示spring事件機(jī)制:
import org.springframework.context.ApplicationEvent;
public class EmailEvent extends ApplicationEvent{
private String address;
private String text;
public EmailEvent(Object source) {
super(source);
}
public EmailEvent(Object source, String address, String text) {
super(source);
this.address = address;
this.text = text;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
http://www.senta7.net/content/?729.html
public String getText(www.yacuangyl.com) {
return text;
}
public void setText(String text) {
this.text = text;
}
}
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class EmailNotifier implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
//處理email事件
if(event instanceof www.xcdeyiju.com EmailEvent){
EmailEvent email = (EmailEvent) event;
System.out.println(email.getAddress()+" "+email.getText());
}else {
//輸出spring容器的內(nèi)置事件
System.out.println("其它事件:"+event);
}
}
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans_7_4_4.xml");
EmailEvent emailEvent = applicationContext.getBean("emailEvent",EmailEvent.class);
applicationContext.publishEvent(emailEvent);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.jujinyule.com .org/schema/beans"
xmlns:xsi="http://www.yuchengyulegw.com 2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.hnawesm.com org/schema/beans/spring-beans.xsd">
<bean class="EmailNotifier"></bean>
<bean id="emailEvent" class="EmailEvent">
<constructor-arg value="test"></constructor-arg>
<constructor-arg value="123@qq.com"></constructor-arg>
<constructor-arg value="this is a test">www.seocelve.com</constructor-arg>
</bean>
</beans>
從上面的代碼可以看出,事件監(jiān)聽器不僅監(jiān)聽到了我們程序顯示觸發(fā)的事件,還監(jiān)聽了spring容器內(nèi)置的事件。如果實(shí)際開發(fā)需要,我們可以在spring容器初始化或銷毀時(shí)回調(diào)自定義方法,就可以通過上面的事件監(jiān)聽機(jī)制來完成。
spring提供了如下幾個(gè)內(nèi)置對(duì)象:
ContextRefreshedEvent、ContextStartedEvent、ContextClosedEvent、ContextStoppedEvent、RequestHandledEvent。
5、讓bean獲取spring容器
上面都是通過ApplicationContext創(chuàng)建spring容器,再調(diào)用spring容器的getBean()方法獲取bean。這種情況下,程序總是持有spring容器的引用。但是在web應(yīng)用中,我們可以用聲明式的方法來創(chuàng)建spring容器:在web.xml文件中配置一個(gè)監(jiān)聽,讓這個(gè)監(jiān)聽類幫我們來創(chuàng)建spring容器,前端MVC框架直接調(diào)用bean,使用依賴注入功能,無需訪問spring容器本身。
在某些特殊情況下,bean需要實(shí)現(xiàn)某個(gè)功能(比如:bean需要輸出國(guó)際化信息,或向spring容器發(fā)布事件),這些功能都需要借助spring容器來完成。就是說我們需要將spring容器作為一個(gè)bean來注入到其它bean中,只不過spring容器bean是一個(gè)容器級(jí)別的bean。
為了讓bean獲取它所在容器的引用,可以讓bean實(shí)現(xiàn)beanFactoryAware接口。該接口只有一個(gè)方法setBeanFactory(BeanFactory beanFactory)方法,方法的beanFactory參數(shù)指向spring容器,會(huì)由spring容器注入。我們bean中定義一個(gè)setter方法后,通常都是由在配置文件中配置元素來驅(qū)動(dòng)spring容器來注入依賴bean的,但是這里我們并沒有這樣做,這是因?yàn)橐粋€(gè)bean如果實(shí)現(xiàn)了beanFactory接口,spring在創(chuàng)建該bean時(shí),會(huì)自動(dòng)注入spring容器本身。與beanFactoryAware接口類似的還有BeanNameAware、ResourceLoaderAware接口,這些接口都會(huì)提供類似的setter方法,這些方法會(huì)由spring容器來注入。
下面我們來演示一個(gè)示例,這個(gè)示例中的Person類中的sayHi()方法將輸出國(guó)際化消息,這就需要Person獲取Spring容器,借助Spring容器來完成國(guó)際化。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="messagSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>messages/message</value>
</list>
</property>
</bean>
<bean id="person" class="com.container.Person">
</bean>
</beans>
package com.container;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Locale;
public class Person implements ApplicationContextAware{
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public void sayHello(String name){
Locale locale = Locale.getDefault(Locale.Category.FORMAT);
String myName = applicationContext.getMessage("name",new String[]{name},Locale.US);
System.out.println(myName);
}
public static void main(String[] args) {
System.out.println(Person.class.getClassLoader().getResource(".").getPath());
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans_7_4_5.xml");
Person p = applicationContext.getBean("person",Person.class);
p.sayHello("江疏影");
}
}
message_zh_CN.properties國(guó)際化資源文件
name=CH \u4F60\u597D,{0}
message_en_US.properties國(guó)際化資源文件
轉(zhuǎn)載于:https://www.cnblogs.com/qwangxiao/p/11325322.html
總結(jié)
以上是生活随笔為你收集整理的Spring实战(前言:Spring容器)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android IPC系列(一):AID
- 下一篇: 一台电脑同时添加git和bitbucke