目錄
5.2.3、BeanFactory 和FactoryBean對比:
5.4.2、BeanPOSTProcessor後處理Bean
6、集合注入(Array、List、Set、Map、Properties)
1、Spring框架概述
2、IOC
2.1、導入jar包
四個核心(beans、core、context、expression)和一個依賴(commons.logging)
2.2、目標類
在之前的學習中,通常通過new實例化對象,學習spring框架後,將由spring創建對象的實例,即IoC(Inverse of control,控制反轉)
創建UserService接口和其實現類
public interface UserService { public void addUser(); } public class UserServiceImpl implements UserService{ @Override public void addUser() { // TODO 自動生成的方法存根 System.out.println("test of ioc"); } }
2.3、配置文件
<?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 definitions here <bean>這個標籤配置的是我們需要創建的對象 id:用於之後從Spring容器獲得實例時使用 class:需要創建實例時的全限定名 --> <bean id="UserServiceId" class = "test_ioc.UserServiceImpl" ></bean> </beans>
2.4、測試
public class TestIoC { @Test public void demo01() { //之前學習的是以下方式new實例對象 UserService userService = new UserServiceImpl(); userService.addUser(); } @Test public void demo02() { /* * 從Spring容器中獲得實例對象 * 1、獲取容器 * 2、獲得內容 */ //1、獲取容器 String xmlPath = "applicationContext.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); //2、獲取內容:不需要自己new 都是從spring容器中獲得 UserService userService = (UserService) applicationContext.getBean("UserServiceId"); userService.addUser(); } }
結果如下:
3、DI
3.1、依賴注入
依賴:一個對象需要使用到另一個對象注入:通過setter方法進行另一個對象實例設置
class B{ private A a; setter方法; };//B中有一個成員變量a,稱爲B依賴於A
3.2、配置信息
<bean id = "" class = ""> <property name = "" ref = ""></property> </bean> <property>標籤:用於進行屬性注入 name :bean的屬性名,通過setter方法獲得 ref:另一個bean的id值的引用
3.3、舉例說明
1、目標類:dao、service
- 創建BookService接口和實現類
- 創建BookDao接口和實現類
public interface BookDao { public void addBook(); } public class BookDaoImpl implements BookDao { @Override public void addBook() { // TODO 自動生成的方法存根 System.out.println("di add book"); } } public interface BookService { public void addBook(); } public class BookServiceImpl implements BookService { //方式一:接口+實現類 //private BookDao bookDao = new BookDaoImpl(); //方式二:接口+setter private BookDao bookDao; //setter方法 public void setBookDao(BookDao bookDao) { this.bookDao = bookDao; } @Override public void addBook() { // TODO 自動生成的方法存根 this.bookDao.addBook(); } }
2、配置文件
- 將dao和service配置到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.xsd"> <!-- bean definitions here 模擬spring的執行過程 創建service實例:BookService bookService = new BookServiceImpl(); IoC (<bean>) 創建dao實例:BookDao bookDao = new BookDaoImpl(); IoC (<bean>) 將dao設置給service:bookService.setBookDao(bookDao); DI (<property>) <property>標籤:用於進行屬性注入 name :bean的屬性名,通過setter方法獲得 bookDao ref:另一個bean的id值的引用 bookDaoId --> <!-- 創建service--> <bean id="bookServiceId" class="test_di.BookServiceImpl"> <property name="bookDao" ref="bookDaoId"></property> </bean> <!-- 創建dao--> <bean id="bookDaoId" class = "test_di.BookDaoImpl"></bean> </beans>
3、測試
public class TestDi { @Test public void demo() { //從spring容器中獲得 String xmlPath = "test_di/applicationContext.xml"; ApplicationContext applicationcontext= new ClassPathXmlApplicationContext(xmlPath); BookService bookService = (BookService) applicationcontext.getBean("bookServiceId"); bookService.addBook(); } }
4、核心API 、
4.1、BeanFactory:
工廠,用於生成任意bean。採取延遲加載,第一次getBean時會初始化Bean
4.2、ApplicationContext:
是BeanFactory的子接口,功能更加強大(國際化處理、事件傳遞、Bean自動裝配、各種不同應用層的Context實現)。當配置文件被加載就進行了對象的實例化
- ClassPathXmlApplicationContext:用於加載classpath(類路徑,src)下的xml
- FileSystemXmlApplicationContext:用於加載指定盤符下的xml
5、裝配Bean基於XML
5.1、實例化方式(三種)
5.1.1、默認構造
<bean id="" class=""></bean>; --->必須提供默認構造(就是沒有寫構造方法時系統默認的無參構造)
5.1.2、靜態工廠及其測試:
- 常用於Spring整合其他框架(工具)
- 用於生產實例對象,所有的方法必須是static
配置信息
<bean id="" class="工廠的全限定類名" factory-method="靜態方法"></bean>
測試
之前的學習的靜態工廠:
//People接口 public interface People { public void newPeople(); } //People接口的實現類 public class PeopleImpl implements People { @Override public void newPeople() { // TODO 自動生成的方法存根 System.out.println("create a people"); } } //靜態工廠 public class MyBeanFactory { public static People createPeople() { return new PeopleImpl(); } } //靜態工廠測試 public class TestStaticFactory { @Test public void demo01() { People people = MyBeanFactory.createPeople(); people.newPeople(); } }
學習Spring後:
//測試類如下 public class TestStaticFactory { @Test public void demo02() { //Spring工廠 String xmlPath = "test_b_inject_static_factory/applicationContext.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); People people = applicationContext.getBean("People",People.class); people.newPeople(); } }
spring配置信息:(主要是寫配置信息)
<?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 definitions here--> <!-- 將靜態工廠創建的實例教育spring class:確定靜態工廠全限定名 factory-method:確定靜態方法名 --> <bean id="People" class = "test_b_inject_static_factory.MyBeanFactory" factory-method="createPeople"></bean> </beans>
5.1.3、實例工廠及其測試
- 必須現有工廠的實例對象,然後通過實例對象去創建對象。
- 提供的所有方法是非靜態的
配置信息
<bean id = "" factory-bean = "實例工廠" factory-method = "普通方法"></bean>
測試
之前的學習
//People類接口 public interface People { public void newPeople(); } //People類的實現類 public class PeopleImpl implements People{ @Override public void newPeople() { // TODO 自動生成的方法存根 System.out.println("create a people"); } } //實例工廠 public class MyBeanFactory { public People createPeople() { return new PeopleImpl(); } } //測試類 public class TestFactory { @Test public void demo01() { //1、創建工廠 MyBeanFactory myBeanFactory = new MyBeanFactory(); //2、通過工廠實例獲取對象 People people = myBeanFactory.createPeople(); people.newPeople(); } }
學習spring後
public class TestFactory { @Test public void demo02() { String xmlPath = "test_c_inject_factory/applicationContext.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); People people = applicationContext.getBean("People",People.class); people.newPeople(); } }
spring配置信息
<?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 definitions here--> <!-- 創建工廠實例 --> <bean id = "MyBeanFactory" class = "test_c_inject_factory.MyBeanFactory" ></bean> <!-- 獲得People factory-bean:獲得工廠實例 factory-method:確定普通方法的 --> <bean id = "People" factory-bean = "MyBeanFactory" factory-method="createPeople"></bean> </beans>
測試結果
5.2、Bean的種類
5.2.1、普通Bean:
之前的操作都是普通bean,<bean id="" class="A">,spring直接創建A的實例,並返回
5.2.2、FactoryBean:
是一個特殊的bean,具有工廠生成對象的能力,只能生成特定的對象。bean必須實現FactoryBean的接口,此接口提供一個方法getObject()用於獲得特定的bean。-----<bean id="" class="FB">,先創建FB實例,然後調用getObject()方法,並返回方法的返回值
5.2.3、BeanFactory 和FactoryBean對比:
BeanFactory是工廠,用於生成任意Bean,FactoryBean是特殊的bean,用於生成另一個特定的bean。例如ProxyFactoryBean,此工廠bean用於生產代理,<bean id="" class="...ProxyFactoryBean">獲得代理對象實例。AOP使用
5.3、作用域
5.3.1、作用域:
用於確定spring創建bean實例個數
類別 | 說明 |
singleton | 在Spring IoC容器中僅存在一個Bean實例,Bean以單例方式存在 |
prototype | 每次從容器中調用Bean時,都返回一個新的實例,即每次調用getBean()時,相當於執行new XxxBean() |
request | 每次HTTP請求都會創建一個新的Bean,僅適用於webApplicationContext環境 |
session | 同一個HTTP Session共享一個Bean,不同Session使用不同Bean,僅適用於webApplicationContext環境 |
globalSession | 一般用於Portlet應用環境,該作用域僅適用於webApplicationContext環境 |
5.3.2、取值:
singleton:單例,默認情況下是單例模式
prototype:多例,每執行一次getBean()獲得一次實例
5.3.3、配置信息:
<bean id="" class="" scope="取值"></bean> 單例模式: <bean id="People" class = "PeopleImpl"></bean> 多例模式: <bean id="People" class = "PeopleImpl" scope = "prototype"></bean>
5.3.4、測試
測試如下代碼運行結果分別如下:
//People和PeopleImpl與上述相同 public class TestFactory { @Test public void demo01() { String xmlPath = "test_d_scope/applicationContext.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); People people1 = applicationContext.getBean("People",People.class); People people2 = applicationContext.getBean("People",People.class); System.out.println(people1); System.out.println(people2); } }
4、Bean的生命週期
5.4.1、初始化和銷燬及其測試
- 目標方法執行前會執行初始化方法
- 執行銷燬方法的兩點要求:
- 容器必須close,才執行銷燬方法
- 必須是單例模式(默認情況下就是單例模式)
<bean id = "" class = "" init-method = "初始化的方法名" destory-method = "銷燬的方法名稱"> init-method:用於配置初始化方法,準備數據 destroy-method:用於配置銷燬方法,清理資源等
測試代碼:在PeopleImpl類中添加初始化和銷燬方法
public class PeopleImpl implements People { @Override public void newPeople() { // TODO 自動生成的方法存根 System.out.println("create a people"); } //初始化方法 public void myInit() { System.out.println("my init method"); } //銷燬方法 public void myDestroy() { System.out.println("my destroy method"); } }
配置文件
<?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 = "People" class = "test_e_lifecycle.PeopleImpl" init-method = "myInit" destroy-method = "myDestroy"></bean> </beans>
測試類
public class TestFactory { @Test public void demo01() throws Exception, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { String xmlPath = "test_e_lifecycle/applicationContext.xml"; ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); People people = applicationContext.getBean("People",People.class); people.newPeople(); //要求1、容器必須close,銷燬方法才執行 2、必須是單例模式 //applicationContext.getClass().getMethod("close").invoke(applicationContext); //此ApplicationContext接口中沒有定義close()方法,但其實現類提供 applicationContext.close(); } }
測試結果:
5.4.2、BeanPOSTProcessor後處理Bean
- spring提供的一種機制,只要去實現此接口BeanPostProcessor,並將實現類提供給spring容器,spring容器將自動的執行,在初始化方法前執行before(),在初始化方法後執行after()
- Factory hook(鉤子)that allows for custom modification of new instances,e.g.checking for marker interfaces or wrapping them with proxies.(spring提供的工廠鉤子,用於修改實例對象,可以生成代理對象,是AOP的底層 )
- 模擬:
A a = new A(); a = B.before(a);//將a的實例對象傳遞給後處理bean,可以生成代理對象並返回 a.init();//此時a已經是代理對象 a = B.after(a); ----開啓事務---- a.method();//生成代理對象,目的是:在目標方法執行前後執行(例如開啓事務、提交事務) ----提交事務---- a.destory();
- 配置信息
<bean class=""></bean>
- 測試
- BeanPostProcessor實現類:此時返回值爲null,則會出現空指針異常
public class MyBeanPostProcessor implements BeanPostProcessor{ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // TODO 自動生成的方法存根 System.out.println("before method"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // TODO 自動生成的方法存根 System.out.println("after method"); return bean; } }
- 配置文件:(5.4.1配置文件的基礎上,將後處理的實現類註冊給spring)
<?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 definitions here init-method:用於配置初始化方法:準備數據 destroy-method:用於配置銷燬方法:清理資源等 --> <bean id = "People" class = "test_e_lifecycle.PeopleImpl" init-method = "myInit" destroy-method = "myDestroy"></bean> <!-- 將後處理的實現類註冊給spring--> <bean class = "test_e_lifecycle.MyBeanPostProcessor"></bean> </beans>
- 測試結果:在執行before()方法後,實例對象變爲空,出現java.lang.NullPointerException
BeanPostProcessor的實現類中的方法添加返回值:
public class MyBeanPostProcessor implements BeanPostProcessor{ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // TODO 自動生成的方法存根 System.out.println("before method" + " , " + beanName); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // TODO 自動生成的方法存根 System.out.println("after method" + " , " + beanName); return bean; } }
- 結果如下:此時就會按照:before()、init()、after()、實現類的方法、destroy()的順序進行執行
- 繼續實現在執行目標方法前後進行開啓事務和提交事務,修改BeanPostProcessor的實現類
public class MyBeanPostProcessor implements BeanPostProcessor{ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // TODO 自動生成的方法存根 System.out.println("before method" + " , " + beanName); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // TODO 自動生成的方法存根 System.out.println("after method" + " , " + beanName); //bean是目標對象 //生成jdk代理 return Proxy.newProxyInstance( MyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO 自動生成的方法存根 System.out.println("-----開啓事事務-----"); //執行目標方法 Object obj = method.invoke(bean, args); System.out.println("-----提交事務-----"); return obj; }}); } }
- 結果:
- 總結:兩個步驟
- BeanPostProcessor的實現類 (涉及到動態代理)
- 配置 <bean class=“BeanPostProcessor的實現類”></bean>
5、屬性依賴注入
5.5.1、構造方法(之後再補充)
5.5.2、setter方法
- 普通類型屬性的配置文件
<bean id = "" class = "實現類的權限定名"> <!-- 第一種方式 (推薦)--> <property name = "屬性名" value = "值"></property> <!-- 第二種方式 (不推薦)--> <property name = "屬性名"> <value>"值"</value> </property> </bean>
- 引用類型屬性的配置文件
<bean id = "" class = "實現類權限定名"> <!-- 第一種方法 (推薦)--> <property name = "屬性名" ref = "另一個bean的id"></property> <!-- 第二種方法 (不推薦)--> <property name = "屬性名"> <ref bean = "另一個bean的id"/> </property> </bean>
-
測試
準備的兩個類:
public class People { private String pName; private Integer age; private Address homeAddr;//家庭地址 private Address companyAddr;//公司地址 public String getpName() { return pName; } public void setpName(String pName) { this.pName = pName; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Address getHomeAddr() { return homeAddr; } public void setHomeAddr(Address homeAddr) { this.homeAddr = homeAddr; } public Address getCompanyAddr() { return companyAddr; } public void setCompanyAddr(Address companyAddr) { this.companyAddr = companyAddr; } @Override public String toString() { return "People [pName=" + pName + ", age=" + age + ", homeAddr=" + homeAddr + ", companyAddr=" + companyAddr+ "]"; } } /********************************************************************************/ public class Address { private String addr;//地址信息 private String tel;//地址的詳細電話 //添加setter方法 public void setAddr(String addr) { this.addr = addr; } public void setTel(String tel) { this.tel = tel; } public String getAddr() { return addr; } public String getTel() { return tel; } @Override public String toString() { return "Address [addr=" + addr + ", tel=" + tel + "]"; } }
編寫配置文件
<?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 = "People" class = "test_f_xml_b_setter.People"> <property name="pName" value = "jack"></property> <property name="age"> <value>20</value> </property> <property name="homeAddr" ref = "homeAddr"></property> <property name = "companyAddr"> <ref bean = "companyAddr"/> </property> </bean> <!-- Address --> <bean id="homeAddr" class = "test_f_xml_b_setter.Address"> <property name = "addr" value = "東風大道"></property> <property name = "tel" value = "88888888"></property> </bean> <bean id="companyAddr" class = "test_f_xml_b_setter.Address"> <property name ="addr" value = "發展大道"></property> <property name ="tel" value = "66666666"></property> </bean> </beans>
測試類
public class TestSetter { @Test public void demo01() { String xmlPath = "test_f_xml_b_setter/applicationContext.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); People people = (People) applicationContext.getBean("People"); String str = people.toString(); System.out.println(str); } }
測試結果:
5.5.3、P命令空間[瞭解]
- 作用:對“setter方法”注入進行簡化,替換<property>,替換如下
<bean id = "" class = "實現類的權限定名" p:屬性名 = "普通值" p:屬性名-ref = "引用值">
- p命名空間使用的前提,必須添加命名空間
- 測試
修改配置文件如下:
<?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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id = "homeAddr" class = "test_f_xml_c_p.Address" p:addr="東風大道" p:tel="88888888"> </bean> <bean id = "companyAddr" class = "test_f_xml_c_p.Address" p:addr="發展大道" p:tel="66666666"> </bean> <bean id = "People" class = "test_f_xml_c_p.People" p:pName = "jack" p:age = "20" p:homeAddr-ref="homeAddr" p:companyAddr-ref = "companyAddr"> </bean> </beans>
測試結果與5.5.3相同
5.5.4、SpEL(瞭解)
- 對<property>進行統一編程,所有的內容都使用value
<property name="" value="#(表達式)"></property> 數字:#{123} 字符串:#{'jack'} 另外一個bean的引用:#{beanId} 操作數據:#{beanId.propName} 執行方法:#{beadId.toString()} 靜態方法或字段:#{T(類的權限定名).字段|方法}
- 測試
public class Customer { private String cname; private Integer age; private Double pi;//Math.pi public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } public Double getPi() { return pi; } public void setPi(Double pi) { this.pi = pi; } @Override public String toString() { return "Customer [cname=" + cname + ", age=" + age + ", pi=" + pi + "]"; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
配置文件
<?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 = "customer" class = "test_f_xml_d_spel.Customer"> <property name = "cname" value = "#{'jack'}"></property> <property name = "age" value = "#{24}"></property> <property name ="pi" value = "#{T(java.lang.Math).PI}"></property> </bean> </beans>
測試類:
public class TestSpel { @Test public void demo01() { String xmlPath = "test_f_xml_d_spel/applicationContext.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); Customer customer = applicationContext.getBean("customer",Customer.class); System.out.println(customer.toString()); } }
測試結果
6、集合注入(Array、List、Set、Map、Properties)
- 集合的注入都是給<property>添加子標籤
- 一般情況下普通數據是<value>,引用數據是<ref>
- 數組:<array>
- List:<list>
- Set:<set>
- Map:<map>
- Properties:<props>
測試
public class CollectionData { private String[] arrayData; private List<String> listData; private Set<String> setData; private Map<String,String> mapData; private Properties propsData; public String[] getArrayData() { return arrayData; } public void setArrayData(String[] arrayData) { this.arrayData = arrayData; } public List<String> getListData() { return listData; } public void setListData(List<String> listData) { this.listData = listData; } public Set<String> getSetData() { return setData; } public void setSetData(Set<String> setData) { this.setData = setData; } public Map<String, String> getMapData() { return mapData; } public void setMapData(Map<String, String> mapData) { this.mapData = mapData; } public Properties getPropsData() { return propsData; } public void setPropsData(Properties propsData) { this.propsData = propsData; } @Override public String toString() { return "CollectionData [\narrayData=" + Arrays.toString(arrayData) + ", \nlistData=" + listData + ", \nsetData=" + setData + ", \nmapData=" + mapData + ", \npropsData=" + propsData + "\n]"; } }
配置文件:
<?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 = "collectionData" class = "test_f_xml_e_collection.CollectionData"> <property name = "arrayData"> <array> <value>array-String1</value> <value>array-String2</value> <value>array-String3</value> <value>array-String4</value> </array> </property> <property name = "listData"> <list> <value>list-String1</value> <value>list-String2</value> <value>list-String3</value> <value>list-String4</value> </list> </property> <property name = "SetData"> <set> <value>set-String1</value> <value>set-String2</value> <value>set-String3</value> </set> </property> <property name="mapData"> <map> <entry key="key1" value="map-String1"></entry> <entry key="key2" value="map-String2"></entry> <entry key="key3" value="map-String3"></entry> <entry> <key><value>key4</value></key> <value>map-String4</value> </entry> </map> </property> <property name="propsData"> <props> <prop key="key1">props-String1</prop> <prop key="key2">props-String2</prop> <prop key="key3">props-String3</prop> </props> </property> </bean> </beans>
測試類:
public class TestCollection { @Test public void demo() { String xmlPath = "test_f_xml_e_collection/applicationContext.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); CollectionData collectionData = applicationContext.getBean("collectionData",CollectionData.class); System.out.println(collectionData.toString()); } }
測試結果:
6、裝配Bean基於註解
6.1、什麼是註解
- 註解:就是一個類,使用@註解名稱
- 開發中:使用註解取代xml文件
- 使用的前提:添加命名空間,讓spring掃描含有註解的類
- 在參考文件中找到:the context schema
- schema的命名空間
1、命名空間聲明:
默認:xmlns=”“ <標籤名>--> <bean>
顯示:xmlns別名=”“ <別名標籤名>--><context:...>
2、確定schema xsd文件位置
xsl:schemaLocation=”名稱1 位置1 名稱2 位置2....“(內容都是成對的,【名稱 位置】)
6.2、註解分類
1、@Component 取代 <bean class = “”>
@Component("id) 取代 <bean id = "" class = "">
測試:
//定義一個接口 public interface People { public void newPeople(); } //接口的實現類 @Component("people") public class PeopleImpl implements People { @Override public void newPeople() { // TODO 自動生成的方法存根 System.out.println("create a people"); } } //測試類 public class TestDemo { @Test public void demo() { String xmlPath = "test_g_annotation_a_ioc/applicationContext.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); People people = applicationContext.getBean("people",People.class); people.newPeople(); } }
配置文件:
<?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="test_g_annotation_a_ioc"></context:component-scan> </beans>
2、web開發,提供3個@Component註解衍生註解(功能一樣),取代<bean class="">
@Repository:dao層
@Service:service層
@Controller:web層
3、依賴注入 給私有字段設置,也可以給setter方法設置
普通值:@value("")
引用值:
方式一:按照【類型】注入
@Autowired
方式二:按照【名稱】注入1
@Autowired
@Qualifier("名稱")
方式三:按照【名稱】注入2
@Resource("名稱")
測試:
@Controller("studentActionId") public class StudentAction { @Autowired//默認 按照類型注入 private StudentService studentService; public void execute() { studentService.addStudent(); } } //service public interface StudentService { public void addStudent(); } //StudentService的實現類 @Service public class StudentServiceImpl implements StudentService { private StudentDao studentDao; @Autowired//默認 按照類型注入 @Qualifier("studentDaoId") public void setStudentDao(StudentDao studentDao) { this.studentDao = studentDao; } @Override public void addStudent() { // TODO 自動生成的方法存根 //System.out.println("service"); studentDao.addStudent(); } } //dao public interface StudentDao { public void addStudent(); } //StudentDao的實現類 @Repository("studentDaoId") public class StudentDaoImpl implements StudentDao { @Override public void addStudent() { // TODO 自動生成的方法存根 System.out.println("create a student"); } }
測試類:
public class TestDemo { @Test public void demo() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("test_g_annotation_b_web/applicationContext.xml"); StudentAction studentAction = (StudentAction) applicationContext.getBean("studentActionId"); studentAction.execute(); } }
配置文件
<?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="test_g_annotation_b_web"></context:component-scan> </beans>
6.3、生命週期
初始化:@PostConstruct
銷燬:@PreDestory
6.4、作用域
@Scope("prototype") 多例
7、註解和xml混合使用
1、將所有的bean都配置在xml中 <bean id = “” class = “”>
2、將所有的依賴都使用註解 @Autowired
默認不生效,爲了生效,需要在xml文件中配置:<context annotation-config></context annotation-config>
總結:註解1 :<context-component-scan base-package ="">
註解2 :<context annotation-config>
1、一般兩個註解不一起使用
1、"註解1"掃描含有註解(@Component等)類的,注入的註解自動的生效,"註解2"只在xml和註解(注入)混合使用時,使注入註解生效