Spring的AbstractApplicationContext是ApplicationContext的抽象實現類,該抽象類的refresh()方法定義了Spring容器在加載配置文件後的各項處理過程這些處理過程清晰的刻畫了Spring容器啓動時所執行的各項操做。java
synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); //1.初始化BeanFactory:根據配置文件實例化BeanFactory,在obtainFreshBeanFactory()方法中, //首先調用refreshBeanFactory()刷新BeanFactory,而後調用getBeanFactory()獲取BeanFactory, //這兩個方法都是由具體子類實現的。在這一步,Spring將配置i文件信息裝入容器的Bean定義註冊表( //BeanDefinitionRegistry)中,但此時Bean還未初始化。 // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); //2.調用工廠後處理器:根據反射機制從BeanDefinitionRegistry中找出全部實現了 //BeanFactoryPostProcessor接口Bean,而且調用其postProcessBeanFactory()接口方法。 // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); //3.註冊Bean後處理器:根據反射機制從BeanRegistry中找出全部實現了BeanPostProcessor接口的 //的Bean,而且將它們註冊到容器Bean後處理器的註冊表中。 // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); //4.初始化消息源:初始化容器的國際化消息資源。 // Initialize message source for this context. initMessageSource(); //5.初始化應用上下文事件廣播器 // Initialize event multicaster for this context. initApplicationEventMulticaster(); //6.初始化其餘特殊的Bean:這是一個鉤子方法,子類能夠藉助這個方法執行一些特殊的操做,如 //AbstractRefreshableWebApplicationContext就使用該方法執行初始化ThemeSource的操做 // Initialize other special beans in specific context subclasses. onRefresh(); //7.註冊事件監聽 // Check for listener beans and register them. registerListeners(); //8.初始化全部單實例的Bean,使用懶加載模式的Bean除外:初始化Bean以後將它們放入Spring容器的 緩衝池。 // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); //9.完成刷新併發布容器刷新事件:建立上下文刷新時間,時間廣播器負責將這些時間廣播到每一個註冊的 //時間監聽器中 // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } }
1.ResourceLoader從存儲介質加載Spring配置信息,並使用Resource表示這個配置文件資源。 2.BeanDefinitionReader讀取Resource所指向的配置文件資源,而後解析配置我呢見。配置文件中的每一個<bean>解析成一個BeanDefinition對象,並保存到BeanDefinitionRegistry中。 3.容器掃描BeanDefinitionRegistry中的BeanDefinition,使用Java反射機制自動識別出Bean工廠的後處理器(實現BeanFactoryPostProcessor接口的Bean),而後調用這些Bean工廠後處理器對BeanDefinitionRegistry中的BeanDefinition進行加工處理。主要完成如下兩項工做。 1. 對使用佔位符的<bean>元素進行解析,獲得最終的配置值。這意味着對一些半成品式的BeanDefinition對象進行架構處理並獲得成品的BeanDefinition對象。 2.對BeanDefinitionRegistry中的BeanDefinition進行掃描,經過Java反射機制找出全部屬性編輯器的Bean(實現了java.beans.PropertyEditor接口的Bean),並自動將它們註冊到Spring容器的屬性編輯器註冊表中(org.springframework.beans.PropertyEditorRegistry). 4.Spring容器從BeanDefinitionRegistry中取出後加工後的BeanDefinition,並調用InstantiationStrategy着手進行Bean實例化的工做。 5.實例化Bean時,Spring容器使用BeanWrapper對Bean進行封裝,BeanWrapper提供了不少以Java反射機制操做Bean的方法,它將結合Bean的Definition及容器中的屬性編輯器,完成屬性注入工做。 6.利用容器註冊的Bean進行後處理器(實現BeanPostProcessor接口的Bean)對已經完成屬性設置工做的Bean進行後續的加工,直接裝配出一個準備就緒的Bean.
物料組件:Resource,BeanDefinition,PropertyEditor及最終的Bean等,它們時加工流程被加工,被消費的組建,就像流水線上被加工的物料同樣。 設備組件:ResourceLoader,BeanDefinitonReader,BeanFactoryPostProcessor,InstantiationStrategy及BeanWrapper等。它們就像流水線上不一樣環節的設備加工設置,對物料組建進行加工處理。
org.springframework.beans.factory.config.BeanDefinition是配置文件<bean></bean>元素標籤在容器中的內部表示。<bean></bean>元素標籤用於class,scope,lazy-init等配置屬性,BeanDefinition則提供了相應的beanClass,scope,lazyInit類屬性,BeanDefinition就像<bean></bean>的鏡像。mysql
BeanDefinition類的集成結構以下:spring
RootBeanDefinition是最經常使用的實現類,它對應通常性的<bean></bean>元素標籤。配置文件能夠定義父子bean,父bean使用RootBeanDefinition,子Bean使用ChildBeanDefinition表示,而沒有父bean就默認使用RootBeanDefinition表示。 AbstractBeanDefinition對兩者共同的類信息進行抽象。sql
BeanDefinition是對配置文件中的<bean></bean>進行表示,最終將BeanDefinition會被存儲在Spring的內存數據庫BeanDefinitionRegistry中,後續的操做直接從這個數據庫中直接獲取,BeanDefinition只在容器啓動時加載並解析,除非容器刷新或者重啓,這些信息不會發生變化。數據庫
org.springframework.beans.factory.support.InstantiationStrategy負責根據BeanDefinition對象建立一個Besan實例。Spring之因此將實例化Ban共工做經過一個策略接口進行描述,是爲了能夠方便的採用不一樣的實例化策略,以知足不太的應用需求,如經過CGLib類庫爲Bean動態建立子類再進行實例化,InstantiationStrategy類的繼承結構以下: 1.SimpleInstantiationStrategy是最經常使用的實例化策略,該策略理由Bean實現類的默認構造函數,帶參構造函數或工廠方法建立Bean的實例。apache
2.CglibSubclassingInstantiationStrategy拓展了SimpleInstantiationStrategy,爲須要進行方法注入的Bean提供了支持,而後使用這個動態生成的子類建立bean的實例。數組
InstantiationStrategy僅負責實例化Bean的操做,至關於執行Java語言的new操做,它只負責實例化Bean,沒有涉及任何的屬性設置,實際上獲得的是一個半成品的Bean,屬性操做交給BeanWrapper架構
屬性的設置由BeanWrapper這個代理器完成,InstantiationStratedy建立出Bean實例以後,BeanWrapper來完成屬性填充的工做,容器主控程序將Bean實例經過BeanWrapper包裝起來,這是經過調用BeanWrapper#setWrappedInstance(Object obj)方阿飛完成的。BeanWrapper類的繼承結構以下: 併發
PropertyAccessor和PropertyEditorRegistry是BeanWrapper的兩個頂級接口,PropertyAccessor定義了各類訪問Bean屬性的接口,如setPropertyValue(String,Object),setPropertyValues(PropertyValue pvs)等;而PropertyEditorRegistry是屬性編輯器的註冊表.BeanWrapper實現類BeanWrapperImpl做用: 1.Bean包裹器 2.屬性訪問器 3.屬性編輯器註冊表app
一個BeanWrapperImpl實例內部封裝了兩類組件:1.被封裝的待處理的Bean,以及一套用於設置Bean屬性的屬性編輯器。 屬性的注入須要從BeanDefinitionRegistry中獲取到BeanDefinition,而後Spring的主控程序從BeanDefinition中獲取Bean的屬性的配置信息PropertyValue,而且使用屬性編輯器對PropertyValue進行裝換以獲得Bean的屬性值。BeanWrapper內部使用了Spring的BeanUtils工具類對Bean進行反射曹祖哦,設置屬性。
Sun所制定的JavaBean規範很大程度上是爲IDE準備的——它讓IDE可以以可視化的方式設置avaBean的屬性,若是在IDE中開發一個可視化的應用程序,則須要經過屬性設置的方式對組成的各類組件進行定製,IDE經過屬性屬性編輯器讓開發人員使用可視化的方式設置組件的屬性。
IDE都支持JavaBean規範所定義的屬性編輯器,當組件開發商發佈一個組件時,它每每將組件對應的屬性編輯器捆綁發行,這樣開發者就能夠在IDE環境下方便地利用屬性編輯器對組件進行定製工做。
JavaBean規範經過java.beans.PropertyEditor定義了設置JavaBean屬性地方法,經過BeanInfo描述了JavaBean描述了JavaBean的哪些屬性是能夠定製的,此外描述了可定製屬性與PropertyEditor的對應關係。
BeanInfo與JavaBean之間的的對應關係經過兩者之間的命名的規範確立。對應JavaBean的BeanInfo採用以下的命名規範:<Bean>BeanInfo.例如ChartBean對應的BeanInfo爲ChartBeanInfo.當JavaBean連同其屬性編輯器以通註冊到IDE中後,在開發界面中對JavaBean進行定製時,IDE就會根據JavaBean規範找到對應的BeanInfo,再根據BeanInfo的描述信息找到BeanInfo中描述西悉尼找到JavaBean屬性描述(是否開發,使用那個屬性編輯器),進而爲JavaBean生成特定的開發編輯界面.
JavaBean規範提供了一個管理默認屬性編輯器的管理器PropertyEditorManager,該管理器內保存者一些常見的類型的屬性編輯器。若是某個JavaBean的常見屬性沒有經過BeanInfo顯式地指定屬性編輯器,那麼IDE將自動使用PropertyEditorManager中註冊地對應默認地屬性編輯器。
PropertyEditor是屬性編輯器地接口,規範了將外部地設置值轉換爲內部的JavaBean屬性值的轉換接口方法,PropertyEditor主要的接口方法: 1.getValue():返回屬性的當前值,基本類型被封裝成對應的封裝類實例。 2.setValue(Object value):設置屬性值,基本類型以瘋傳類傳入
3.String getAsText():將屬性對象用字符串表示,以便外部的屬性編輯器能以可視化的方式顯示。默認的返回null,表示該屬性不能以字符串表示。 4.void setAsText(String text):用一個屬性去更新屬性的內部值,這個字符串通常從外部屬性扁你機器傳入。 5.String[] getTags():返回不鳥事有效屬性值的字符串數組(如boolean對應的由效Tag爲true和false),以便屬性編輯器能如下拉框方式顯示出來。默認返回null,表示屬性沒有匹配的字符候選值有些集合。 6.String getJavaInitializationString():爲屬性提供一個表示初始值得字符串,屬性編輯器以此值做爲屬性得默認值。
PropertyEditor接口方法是內部屬性值和外部屬性值得溝通橋樑,是專門爲IDE中得可視化屬性編輯器提供得。
BeanInfo主要描述了JavaBean的哪些屬性能夠編輯對應的屬性編輯器,每一個屬性對應一個屬性描述器PropertyDescriptor。構造函數public PropertyDescriptor(String propertyName, Class<?> beanClass),其中propertyName:屬性名,beanClass:javaBean對應的class。此外PropertyDescriptor還有一個方法 public void setPropertyEditorClass(Class<?> propertyEditorClass)方法,用於爲JavaBean屬性指定編輯器。BeanInfo接口最重要的方法就是PropertyDescriptor[] getPropertyDescriptors(),該方法返回JavaBean的屬性描述器數組。 BeanInfo接口的一個經常使用實現類是SimpleBeanInfo,通常狀況下,能夠經過拓張SimpleBeanInfo實現本身的功能。
Spring的屬性編輯器和傳統用於IDE開發的屬性編輯器不一樣,它沒有UI界面,僅負責將配置文件中的文件配置值轉換爲Bean屬性的對應值,因此Spring的屬性編輯器並不是傳統意義上的JavaBean屬性編輯器。 Spring爲常見的屬性累提供了默認的屬性編輯器。BeanWrapperImpl類拓展了PropertyEditorRegistrySupport類,Spring在PropertyEditorRegistrySupport中爲常見屬性類型提供了默認的屬性編輯器。
PropertyEditorRegistrySupport有兩個變量 Map<Class<?>, PropertyEditor> defaultEditors:用於保存默認屬性類型的編輯器,元素的鍵爲類的屬性類型,值爲對應的屬性編輯器實例。 Map<Class<?>, PropertyEditor> customEditors:用於保存用戶自定義的屬性編輯器,元素的鍵值和defaultEditors相同。 ![](htt ps://oscimg.oschina.net/oscnet/fead06d498367e6b6b83997e312b3df412b.jpg)
這些默認的屬性編輯器用於解決常見的屬性類型的是註冊問題。若是用戶的應用包括一些特殊的類型的屬性的話,並且但願配置文件中以字面值提供配置,那麼就須要編寫自定義屬性編輯器註冊到Spring容器中。這樣,Spring才能將配置文件中的配置屬性配置值轉換爲對應的屬性類型值。
Spring的帶份默認屬性編輯機器都直接拓展於java.beans.PropertyEditorSupport類,開發者也能夠經過拓展PropertyEditorSupport實現本身的屬性編輯器。相對於用於IDE環境的屬性百年機器來講,Spring環境下使用的屬性編輯器的功能比較單一,僅須要將配置文件中的字面值轉換爲屬性類型的對象便可,並不須要提供UI界面,所以須要簡單覆蓋PropertyEditorSupport的setAsText()便可。
例子: 1.Boss.java
public class Boss { private String name; private Car car = new Car(); public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } public String getName() { return name; } public void setName(String name) { this.name = name; } [@Override](https://my.oschina.net/u/1162528) public String toString() { return "Boss{" + "name='" + name + '\'' + ", car=" + car + '}'; } }
Car.java
public class Car { private int maxSpeed; public String brand; private double price; public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public int getMaxSpeed() { return maxSpeed; } public void setMaxSpeed(int maxSpeed) { this.maxSpeed = maxSpeed; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public String toString(){ return "brand:"+brand+"/maxSpeed:"+maxSpeed+"/price:"+price; } }
自定義屬性編輯器CustomerCarEditor.java
public class CustomerCarEditor extends PropertyEditorSupport { //將字面值轉換爲屬性類型對象 [@Override](https://my.oschina.net/u/1162528) public void setAsText(String text) throws IllegalArgumentException { if (StringUtils.isEmpty(text)||text.indexOf(",")==-1){ throw new IllegalArgumentException("設置的字符串格式不正確"); } String[] infos = text.split(","); Car car = new Car(); car.setBrand(infos[0]); car.setMaxSpeed(Integer.valueOf(infos[1])); car.setPrice(Double.valueOf(infos[2])); //調用父類得setValue()方法設置轉換後得屬性對象 setValue(car); } }
beans.xml配置文件:
<?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-4.0.xsd"> <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <entry key="com.flexible.editor.editorbean.Car" value="com.flexible.editor.editorbean.CustomerCarEditor"/> </map> </property> </bean> <bean id="boss" class="com.flexible.editor.editorbean.Boss"> <property name="name" value="John"/> <property name="car" value="紅旗CA72,200,20000.00"/> </bean> </beans>
測試代碼:
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:editor/beans"); Boss boss = (Boss) context.getBean("boss"); System.out.println(boss.toString());
執行結果:
Boss{name='John', car=brand:紅旗CA72/maxSpeed:200/price:20000.0}
PropertyPlaceholderConfigurer可以使Bean在配置時引用外部屬性文件。PropertyPlaceholderConfigurer實現了BeanFactoryPostProcessorBean接口。
jdbc.properties
dbName=sampledb driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/${dbName} #userName=root #password=123456 userName=WnplV/ietfQ= password=QAHlVoUc49w=
beans.xml
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!--引入jdbc.properties屬性文件--> <bean class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer" p:location="classpath:placeholder/jdbc.properties" p:fileEncoding="utf-8"> </bean> <!----> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="${driverClassName}" p:url="${url}" p:username="${userName}" p:password="${password}" ></bean> </beans>
propertyPlaceholderConfigurer的其餘屬性 1.locations:若是隻有一個屬性文件,直接使用location指定就能夠,若是有多個屬性文件,則能夠經過locations屬性進行設置。能夠像配置List同樣配置locations屬性。
2.fileEncoding:屬性文件的編碼格式。Spring使用了操做系統默認的編碼戈斯和,若是採用了特殊的編碼格式須要經過該屬性顯式指定。
3.order:若是配置i文化你中定義了多個PropertyPlaceholderConfigurer,則經過該屬性指定有限順序
4.placeholderPrefix:在上面的例子中,可能夠經過${屬性名}引用屬性文件中的屬性項,其中"${爲佔位符前綴","}"是暫未付後綴
可使用<context:property-placeholder location="classpath:placeholder/jdbc.properties"></context:property-placeholder>引入屬性文件,可是若是須要一些高級功能(加密)
基於註解及基於Java類的配置中引用屬性
爲每種語言提供一套相應的資源文件俺,並以規範化的命名的方式保存在特定的目錄中,由系統自動根據客戶端語言選擇合適的資源文件。"國際化信息"也成爲"本地化信息",通常須要兩個條件才能夠肯定,Java經過java.util.Local類白哦是一個本地化對象,它容許經過語言參數和國家/地區參數建立以一個肯定的本地化對象。 例如: public class LocalUtils {
public static Locale myLocal(){ //帶有語言和國家/地區的本地化對象 Locale local = new Locale("zh","CN"); //只有語言信息的本地化對象。 Locale locale2 = new Locale("zh"); //等同於Locale("zh","CN") Locale locale3 = Locale.CHINA; //等同於Locale("zh") Locale locale4 = Locale.CHINESE; //獲取本地系統默認的本地化對象 Locale locale5 = Locale.getDefault(); return locale5; } }
注意: 在測試的時候若是須要該百年系統默認的本地化設置,則能夠在啓動JVM時經過命令參實指定:java -Duser.language=en -Duser.region=US MyTest
本地化工具
NumberFormart,DateFormart,MessageFormat。MessageFormat在NumberFormart和DateFormat的基礎之上提供了佔位符字符串的格式換的功能,支持時間,貨幣,數組以及對象屬性格式化操做。
例如: Locale locale = new Locale("zh","CN"); NumberFormat format = NumberFormat.getCurrencyInstance(locale); double num = 123456.78; System.out.println(format.format(num));
//格式化信息串 String pattern1 = "{0},你好!你於{1}我行存入了{2}元"; //用於動態替換佔位符的參數 Object[] params = {"張三",new GregorianCalendar().getTime(),1000000.0E3}; //使用默認的本地化對象格式化信息 String message1 = MessageFormat.format(pattern1,params); System.out.println(message1); String pattern2 = "At {1,time,short} On {1,date,long},{0} paid {2,number,currency}."; MessageFormat messageFormat = new MessageFormat(pattern2,Locale.US); String result = messageFormat.format(params); System.out.println(result);
執行結果: CN ¥123,456.78 張三,你好!你於18-11-19 下午12:51我行存入了1,000,000,000元 At 12:51 PM On November 19, 2018,張三 paid $1,000,000,000.00.
ResourceBundle 若是須要國際化的支持,就必須爲不一樣的本地化類型非被提供對應的資源文件,並以鍋飯的方式進行命名: <資源名><語言代碼><國家/地區代碼>.properties,其語言代碼和讀取代碼都是可選的。<資源名>.properties命名的國際化資源文件是默認的資源文件,即某個本地換化類型在系統找不到的對應的資源文件,就纔有這個默認的資源文件。 例如:
Locale locale = new Locale("zh","CN"); Locale locale2 = new Locale("en","US"); ResourceBundle resourceBundle = ResourceBundle.getBundle("com/flexible/message",locale); ResourceBundle resourceBundle2 = ResourceBundle.getBundle("com/flexible/message",locale2); System.out.println(resourceBundle.getString("userName")); System.out.println(resourceBundle2.getString("userName"));
執行結果: 張三 zhangsan
Spring定義了訪問國際化信息的MessageSource接口,而且提供了若干個易用的實現類,這些重要的方法以下:
1.String getMessage(String code, Object[] args, String defaultMessage, Locale locale):code表示國際化信息中的屬性名稱,args用於傳遞格式化串佔位符所用的運行期參數;當在資源中找不到對應的屬性名稱時,返回defaultMessage參數指定的默認信息,locale表示本地化對象。
2.String getMessage(String code, Object[] args, Locale locale)throws NoSuchMessageException:與1的方法同樣,只是在找不到資源的時候拋出NoSuchMessageException
3.String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException:將屬性名,參數數組以及默認信息封裝起來,他的功能和第一個接口方法相同。
MessageSource的類結構
HierarchicalMessageSource:接口添加了兩個方法,創建了父子層級的MessageSource結構,相似於前面介紹的HierachicalBeanFactory.該接口的setParentMessageSource(MessageSource parent)放啊用於設置父MessageSource和MessageSource getParentMessageSource()返回父MessageSource
ResourceBundleMessageSource和ReloadableResourceBundleMessageSource是HierarchicalMessageSource兩個重要的子類。
容許用戶經過beanName制定一個字眼名(包括類路徑的全限定資源名),或者經過beanNames指定一組資源名。使用ResourceBundleMessageSource例子以下:
String[] configs = {"message/beans"}; ApplicationContext context = new ClassPathXmlApplicationContext(configs); //獲取MessageSource的Bean MessageSource ms = (MessageSource)context.getBean("mySource"); Object[] params = {"jack",new GregorianCalendar().getTime()}; //獲取格式化的國際信息 String str1 = ms.getMessage("userName",params, Locale.US); System.out.println(str1);
xml配置文件:
<bean id="mySource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basenames"> <list> <value>com/flexible/message</value> </list> </property> </bean>
執行結果: zhangsan
該類能夠是實現資源的定時刷新
<bean id="mySource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basenames"> <list> <value>com/flexible/message</value> </list> </property> <property name="cacheSeconds" value="5"></property> </bean>
Spring正常狀況下時不會將國際化資源做爲Bean注入其餘的Bean當中,而是作爲容器的基礎設施向全部的bean開放。在前面已經介紹過initMessageSource()就是初始化容器中的國際化信息資源,它根據反射機制從BeanDefinitionRegistry中找出名爲messageSource且類型爲org.springframework.context.MessageSource的Bean,將這個Bean定義的信息資源加載爲容器級別的國際化信息資源。 例如:
ApplicationContext context = new ClassPathXmlApplicationContext("containermessagesouece/beans"); String userName1 = context.getMessage("userName", params, Locale.CHINA); String userName2 = context.getMessage("userName", params, Locale.US); System.out.println("userName1:"+userName1+"---"+"userName2:"+userName2);
beans.xml
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> //這個地方只能命名爲messageSource,不然就會拋出NoSuchMessageException <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basenames"> <list> <value>com/flexible/message</value> </list> </property> </bean> </beans>