Spring Bean詳解
Spring Bean
在Spring的應用中,Spring IoC容器可以建立、裝配和配置應用元件物件,這裡的元件物件稱為Bean。
Bean的配置
Spring可以看作一個大型工廠,用於生產和管理Spring容器中的Bean。如果要使用這個工廠生產和管理Bean,需要開發者將Bean配置在Spring的配置檔案中,Spring框架支援XML和Properties兩種格式的配置檔案,在實際開發中常用XML格式的配置檔案。
從前面的內容得知XML配置檔案的根元素是<beans>
,<beans>
中包含了多個<bean>
子元素,每個<bean>
元素定義<bean>
<bean>
元素的常用屬性及其子元素如下所示
屬性或子元素名稱 | 描述 |
---|---|
id |
Bean在BeanFactory中的唯一標識,在程式碼中通過BeanFactory獲取Bean例項時使用的索引名稱。 |
class |
Bean的具體實現類,使用全類名描述。 |
scope |
指定Bean例項的作用域。 |
<construct-arg> |
<bean> 元素的子元素,使用構造方法注入,指定構造方法的引數,該元素的index屬性指定引數的序號,ref屬性指定對BeanFactory中其他Bean的引用關係,type屬性指定引數型別,vlaue屬性指定引數的常量值。 |
<property> |
<bean> 元素的子元素,用於設定一個屬性,該元素的name屬性指定Bean例項中相應屬性名稱,value指定Bean的屬性值,ref屬性指定屬性對BeanFactory中其他Bean的引用關係。 |
<list> |
<property> 元素的子元素,用於封裝List或陣列型別的依賴注入。 |
<map> |
<property> 元素的子元素,用於封裝map型別的依賴注入。 |
<set> |
<property> 元素的子元素,用於封裝set型別的依賴注入。 |
<entry> |
<map> 元素的子元素,用於設定一個鍵值對。 |
Bean的配置示例如下:
<?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">
<!--將指定類TestDIDaoImpl配置給Spring,讓Spring為其建立例項-->
<bean id="myTestDIDao" class="dao.Impl.TestDIDaoImpl"/>
<!--使用構造方法注入-->
<bean id="testDIService" class="service.Impl.TestDIServiceImpl">
<!--將myTestDIDao注入到TestDIServiceImpl類的屬性的TestDIDao上-->
<constructor-arg index="0" ref="myTestDIDao"/>
</bean>
<!--使用setter方法注入-->
<bean id="testDIService_setter" class="service.Impl.TestDIServiceImpl_setter">
<!--呼叫setter方法,將myTestDIDao注入到方法的屬性中-->
<property name="testDIDao" ref="myTestDIDao"/>
</bean>
</beans>
Bean的例項化
在面向物件中,如果想要使用某個物件,需要事先例項化該物件,同樣,在Spring框架中,如果想使用Spring容器中的Bean,也需要例項化Bean,Spring框架例項化Bean有3種方式,即構造方法例項化,靜態工廠例項化和例項工廠例項化(最常用的是構造方法例項化)。
構造方法例項化
在Spring框架中,Spring容器可以呼叫Bean對應類中的無參構造方法來例項化Bean,這種方式稱為構造方法例項化。
- 建立BeanClass類
package instance;
public class BeanClass {
public String message;
public BeanClass(){
message="構造方法例項化Bean";
}
public BeanClass(String s){
message=s;
}
}
- 建立配置檔案
<?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-->
<bean id="constructorInstance" class="instance.BeanClass"/>
</beans>
- 建立測試類
package Test;
import instance.BeanClass;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestInstance {
public static void main(String[] args) {
ApplicationContext appCo=new ClassPathXmlApplicationContext("applicationContext.xml");
BeanClass beanClass = (BeanClass) appCo.getBean("constructorInstance");
System.out.println(beanClass+beanClass.message);
}
}
靜態工廠例項化
在使用靜態工廠例項化Bean時要求開發者在工廠類中建立一個靜態方法來建立Bean的例項,在配置Bean時,class屬性指定靜態工廠類,同時還需要使用factory-method
屬性指定工廠類中的靜態方法,下面通過例項測試靜態工廠例項化
- 建立工廠類
BeanStaticFactory
package instance;
public class BeanStaticFactory {
private static BeanClass beanInstanece=new BeanClass("呼叫靜態工廠方法例項化");
public static BeanClass createInstance(){
return beanInstanece;
}
}
- 編輯配置檔案
<?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="staticFactory" class="instance.BeanStaticFactory" factory-method="createInstance"/>
</beans>
- 新增測試程式碼
package Test;
import instance.BeanClass;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestInstance {
public static void main(String[] args) {
ApplicationContext appCo=new ClassPathXmlApplicationContext("applicationContext.xml");
BeanClass beanClass = (BeanClass) appCo.getBean("staticFactory");
System.out.println(beanClass+beanClass.message);
}
}
例項工廠例項化
在使用例項工廠例項化Bean時要求開發者在工廠類中建立一個例項方法來建立Bean的例項,在配置Bean時需要使用factory-bean
屬性指定配置的例項工廠,同時還需要使用factory-method
屬性指定例項工廠中的例項方法。下面通過程式碼測試例項工廠例項化。
- 建立工廠類
BeanInstanceFactory
package instance;
public class BeanInstanceFactory {
public BeanClass createBeanClassInstance(){
return new BeanClass("呼叫例項工廠例項化Bean");
}
}
- 編輯配置檔案
<?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="myFactory" class="instance.BeanInstanceFactory"/>
<!--使用factory-bean屬性指定配置工廠,使用factory-method屬性指定使用哪個方法例項化-->
<bean id="instanceFactoryInstance" factory-bean="myFactory" factory-method="createBeanClassInstance"/>
</beans>
- 測試方法
package Test;
import instance.BeanClass;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestInstance {
public static void main(String[] args) {
ApplicationContext appCo=new ClassPathXmlApplicationContext("applicationContext.xml");
BeanClass beanClass = (BeanClass) appCo.getBean("instanceFactoryInstance");
System.out.println(beanClass+beanClass.message);
}
}
Bean的作用域
在Spring中不但可以完成Bean的例項化,還可以指定Bean的作用域,在Spring中定義例項化Bean的作用域如下:
作用域名稱 | 描述 |
---|---|
singleton |
預設的作用域,使用singleton定義的Bean在Spring容器中只有一個Bean例項。 |
prototype |
Spring容器每次獲取prototype定義的Bean,容器都將建立一個新的Bean例項。 |
requesrt |
在一次HTTP請求中容器將返回一個Bean例項,不同的HTTP請求返回不同的Bean例項,僅在Web應用中使用。 |
session |
在一個HTTPSession中,容器將返回一個Bean例項,僅在Web應用中使用。 |
application |
為每個ServletContext物件建立一個例項,即同一個應用共享一個Bean例項,僅在Web應用使用。 |
websocket |
為每個WebSocket物件建立一個例項,僅在Web應用使用。 |
在上表中,
singleton
和prototype
是最常用的兩種,後面4種僅在Web應用使用。
Singleton作用域
當將bean的scope設定為singleton時,Spring IoC容器僅生成和管理一個Bean物件,在使用id獲取Bean例項時,IoC容器將返回共享的Bean例項。
由於singleton是scope的預設方式,因此可以不寫。
測試singleton作用域,程式碼如下:
package Test;
import instance.BeanClass;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestInstance {
public static void main(String[] args) {
ApplicationContext appCo=new ClassPathXmlApplicationContext("applicationContext.xml");
BeanClass beanClass1 = (BeanClass) appCo.getBean("instanceFactoryInstance");
System.out.println(beanClass1+beanClass1.message);
BeanClass beanClass2 = (BeanClass) appCo.getBean("instanceFactoryInstance");
System.out.println(beanClass2+beanClass2.message);
}
}
獲取到兩個物件的hash值相同,因此是同一個物件。
prototype作用域
當將bean的scope設定為prototype時,SpringIoC容器將為每次請求建立一個新例項。如果將bean的配置改為:
<bean id="instanceFactoryInstance" factory-bean="myFactory" factory-method="createBeanClassInstance" scope="prototype"/>
則可以每次請求時都會建立一個新的例項。
Bean的生命週期
一個物件的生命週期包括建立(例項化和初始化),使用以及銷燬等階段,在Spring中,Bean物件週期也遵循這一過程,但是Spring提供許多對外的介面,允許開發者對3個過程(例項化,初始化,銷燬)的前後做一些操作。在SpringBean中,例項化是為物件開闢空間,初始化則是對屬性的初始化。
Spring容器可以管理singleton作用域Bean的生命週期,在此作用域下,Spring能夠精確地知道Bean何時被建立,何時初始化完成,以及何時被銷燬,而對於prototype作用域的Bean,Spring只負責建立,當容器建立了Bean的例項後,Bean例項就交給了客戶端的程式碼管理,Spring容器不再跟蹤其生命週期,並且不會管理那些被配置成prototype作用域的Bean,Spring中的生命週期的執行是一個很複雜的過程,可借鑑Servlet的宣告週期“例項化→初始化→接收請求→銷燬”來理解Spring的宣告週期。
Bean的生命週期整個過程如下:
- 根據Bean的配置情況例項化一個Bean
- 根據Spring上下文對例項化的Bean進行依賴注入,即對Bean的屬性進行初始化。
- 如果Bean實現了
BeanNameAware
介面,將呼叫它實現的setBeanName(String beanId)
方法,此引數傳遞的是Spring配置檔案中Bean的id。 - 如果Bean實現了
BeanFactoryAware
介面,將呼叫它實現的setBeanFactory
方法,此處傳遞的引數是當前Spring工廠例項的引用。 - 如果Bean實現了
ApplicationContextAware
介面,將呼叫它實現的setApplicationContext(ApplicationContext)
方法,此處引數傳遞的是Spring上下文例項的引用。 - 如果Bean關聯了
BeanPostProcessor
介面,將呼叫初始化方法postProcessBeforeInitialization(Object obj,String s)
對Bean進行操作。 - 如果Bean實現了
InitalizingBean
介面,將呼叫afterPropertiesSet
方法。 - 如果Bean在Spring配置檔案中配置了
init-method
屬性,將自動呼叫其配置的初始化方法。 - 如果Bean關聯了
BeanPostProcessor
介面,將呼叫postProcessAfterInitialzation(Object obj,String s)
方法,由於是在Bean初始化結束後呼叫After方法,也可用於記憶體或快取技術。
以上工作完成後就可以使用該Bean,由於該Bean的作用域是singleton,所以呼叫的是同一個Bean例項。
- 當Bean不再需要時進入銷燬階段,如果Bean實現了
DisposableBean
介面,則呼叫其實現的destroy
方法將Spring中的Bean銷燬。 - 如果在配置檔案中通過
destroy-method
屬性指定了Bean的銷燬方法,將呼叫其配置的銷燬方法進行銷燬。
在Spring中,通過實現特定的介面或通過<bean>
元素的屬性設定可以對Bean的生命週期產生影響,開發者可以隨意的配置屬性,但是不建議過多的使用Bean實現介面,因為這樣會使程式碼和Spring聚合較緊密。下面通過例項來演示Bean生命週期:
- 建立Bean的實現類
package life;
public class BeanLife {
public void initMyself(){
System.out.println(this.getClass().getName()+"執行自定義的初始化方法");
}
public void destroyMyself(){
System.out.println(this.getClass().getName()+"執行自定義的銷燬方法");
}
}
- 在Spring的配置檔案中建立一個Bean
<!--配置bean,使用init-method指定初始化方法,使用destroy-method指定銷燬方法-->
<bean id="beanLife" class="life.BeanLife" init-method="initMyself" destroy-method="destroyMyself"/>
- 測試生命週期
package Test;
import life.BeanLife;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestLife {
public static void main(String[] args) {
//為了方便演示銷燬方法,使用ClassPathXmlApplicationContext實現類宣告容器。
ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("獲取物件之前");
BeanLife beanLife=(BeanLife)ctx.getBean("beanLife");
System.out.println("獲取物件之後"+beanLife);
ctx.close();
}
}
Bean的裝配方式
Bean的裝配可以理解為將Bean依賴注入到Spring容器中,Bean的裝配方式即Bean依賴注入的方式。Spring容器支援基於XML的裝配、基於註解的裝配以及自動裝配方式,其中最受青睞的裝配方式是基於註解的裝配。
基於XML的配置方式的裝配
基於XML的裝配方式提供了兩種方式,即使用構造方法注入和使用屬性的setter方法注入。
在使用構造方法注入方式裝配Bean時,Bean的實現類需要提供帶引數的構造方法,並在配置方式中使用<bean>
的子元素<construct-arg>
來定義構造方法的引數,在使用屬性的setter方法注入方式裝配Bean時,Bean的實現類需要提供一個預設無引數的構造方法,併為需要注入的屬性提供對應的setter方法,另外還需要使用<bean>
元素的子元素<property>
為每個屬性注入值。
下面通過例項來演示基於XML配置的裝配方式。
- 建立Bean的實現類
ComplexUser
package assemble;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class ComplexUser {
private String uname;
private List<String> hobbyList;
private Map<String,String> residenceMap;
private Set<String> aliasSet;
private String[] array;
/**
* 使用構造方法注入,需要提供帶引數的構造方法
* @param uname
* @param hobbyList
* @param residenceMap
* @param aliasSet
* @param array
*/
public ComplexUser(String uname, List<String> hobbyList, Map<String, String> residenceMap, Set<String> aliasSet, String[] array) {
this.uname = uname;
this.hobbyList = hobbyList;
this.residenceMap = residenceMap;
this.aliasSet = aliasSet;
this.array = array;
}
/**
* 使用屬性的setter方法注入,提供預設無參構造方法,併為注入的屬性提供setter方法
*/
public ComplexUser() {
}
public void setUname(String uname) {
this.uname = uname;
}
public void setHobbyList(List<String> hobbyList) {
this.hobbyList = hobbyList;
}
public void setResidenceMap(Map<String, String> residenceMap) {
this.residenceMap = residenceMap;
}
public void setAliasSet(Set<String> aliasSet) {
this.aliasSet = aliasSet;
}
public void setArray(String[] array) {
this.array = array;
}
@Override
public String toString() {
return "ComplexUser{" +
"uname='" + uname + '\'' +
", hobbyList=" + hobbyList +
", residenceMap=" + residenceMap +
", aliasSet=" + aliasSet +
", array=" + Arrays.toString(array) +
'}';
}
}
- 配置Bean,在Spring配置檔案中使用
ComplexUser
配置Bean的兩個例項
<!--使用構造方法注入方式裝配ComplexUser例項user1-->
<bean id="user1" class="assemble.ComplexUser">
<constructor-arg index="0" value="chenheng1"/>
<constructor-arg index="1">
<list>
<value>唱歌</value>
<value>跳舞</value>
<value>爬山</value>
</list>
</constructor-arg>
<constructor-arg index="2">
<map>
<entry key="dalian" value="大連"/>
<entry key="beijing" value="北京"/>
<entry key="shanghai" value="上海"/>
</map>
</constructor-arg>
<constructor-arg index="3">
<set>
<value>chenheng100</value>
<value>chenheng101</value>
<value>chenheng102</value>
</set>
</constructor-arg>
<constructor-arg index="4">
<array>
<value>aaa</value>
<value>bbb</value>
</array>
</constructor-arg>
</bean>
<!--使用構造方法注入方式裝配ComplexUser例項user2-->
<bean id="user2" class="assemble.ComplexUser">
<constructor-arg index="0" value="chenheng2"/>
<constructor-arg index="1">
<list>
<value>看書</value>
<value>學習</value>
</list>
</constructor-arg>
<constructor-arg index="2">
<map>
<entry key="shenzhen" value="深圳"/>
<entry key="guanzhou" value="廣州"/>
<entry key="tianjin" value="天津"/>
</map>
</constructor-arg>
<constructor-arg index="3">
<set>
<value>chenheng103</value>
<value>chenheng104</value>
<value>chenheng105</value>
</set>
</constructor-arg>
<constructor-arg index="4">
<array>
<value>ccc</value>
<value>ddd</value>
</array>
</constructor-arg>
</bean>
- 測試基於XML的裝配方式
package Test;
import assemble.ComplexUser;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAssemble {
public static void main(String[] args) {
ApplicationContext appCon = new ClassPathXmlApplicationContext("applicationContext.xml");
//使用構造方法裝配測試
ComplexUser u1=(ComplexUser)appCon.getBean("user1");
System.out.println(u1);
//使用setter方法裝配測試
ComplexUser u2=(ComplexUser)appCon.getBean("user2");
System.out.println(u2);
}
}
基於註解的裝配
在Spring框架中,儘管使用XML配置檔案可以簡單地裝配Bean,但如果應用中有大量的Bean需要裝配,會導致XML配置檔案過於龐大,不方便維護,因此更多時候我們建議使用註解配置。
在Spring框架中定義了一系列的註解,下面介紹幾個常用的註解。
-
@Component
:該註解是一個泛化的概念,僅僅表示一個元件物件(Bean)。可以作用在任何層次上,下面通過一個例項解釋@Component
。- 建立一個Bean
package annotation; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component() /** 相當於@Component(“annotationUser”)或@Component(value = “annotationUser”), * annotationUser為Bean的id,預設為首字母小寫的類名 **/ public class AnnotationUser { @Value("chenheng") //只注入了值,對於複雜的注入目前使用該方式無法解決。 private String uname; public String getUname() { return uname; } public void setUname(String uname) { this.uname = uname; } }
- 配置註解:現在有了Bean的實現類,但還無法測試,因為Spring容器並不知道去哪裡找Bean物件。需要在配置檔案中配置註解,方式如下:
<context:component-scan base-package="bean所在的包"/>
,因此建立配置檔案annotationContext.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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="annotation"/> </beans>
- 測試Bean例項
package Test; import annotation.AnnotationUser; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestAnnotation { public static void main(String[] args) { ApplicationContext appCon = new ClassPathXmlApplicationContext("annotationContext.xml"); AnnotationUser annotationUser = (AnnotationUser)appCon.getBean("annotationUser"); System.out.println(annotationUser); } }
在Spring4.0以上,配置註解指定包中的註解進行掃描需要事先匯入SpringAOP的jar包。
@Repository
:該註解用於將資料訪問層(DAO)的類標識為Bean,即註解資料訪問層Bean,其功能與@Compoent
相同。@Service
:該註解用於標註一個業務邏輯層元件,其功能與@Compoent
相同。@Autowired
:該註解對類成員變數、方法及建構函式進行標註,完成自動裝配的工作,通過使用@Autowired
來消除setter和getter方法,預設按照Bean的型別進行裝配。
預設按照bean型別注入,意思是不需要寫property屬性,直接按照名稱向類成員變數、方法及建構函式注入。
@Controller
:該註解用於標註一個控制器元件類,其功能與@Compoent
相同。@Resource
:該註解與@Autowired
的功能一樣,區別在於該註解是按照名稱來進行裝配注入的,只有當找不到與名稱匹配的Bean時才會按照型別來裝配注入。而@Autowired
預設是按照Bean的型別進行裝配,如果想按照名稱來裝配,則需要與@Qualifier
註解一起使用。
@Resource
有兩個屬性——name和type,name屬性指定的是Bean例項的名稱,即按照名稱注入,type指定的是Bean型別,即按照Bean的型別進行裝配。
@Qualifier
:該註解與@Autowired
配合使用,當@Autowired
註解需要按照名稱來裝配注入時需要和該註解一起使用,Bean的例項名稱由@Qulifier
註解的引數指定。
在上面的幾個註解中,@Controller
,@Repository
,@Service
的功能與@Compoent
一樣,但是為了讓類的標註更加清晰,在開發中推薦使用@Repository
標註資料訪問層(DAO層),@Service
標註業務邏輯層(Service層),@Controller
標註控制器層(控制層)。
下面通過例項使用註解:
- 建立Dao層介面
TestDao
package annotation.dao;
public interface TestDao {
public void save();
}
- 實現TestDao介面
TestDaoImpl
package annotation.dao.Impl;
import annotation.dao.TestDao;
import org.springframework.stereotype.Repository;
@Repository("testDao")
/**相當於@Repository,但如果在service中使用@Resource(name="testDao")時,不能省略testDao*/
public class TestDaoImpl implements TestDao {
@Override
public void save() {
System.out.println("testDao save");
}
}
- 建立Service介面TestService
package annotation.Service;
public interface TestService {
public void save();
}
- 實現Service介面TestServiceImpl
package annotation.Service.Impl;
import annotation.Service.TestService;
import annotation.dao.TestDao;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service("testService") //相當於testService
public class TestServiceImpl implements TestService {
@Resource(name = "testDao")//相當於使用@Autowired。按照型別裝配
private TestDao testDao;
@Override
public void save() {
testDao.save();
System.out.println("testService save");
}
}
- 建立Controller類
package annotation.Controller;
import annotation.Service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class TestController {
@Autowired
private TestService testService;
public void save(){
testService.save();
System.out.println("testController save");
}
}
- 配置註解
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="annotation"/>
</beans>
- 建立測試類
package Test;
import annotation.Controller.TestController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestMoreAnnoation {
public static void main(String[] args) {
ApplicationContext appCo=new ClassPathXmlApplicationContext("annotationContext.xml");
TestController testController = (TestController)appCo.getBean("testController");
testController.save();
}
}