Spring 是衆多開源java項目中的一員,基於分層的javaEE應用一站式輕量級開源框架,主要核心是 IOC(控制反轉/依賴注入)與 AOP(面向切面)兩大技術,實現項目在開發過程當中的輕鬆解耦,提升項目的開發效率。html
在項目中引入 Spring 當即能夠帶來下面的好處 下降組件之間的耦合度,實現軟件各層之間的解耦。可使用容器提供的衆多服務,如:事務管理服務、消息服務等等。當咱們使用容器管理事務時,開發人員就再也不須要手工控制事務.也不需處理複雜的事務傳播。 容器提供單例模式支持,開發人員再也不須要本身編寫實現代碼。 容器提供了AOP技術,利用它很容易實現如權限攔截、運行期監控等功能。java
Spring 總共大約有20個模塊,由1300多個不一樣的文件構成。而這些組件被分別整合在覈心容器(Core Container)、Aop(Aspect Oriented Programming)和設備支持(Instrmentation)、數據訪問及集成(Data Access/Integeration)、Web、報文發送(Messaging)、測試6個模塊集合中。web
Spring 上下文Spring Context:Spring 上下文是一個配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企業服務,例如 JNDI、EJB、電子郵件、國際化、校驗和調度功能。spring
Spring-Expression 模塊是統一表達式語言(unified EL)的擴展模塊,能夠查詢、管理運行中的對象,同時也方便的能夠調用對象方法、操做數組、集合等。它的語法相似於傳統EL,但提供了額外的功能,最出色的要數函數調用和簡單字符串的模板函數。編程
Spring-tx 模塊是SpringJDBC事務控制實現模塊。使用Spring框架,它對事務作了很好的封裝,經過它的Aop配置,能夠靈活的配置在任何一層。數組
Spring-Orm 模塊是ORM框架支持模塊,主要集成 hibernate, Java Persistence API (JPA) 和 Java Data Objects (JDO) 用於資源管理、數據訪問對象(DAO)的實現和事務策略。緩存
Spring-Jms 模塊(Java Messaging Service)可以發送和接受信息。安全
Spring-Oxm 模塊主要提供一個抽象層以支撐OXM(OXM 是 Object-to-XML-Mapping 的縮寫,它是一個O/M-mapper,將java對象映射成 XML 數據,或者將 XML 數據映射成 java 對象),例如:JAXB, Castor, XMLBeans, JiBX 和 XStream 等。websocket
Spring-messaging是Spring4 新加入的一個模塊,主要職責是爲Spring 框架集成一些基礎的報文傳送應用。session
JDK 版本:
JDK 1.7 及以上版本
Spring版本:
Spring 5.x版本
修改 JDK 版本
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties>
修改單元測試 JUnit 版本
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency>
build標籤中的pluginManagement標籤
<!--刪除build標籤中的pluginManagement標籤--> <build> </build>
Maven倉庫:https://mvnrepository.com/
<!-- 添加Spring框架的核心依賴 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.4.RELEASE</version> </dependency>
package com.xxxx.service; public class UserService { public void test(){ System.out.println("Hello Spring!"); } }
在 srcmainresources 目錄下新建 spring.xml 文件,並拷貝官網文檔提供的模板內容到 xml 中。
配置 bean 到 xml 中,把對應 bean 歸入到 Spring 容器來管理
spring.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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- xmlns 即 xml namespace xml使用的命名空間 xmlns:xsi 即xml schema instance xml 遵照的具體規範 xsi:schemaLocation 本文檔xml遵照的規範 官方指定 --> <bean id="userService" class="com.xxxx.service.UserService"></bean> </beans>
在 spring.xml 中配置 Bean 對象
<!-- id:bean對象的id,惟一標識。通常是Bean對象的名稱的首字母小寫 class:bean對象的類路徑 --> <bean id="userService" class="com.xxxx.service.UserService"></bean>
package com.xxxx; import com.xxxx.service.UserService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App { public static void main(String[] args) { // 獲取Spring上下文環境 (加載配置文件) ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml"); // 經過getBean方法獲得Spring容器中實例化好的Bean對象 (實例化Bean對象) // userService表明的是配置文件中bean標籤的id屬性值 UserService userService = (UserService) ac.getBean("userService"); // 調用方法 (使用實例化對象) userService.test(); } }
思路:
package com.xxxx.spring; /** * bean對象 * 用來接收配置文件中bean標籤的id與class屬性值 */ public class MyBean { private String id; // bean對象的id屬性值 private String clazz; // bean對象的類路徑 public MyBean() { } public MyBean(String id, String clazz) { this.id = id; this.clazz = clazz; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getClazz() { return clazz; } public void setClazz(String clazz) { this.clazz = clazz; } }
<!-- dom4j --> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency> <!-- XPath --> <dependency> <groupId>jaxen</groupId> <artifactId>jaxen</artifactId> <version>1.1.6</version> </dependency>
spring.xml
<?xml version="1.0" encoding="utf-8" ?> <beans> <bean id="userService" class="com.xxxx.service.UserService"></bean> <bean id="accountService" class="com.xxxx.service.AccountService"></bean> </beans>
package com.xxxx.spring; /** * Bean 工廠接口定義 */ public interface MyFactory { // 經過id值獲取對象 public Object getBean(String id); }
package com.xxxx.spring; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.XPath; import org.dom4j.io.SAXReader; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 模擬Spring的實現 * 一、經過構造器獲得相關配置文件 * 二、經過dom4j解析xml文件,獲得List 存放id和class * 三、經過反射實例化獲得對象 Class.forName(類的全路徑).newInstance(); 經過Map<id,Class>存儲 * 四、獲得指定的實例化對象 */ public class MyClassPathXmlApplicationContext implements BeanFactory { private Map beans = new HashMap(); // 實例化後的對象放入map private List<MyBean> myBeans; // 存放已讀取bean 配置信息 /* 一、經過構造器獲得相關配置文件 */ public MyClassPathXmlApplicationContext(String fileName) { /* 二、經過dom4j解析xml文件,獲得List (存放id和class) */ this.parseXml(fileName); /* 三、經過反射實例化獲得對象Class.forName(類路徑).newInstance(); 經過Map存儲 */ this.instanceBean(); } /** * 經過dom4j解析xml文件,獲得List 存放id和class * 一、獲取解析器 * 二、獲得配置文件的URL * 三、經過解析器解析xml文件(spring.xml) * 四、經過xpath語法,獲取beans標籤下的全部bean標籤 * 五、經過指定語法解析文檔對象,返回集合 * 六、判斷集合是否爲空,遍歷集合 * 七、獲取標籤元素中的屬性 * 八、獲得Bean對象,將Bean對象設置到集合中 * @param fileName */ private void parseXml(String fileName) { // 一、獲取解析器 SAXReader reader = new SAXReader(); // 二、獲得配置文件的URL URL url = this.getClass().getClassLoader().getResource(fileName); try { // 三、經過解析器解析xml文件(spring.xml) Document document = reader.read(url); // 四、經過xpath語法,獲取beans標籤下的全部bean標籤 XPath xPath = document.createXPath("beans/bean"); // 經過指定語法解析文檔對象,返回集合 List<Element> list = xPath.selectNodes(document); // 判斷集合是否爲空,遍歷集合 if (list != null && list.size() > 0) { myBeans = new ArrayList<>(); for(Element el : list) { // 獲取標籤元素中的屬性 String id = el.attributeValue("id"); // id 屬性值 String clazz = el.attributeValue("class"); // class 屬性值 System.out.println(el.attributeValue("id")); System.out.println(el.attributeValue("class")); // 獲得Bean對象 MyBean bean = new MyBean(id, clazz); // 將Bean對象設置到集合中 myBeans.add(bean); } } } catch (DocumentException e) { e.printStackTrace(); } } /** * 經過反射實例化獲得對象 * Class.forName(類的全路徑).newInstance(); * 經過Map<id,Class>存儲 */ private void instanceBean() { // 判斷bean集合是否爲空,不爲空遍歷獲得對應Bean對象 if (myBeans != null && myBeans.size() > 0) { for (MyBean bean : myBeans){ try { // 經過類的全路徑實例化對象 Object object = Class.forName(bean.getClazz()).newInstance(); // 將id與實例化對象設置到map對象中 beans.put(bean.getId(), object); } catch (Exception e) { e.printStackTrace(); } } } } /** * 經過key獲取map中的指定value * @param id * @return */ @Override public Object getBean(String id) { Object object = beans.get(id); return object; } }
建立與配置文件中對應的Bean對象
UserService.java
package com.xxxx.service; public class UserService { public void test(){ System.out.println("UserService Test..."); } }
AccountService.java
package com.xxxx.service; public class AccountService { public void test(){ System.out.println("AccountService Test..."); } }
測試是否能夠獲取實例化的Bean對象
package com.xxxx; import com.xxxx.spring.MyFactory; import com.xxxx.spring.MyClassPathXmlApplicationContext; import com.xxxx.service.AccountService; import com.xxxx.service.UserService; public class App { public static void main(String[] args) { MyFactory factory = new MyClassPathXmlApplicationContext("spring.xml"); // 獲得實例化對象 UserService userService = (UserService) factory.getBean("userService"); userService.test(); UserService userService2 = (UserService) factory.getBean("userService"); System.out.println(userService+"=====" + userService2); AccountService accountService = (AccountService)factory.getBean("accountService"); accountService.test(); } }
Spring 容器在啓動的時候 讀取xml配置信息,並對配置的 bean 進行實例化(這裏模擬的比較簡單,僅用於幫助你們理解),同時經過上下文對象提供的 getBean() 方法拿到咱們配置的 bean 對象,從而實現外部容器自動化維護並建立 bean 的效果。
spring.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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userService" class="com.xxxx.service.UserService"></bean> </beans>
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
ApplicationContext ac = new FileSystemXmlApplicationContext("C:/IdeaWorkspace/spring01/src/main/resources/spring.xml");
Spring 框架啓動時能夠加載多個配置文件到環境中。對於比較複雜的項目,可能對應的配置文件有多個,項目在啓動部署時會將多個配置文件同時加載進來。
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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userService" class="com.xxxx.service.UserService"></bean> </beans>
dao.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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userDao" class="com.xxxx.dao.UserDao"></bean> </beans>
// 同時加載多個資源文件 ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml","dao.xml");
spring.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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!--導入須要包含的資源文件--> <import resource="service.xml"/> <import resource="dao.xml"/> </beans>
加載時只需加載總的配置文件便可
// 加載總的資源文件 ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
注:經過默認構造器建立 空構造方法必須存在 不然建立失敗
設置配置文件 spring.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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userService" class="com.xxxx.service.UserService"></bean> </beans>
獲取實例化對象
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml"); UserService userService = (UserService) ac.getBean("userService"); userService.test();
注:
定義靜態工廠類
package com.xxxx.factory; import com.xxxx.service.UserService; /** * 定義靜態工廠類 */ public class StaticFactory { /** * 定義對應的靜態方法,返回實例化對象 * @return */ public static UserService createUserService() { return new UserService(); } }
設置配置文件 spring.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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!--靜態工廠--> <bean id="userService" class="com.xxxx.factory.StaticFactory" factory-method="createUserService"></bean> </beans>
獲取實例化對象
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml"); UserService userService = (UserService) ac.getBean("userService"); userService.test();
當咱們指定Spring使用靜態工廠方法來建立Bean實例時,Spring將先解析配置文件,並根據配置文件指定的信息,經過反射調用靜態工廠類的靜態工廠方法,並將該靜態工廠方法的返回值做爲Bean實例,在這個過程當中,Spring再也不負責建立Bean實例,Bean實例是由用戶提供的靜態工廠方法提供的。
注:
定義工廠類
package com.xxxx.factory; import com.xxxx.service.UserService; /** * 定義工廠類 */ public class InstanceFactory { /** * 定義方法,返回實例化對象 * @return */ public UserService createUserService() { return new UserService(); } }
設置配置文件 spring.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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 實例化工廠 1.定義實例化工廠bean 2.引用工廠bean 指定工廠建立方法(方法爲非靜態) --> <bean id="instanceFactory" class="com.xxxx.factory.InstanceFactory"></bean> <bean id="userService" factory-bean="instanceFactory" factory-method="createUserService"></bean> </beans>
獲取實例化對象
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml"); UserService userService = (UserService) ac.getBean("userService"); userService.test();
開發中項目通常使用一種方式實例化bean,項目開發基本採用第一種方式,交給Spring託管,使用時直接拿來使用便可。另外兩種瞭解
手動實例化與外部引入
圖一:
圖二:
對比發現:圖二中對於 UserDao 對象的建立並無像圖一那樣主動的去實例化,而是經過帶參方法形式將UserDao 傳入過來,從而實現 UserService 對UserDao類 的依賴。
而實際建立對象的幕後對象便是交給了外部來建立。
Spring 支持的注入方式共有四種:set 注入、構造器注入、靜態工廠注入、實例化工廠注入。
注:
屬性字段提供set方法
public class UserService { // 業務對象UserDao set注入(提供set方法) private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } }
配置文件的bean標籤設置property標籤
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- IOC經過property標籤手動裝配(注入): Set方法注入 name:bean對象中屬性字段的名稱 ref:指定bean標籤的id屬性值 --> <bean id="userDao" class="com.xxxx.dao.UserDao"></bean> <bean id="userService" class="com.xxxx.service.UserService"> <!--業務對象 注入--> <property name="userDao" ref="userDao"/> </bean> </beans>
屬性字段提供set方法
public class UserService { // 經常使用對象String set注入(提供set方法) private String host; public void setHost(String host) { this.host = host; } // 基本類型Integer set注入(提供set方法) private Integer port; public void setPort(Integer port) { this.port = port; } }
配置文件的bean標籤設置property標籤
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- IOC經過property標籤手動裝配(注入): Set方法注入 name:bean對象中屬性字段的名稱 value:具體的值(基本類型 經常使用對象|日期 集合) --> <bean id="userService" class="com.xxxx.service.UserService"> <!--經常使用對象String 注入--> <property name="host" value="127.0.0.1"/> <!--基本類型注入--> <property name="port" value="8080"/> </bean> </beans>
屬性字段提供set方法
public class UserService { // List集合 set注入(提供set方法) public List<String> list; public void setList(List<String> list) { this.list = list; } // Set集合 set注入(提供set方法) private Set<String> set; public void setSet(Set<String> set) { this.set = set; } // Map set注入(提供set方法) private Map<String,Object> map; public void setMap(Map<String, Object> map) { this.map = map; } // Properties set注入(提供set方法) private Properties properties; public void setProperties(Properties properties) { this.properties = properties; } }
配置文件的bean標籤設置property標籤
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- IOC經過property標籤手動裝配(注入): Set方法注入 name:bean對象中屬性字段的名稱 value:具體的值(基本類型 經常使用對象|日期 集合) --> <!--List集合 注入--> <property name="list"> <list> <value>上海</value> <value>北京</value> <value>杭州</value> </list> </property> <!--Set集合注入--> <property name="set"> <set> <value>上海SH</value> <value>北京BJ</value> <value>杭州HZ</value> </set> </property> <!--Map注入--> <property name="map"> <map> <entry> <key><value>周杰倫</value></key> <value>我是如此相信</value> </entry> <entry> <key><value>林俊杰</value></key> <value>惋惜沒若是</value> </entry> <entry> <key><value>陳奕迅</value></key> <value>十年</value> </entry> </map> </property> <!--Properties注入--> <property name="properties"> <props> <prop key="上海">東方明珠</prop> <prop key="北京">天安門</prop> <prop key="杭州">西湖</prop> </props> </property> </beans>
UserService.java
public class UserService { // 業務對象UserDao set注入(提供set方法) private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } // 經常使用對象String set注入(提供set方法) private String host; public void setHost(String host) { this.host = host; } // 基本類型Integer set注入(提供set方法) private Integer port; public void setPort(Integer port) { this.port = port; } // List集合 set注入(提供set方法) public List<String> list; public void setList(List<String> list) { this.list = list; } // List集合輸出 public void printList() { list.forEach(s -> System.out.println(s)); } // Set集合 set注入(提供set方法) private Set<String> set; public void setSet(Set<String> set) { this.set = set; } // Set集合輸出 public void printSet() { set.forEach(s -> System.out.println(s)); } // Map set注入(提供set方法) private Map<String,Object> map; public void setMap(Map<String, Object> map) { this.map = map; } // Map輸出 public void printMap() { map.forEach((k,v) -> System.out.println(k + "," + v)); } // Properties set注入(提供set方法) private Properties properties; public void setProperties(Properties properties) { this.properties = properties; } // Properties輸出 public void printProperties(){ properties.forEach((k,v) -> System.out.println(k + ","+ v )); } public void test(){ System.out.println("UserService Test..."); userDao.test(); studentDao.test(); System.out.println("Host:" + host + ",port:" + port); // List集合 printList(); // Set集合 printSet(); // Map printMap(); // Properties printProperties(); } }
spring.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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- IOC經過property標籤手動裝配(注入): Set方法注入 name:bean對象中屬性字段的名稱 ref:指定bean標籤的id屬性值 value:具體的值(基本類型 經常使用對象|日期 集合) --> <bean id="userDao" class="com.xxxx.dao.UserDao"></bean> <bean id="userService" class="com.xxxx.service.UserService"> <!--業務對象 注入--> <property name="userDao" ref="userDao"/> <property name="studentDao" ref="studentDao"/> <!--經常使用對象String 注入--> <property name="host" value="192.168.1.109"/> <!--基本類型注入--> <property name="port" value="8080"/> <!--List集合 注入--> <property name="list"> <list> <value>上海</value> <value>北京</value> <value>杭州</value> </list> </property> <!--Set集合注入--> <property name="set"> <set> <value>上海SH</value> <value>北京BJ</value> <value>杭州HZ</value> </set> </property> <!--Map注入--> <property name="map"> <map> <entry> <key><value>周杰倫</value></key> <value>我是如此相信</value> </entry> <entry> <key><value>林俊杰</value></key> <value>惋惜沒若是</value> </entry> <entry> <key><value>陳奕迅</value></key> <value>十年</value> </entry> </map> </property> <!--Properties注入--> <property name="properties"> <props> <prop key="上海">東方明珠</prop> <prop key="北京">天安門</prop> <prop key="杭州">西湖</prop> </props> </property> </bean> </beans>
注:
Java 代碼
public class UserService { private UserDao userDao; // JavaBean 對象 public UserService(UserDao userDao) { this.userDao = userDao; } public void test(){ System.out.println("UserService Test..."); userDao.test(); } }
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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- IOC經過構造器注入: 經過constructor-arg標籤進行注入 name:屬性名稱 ref:指定bean標籤的id屬性值 --> <bean id="userDao" class="com.xxxx.dao.UserDao" ></bean> <bean id="userService" class="com.xxxx.service.UserService"> <constructor-arg name="userDao" ref="userDao"></constructor-arg> </bean> </beans>
Java 代碼
public class UserService { private UserDao userDao; // JavaBean 對象 private AccountDao accountDao // JavaBean 對象 public UserService(UserDao userDao, AccountDao accountDao) { this.userDao = userDao; this.accountDao = accountDao; } public void test(){ System.out.println("UserService Test..."); userDao.test(); accountDao.test(); } }
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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- IOC經過構造器注入: 經過constructor-arg標籤進行注入 name:屬性名稱 ref:指定bean標籤的id屬性值 --> <bean id="userDao" class="com.xxxx.dao.UserDao" ></bean> <bean id="accountDao" class="com.xxxx.dao.AccountDao" ></bean> <bean id="userService" class="com.xxxx.service.UserService"> <constructor-arg name="userDao" ref="userDao"></constructor-arg> <constructor-arg name="accountDao" ref="accountDao"></constructor-arg> </bean> </beans>
Java 代碼
public class UserService { private UserDao userDao; // JavaBean 對象 private AccountDao accountDao; // JavaBean 對象 private String uname; // 字符串類型 public UserService(UserDao userDao, AccountDao accountDao, String uname) { this.userDao = userDao; this.accountDao = accountDao; this.uname = uname; } public void test(){ System.out.println("UserService Test..."); userDao.test(); accountDao.test(); System.out.println("uname:" + uname); } }
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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- IOC經過構造器注入: 經過constructor-arg標籤進行注入 name:屬性名稱 ref:指定bean標籤的id屬性值 value:基本類型 經常使用對象的值 index:構造器中參數的下標,從0開始 --> <bean id="userDao" class="com.xxxx.dao.UserDao" ></bean> <bean id="accountDao" class="com.xxxx.dao.AccountDao" ></bean> <bean id="userService" class="com.xxxx.service.UserService"> <constructor-arg name="userDao" ref="userDao"></constructor-arg> <constructor-arg name="accountDao" ref="accountDao"></constructor-arg> <constructor-arg name="uname" value="admin"></constructor-arg> </bean> </beans>
循環問題產生的緣由:
Bean經過構造器注入,之間彼此相互依賴對方致使bean沒法實例化。
問題展現:
Java 代碼
public class AccountService { private RoleService roleService; public AccountService(RoleService roleService) { this.roleService = roleService; } public void test() { System.out.println("AccountService Test..."); } } public class RoleService { private AccountService accountService; public RoleService(AccountService accountService) { this.accountService = accountService; } public void test() { System.out.println("RoleService Test..."); } }
XML配置
<!-- 若是多個bean對象中互相注入,則會出現循環依賴的問題 能夠經過set方法注入解決 --> <bean id="accountService" class="com.xxxx.service.AccountService"> <constructor-arg name="roleService" ref="roleService"/> </bean> <bean id="roleService" class="com.xxxx.service.RoleService"> <constructor-arg name="accountService" ref="accountService"/> </bean>
如何解決:將構造器注入改成set方法注入
Java代碼
public class AccountService { private RoleService roleService; /* public AccountService(RoleService roleService) { this.roleService = roleService; }*/ public void setRoleService(RoleService roleService) { this.roleService = roleService; } public void test() { System.out.println("AccountService Test..."); } } public class RoleService { private AccountService accountService; /* public RoleService(AccountService accountService) { this.accountService = accountService; }*/ public void setAccountService(AccountService accountService) { this.accountService = accountService; } public void test() { System.out.println("RoleService Test..."); } }
XML配置
<!-- <bean id="accountService" class="com.xxxx.service.AccountService"> <constructor-arg name="roleService" ref="roleService"/> </bean> <bean id="roleService" class="com.xxxx.service.RoleService"> <constructor-arg name="accountService" ref="accountService"/> </bean> --> <!--修改成set方法注入--> <bean id="accountService" class="com.xxxx.service.AccountService"> <property name="roleService" ref="roleService"/> </bean> <bean id="roleService" class="com.xxxx.service.RoleService"> <property name="accountService" ref="accountService"/> </bean>
定義靜態工廠類
public class StaticFactory { // 定義靜態方法 public static TypeDao createTypeDao() { return new TypeDao(); } }
Java代碼
public class TypeService { private TypeDao typeDao; public void setTypeDao(TypeDao typeDao) { this.typeDao = typeDao; } public void test() { System.out.println("TypeService Test..."); } }
XML配置
在配置文件中設置bean標籤,指定工廠對象並設置對應的方法
<bean id="typeService" class="com.xxxx.service.TypeService"> <property name="typeDao" ref="typeDao"/> </bean> <!-- 靜態工廠注入: 靜態工廠注入也是藉助set方法注入,只是被注入的bean對象的實例化是經過靜態工廠實例化的 --> <bean id="typeDao" class="com.xxxx.factory.StaticFactory" factory-method="createTypeDao"></bean>
定義工廠類
public class InstanceFactory { public TypeDao createTypeDao() { return new TypeDao(); } }
Java代碼
public class TypeService { private TypeDao typeDao; public void setTypeDao(TypeDao typeDao) { this.typeDao = typeDao; } public void test() { System.out.println("TypeService Test..."); } }
XML配置
聲明工廠bean標籤,聲明bean對象,指明工廠對象和工廠方法
<bean id="typeService" class="com.xxxx.service.TypeService"> <property name="typeDao" ref="typeDao"/> </bean> <!-- 實例化工廠注入: 實例化工廠注入也是藉助set方法注入,只是被注入的bean對象的實例化是經過實例化工廠實例化的 --> <bean id="instanceFactory" class="com.xxxx.factory.InstanceFactory"></bean> <bean id="typeDao" factory-bean="instanceFactory" factory-method="createTypeDao"></bean>
重點掌握set注入和構造器注入,工廠方式瞭解便可。實際開發中基本使用set方式注入bean。
開發項目中set方式注入首選
使用構造注入能夠在構建對象的同時一併完成依賴關係的創建,對象一創建則全部的一切也就準備好了,但若是要創建的對象關係不少,使用構造器注入會在構建函數上留下一長串的參數,且不易記憶,這時使用Set注入會是個不錯的選擇。
使用Set注入能夠有明確的名稱,能夠了解注入的對象會是什麼,像setXXX()這樣的名稱會比記憶Constructor上某個參數的位置表明某個對象更好。
p名稱空間的使用
spring2.5之後,爲了簡化setter方法屬性注入,引用p名稱空間的概念,能夠將 子元素,簡化爲元素屬性配置。
屬性字段提供 set 方法
public class UserService { // 業務對象UserDao set注入(提供set方法) private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } // 經常使用對象String set注入(提供set方法) private String host; public void setHost(String host) { this.host = host; } }
在配置文件 spring.xml 引入 p 名稱空間
xmlns:p="http://www.springframework.org/schema/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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userDao" class="com.xxxx.dao.UserDao"></bean> <!-- p:屬性名:="xxx" 引入常量值 p:屬性名-ref:="xxx" 引入其餘Bean對象的id屬性值 --> <bean id="userService" class="com.xxxx.service.UserService" p:userDao-ref="userDao" p:host="127.0.0.1" /> </beans>
註解方式注入 Bean
對於 bean 的注入,除了使用 xml 配置之外,可使用註解配置。註解的配置,能夠簡化配置文件,提升開發的速度,使程序看上去更簡潔。對於註解的解釋,Spring對於註解有專門的解釋器,對定義的註解進行解析,實現對應bean對象的注入。經過反射技術實現。
修改配置文件
<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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
開啓自動化注入
<!--開啓自動化裝配(注入)--> <context:annotation-config/> <bean id="userDao" class="com.xxxx.dao.UserDao"></bean> <bean id="userService" class="com.xxxx.service.UserService"></bean>
@Resource註解實現自動注入(反射)
代碼示例
默認根據屬性字段名稱查找對應的bean對象 (屬性字段的名稱與bean標籤的id屬性值相等)
/** * @Resource註解實現自動注入(反射) * 默認根據屬性字段名稱查找對應的bean對象 (屬性字段的名稱與bean標籤的id屬性值相等) */ public class UserService { @Resource private UserDao userDao; // 屬性字段的名稱與bean標籤的id屬性值相等 public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void test() { // 調用UserDao的方法 userDao.test(); } }
若是屬性字段名稱未找到,則會經過類型(Class類型)查找
/** * @Resource註解實現自動注入(反射) * 若是屬性字段名稱未找到,則會經過類型(Class類型)查找 */ public class UserService { @Resource private UserDao ud; // 當在配置文件中屬性字段名(ud)未找到,則會查找對應的class(UserDao類型) public void setUd(UserDao ud) { this.ud = ud; } public void test() { // 調用UserDao的方法 ud.test(); } }
屬性能夠提供set方法,也能夠不提供set方法
/** * @Resource註解實現自動注入(反射) * 屬性能夠提供set方法,也能夠不提供set方法 */ public class UserService { @Resource private UserDao userDao; // 不提供set方法 public void test() { // 調用UserDao的方法 userDao.test(); } }
註解能夠聲明在屬性級別 或 set方法級別
/** * @Resource註解實現自動注入(反射) * 註解能夠聲明在屬性級別 或 set方法級別 */ public class UserService { private UserDao userDao; @Resource // 註解也可設置在set方法上 public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void test() { // 調用UserDao的方法 userDao.test(); } }
能夠設置name屬性,name屬性值必須與bean標籤的id屬性值一致;若是設置了name屬性值,就只會按照name屬性值查找bean對象
/** * @Resource註解實現自動注入(反射) * 能夠設置name屬性,name屬性值必須與bean的id屬性值一致; * 若是設置了name屬性值,就只會按照name屬性值查找bean對象 */ public class UserService { @Resource(name = "userDao") // name屬性值與配置文件中bean標籤的id屬性值一致 private UserDao ud; public void test() { // 調用UserDao的方法 ud.test(); } }
當注入接口時,若是接口只有一個實現則正常實例化;若是接口存在多個實現,則須要使用name屬性指定須要被實例化的bean對象
定義接口類 IUserDao.java
package com.xxxx.dao; /** * 定義接口類 */ public interface IUserDao { public void test(); }
定義接口實現類 UserDao01.java
package com.xxxx.dao; /** * 接口實現類 */ public class UserDao01 implements IUserDao { @Override public void test(){ System.out.println("UserDao01..."); } }
定義接口實現類 UserDao02.java
package com.xxxx.dao; /** * 接口實現類 */ public class UserDao02 implements IUserDao { @Override public void test(){ System.out.println("UserDao02..."); } }
XML配置文件
<!--開啓自動化裝配(注入)--> <context:annotation-config/> <bean id="userService" class="com.xxxx.service.UserService"></bean> <bean id="userDao01" class="com.xxxx.dao.UserDao01"></bean> <bean id="userDao02" class="com.xxxx.dao.UserDao01"></bean>
使用註解 UserService.java
/** * @Resource註解實現自動注入(反射) * 當注入接口時,若是接口只有一個實現則正常實例化;若是接口存在多個實現,則須要使用name屬性指定須要被實例化的bean對象 */ public class UserService { @Resource(name = "userDao01") // name屬性值與其中一個實現類的bean標籤的id屬性值一致 private IUserDao iUserDao; // 注入接口(接口存在多個實現) public void test() { iUserDao.test(); } }
@Autowired註解實現自動化注入:
默認經過類型(Class類型)查找bean對象 與屬性字段的名稱無關
/** * @Autowired註解實現自動化注入 * 默認經過類型(Class類型)查找bean對象 與屬性字段的名稱無關 */ public class UserService { @Autowired private UserDao userDao; // 默認經過類型(Class類型)查找bean對象 與屬性字段的名稱無關 public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void test() { // 調用UserDao的方法 userDao.test(); } }
屬性能夠提供set方法,也能夠不提供set方法
/** * @Autowired註解實現自動化注入 * 屬性能夠提供set方法,也能夠不提供set方法 */ public class UserService { @Autowired private UserDao userDao; // 不提供set方法 public void test() { // 調用UserDao的方法 userDao.test(); } }
註解能夠聲明在屬性級別 或 set方法級別
/** * @Autowired註解實現自動化注入 * 註解能夠聲明在屬性級別 或 set方法級別 */ public class UserService { private UserDao userDao; @Autowired// 註解能夠聲明在set方法級別 public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void test() { // 調用UserDao的方法 userDao.test(); } }
能夠添加@Qualifier結合使用,經過value屬性值查找bean對象(value屬性值必需要設置,且值要與bean標籤的id屬性值對應)
/** * @Autowired註解實現自動化注入 * 能夠添加@Qualifier結合使用,經過value屬性值查找bean對象 value屬性值必需要設置,且值要與bean標籤的id屬性值對應 */ public class UserService { @Autowired @Qualifier(value="userDao") // value屬性值必需要設置,且值要與bean標籤的id屬性值對應 private UserDao userDao; public void test() { userDao.test(); } }
推薦使用@Resource 註解是屬於J2EE的,減小了與Spring的耦合。
實際的開發中,bean的數量很是多,採用手動配置bean的方式已沒法知足生產須要,Spring這時候一樣提供了掃描的方式,對掃描到的bean對象統一進行管理,簡化開發配置,提升開發效率。
Spring IOC 掃描器 做用:bean對象統一進行管理,簡化開發配置,提升開發效率 一、設置自動化掃描的範圍 若是bean對象未在指定包範圍,即便聲明瞭註解,也沒法實例化 二、使用指定的註解(聲明在類級別) bean對象的id屬性默認是 類的首字母小寫 Dao層: @Repository Service層: @Service Controller層: @Controller 任意類: @Component 注:開發過程當中建議按照指定規則聲明註解
設置自動化掃描範圍
<?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 https://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="com.xxxx"/> </beans>
使用特定的註解
@Repository (Dao層)
@Repository public class ResourceDao { public void test() { System.out.println("ResourceDao..."); } }
@Service(Service層 )
@Service public class ResourceService { @Resource private ResourceDao resourceDao; // service層注入dao層的bean對象 public void test() { System.out.println("ResourceService..."); resourceDao.test(); } }
@Controller (Controller 層 )
@Controller public class ResourceController { @Autowired private ResourceService resourceService; // Controller層注入service層的bean對象 public void test() { System.out.println("ResourceController..."); resourceService.test(); } }
@Component (任意層)
@Component public class PropertyUtils { public void test(){ System.out.println("PropertyUtils..."); } }
定義JavaBean User.java
package com.xxxx.po; /** * User 用戶實體類 */ public class User { private String userName; // 用戶名稱 private String userPwd; // 用戶密碼 public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getUserPwd() { return userPwd; } public void setUserPwd(String userPwd) { this.userPwd = userPwd; } }
編寫Dao層 UserDao.java
package com.xxxx.dao; import com.xxxx.po.User; import org.springframework.stereotype.Repository; @Repository public class UserDao { private final String USERNAME = "admin"; private final String USERPWD = "admin"; /** * 經過用戶名稱查詢用戶對象 * @param userName * @return */ public User queryUserByUserName(String userName){ User user = null; // 判斷用戶名稱是否正確 if(!USERNAME.equals(userName)){ // 若是不正確,返回null return null; } // 若是正確,將用戶名稱和密碼設置到user對象中 user = new User(); user.setUserName(USERNAME); user.setUserPwd(USERPWD); return user; } }
定義業務處理返回消息模型 MessageModel.java
package com.xxxx.po.vo; /** * 定義業務處理返回消息模型 * 封裝返回結果 */ public class MessageModel { private Integer resultCode = 1; // 結果狀態碼 1=成功,0=失敗 private String resultMsg = "操做成功!"; // 結果提示信息 public Integer getResultCode() { return resultCode; } public void setResultCode(Integer resultCode) { this.resultCode = resultCode; } public String getResultMsg() { return resultMsg; } public void setResultMsg(String resultMsg) { this.resultMsg = resultMsg; } }
編寫Service層 UserService.java
package com.xxxx.service; import com.xxxx.dao.UserDao1; import com.xxxx.po.User; import com.xxxx.po.vo.MessageModel; import org.springframework.stereotype.Service; import javax.annotation.Resource; @Service public class UserService { @Resource private UserDao userDao; /** * 驗證用戶登陸 * @param userName * @param userPwd * @return */ public MessageModel userLoginCheck(String userName, String userPwd){ // 定義業務處理返回消息模型 MessageModel messageModel = new MessageModel(); // 判斷用戶名稱是否非空 if(null == userName || "".equals(userName.trim())){ messageModel.setResultCode(0); messageModel.setResultMsg("用戶名不能爲空!"); return messageModel; } // 判斷用戶密碼是否爲空 if(null == userPwd || "".equals(userPwd.trim())){ messageModel.setResultCode(0); messageModel.setResultMsg("密碼不能爲空!"); return messageModel; } // 經過用戶名稱查詢用戶對象 User user = userDao.queryUserByUserName(userName); // 判斷用戶對象是否爲空 if(null == user){ messageModel.setResultCode(0); messageModel.setResultMsg("該用戶不存在!"); return messageModel; } // 若是用戶對象不爲空,判斷密碼是否正確 if(!user.getUserPwd().equals(userPwd)){ messageModel.setResultCode(0); messageModel.setResultMsg("用戶密碼不正確!"); return messageModel; } // 登陸成功 messageModel.setResultMsg("登陸成功!"); return messageModel; } }
編寫Controller層 UserController.java
package com.xxxx.controller; import com.xxxx.po.vo.MessageModel; import com.xxxx.service.UserService1; import org.springframework.stereotype.Controller; import javax.annotation.Resource; @Controller public class UserController { @Resource private UserService userService; /** * 用戶登陸 * @param userName * @param userPwd * @return */ public MessageModel login(String userName, String userPwd){ // 調用Dao層判斷用戶登陸操做,返回結果 MessageModel messageModel = userService.userLoginCheck(userName, userPwd); return messageModel; } }
package com.xxxx; import com.xxxx.controller.UserController; import com.xxxx.po.vo.MessageModel; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestLogin { @Test public void test() { // 獲得Spring容器上下文環境 ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml"); // 獲得UserController實例化對象 UserController userController = (UserController) ac.getBean("userController"); // 傳入參數調用UserController的方法,返回封裝類 MessageModel messageModel= userController.login("admin", "admin"); System.out.println("狀態碼:" + messageModel.getResultCode() + ",提示信息:" + messageModel.getResultMsg()); } }
默認狀況下,咱們從Spring容器中拿到的對象均是單例的,對於bean的做用域類型以下:
注意: lazy-init是懶加載, 若是等於true時做用是指Spring容器啓動的時候不會去實例化這個bean, 而是在程序調用時纔去實例化. 默認是false即Spring容器啓動時實例化.
默認狀況下,被管理的bean只會IOC容器中存在一個實例,對於全部獲取該Bean的操做Spring容器將只返回同一個Bean。
容器在啓動的狀況下就實例化全部singleton 的 bean對象,並緩存與容器中
lazy-init屬性(懶加載)
若是爲false,則在IOC容器啓動時會實例化bean對象,默認false
若是爲true,則IOC容器啓動時不會實例化Bean對象,在使用bean對象時纔會實例化
lazy-init設置爲false有什麼好處?
1)能夠提早發現潛在的配置問題
2)Bean 對象存在於緩存中,使用時不用再去實例化bean,加快程序運行效率
什麼對象適合做爲單例對象?
通常來講對於無狀態或狀態不可改變的對象適合使用單例模式。(不存在會改變對象狀態的成員變量)
好比:controller層、service層、dao層
什麼是無狀態或狀態不可改變的對象?
實際上對象狀態的變化每每均是因爲屬性值得變化而引發的,好比user類 姓名屬性會有變化,屬性姓名的變化通常會引發user對象狀態的變化。對於咱們的程序來講,無狀態對象沒有實例變量的存在,保證了線程的安全性,service 層業務對象便是無狀態對象。線程安全的。
經過scope=「prototype」 設置bean的類型 ,每次向Spring容器請求獲取Bean都返回一個全新的Bean,相對於"singleton"來講就是不緩存Bean,每次都是一個根據Bean定義建立的全新Bean。
表示每一個請求須要容器建立一個全新Bean。好比提交表單的數據必須是對每次請求新建一個Bean來保持這些表單數據,請求結束釋放這些數據。
表示每一個會話須要容器建立一個全新Bean。好比對於每一個用戶通常會有一個會話,該用戶的用戶信息須要存儲到會話中,此時能夠將該Bean做用域配置爲session級別。
相似於session做用域,其用於portlet(Portlet是基於Java的Web組件,由Portlet容器管理,並由容器處理請求,生產動態內容)環境的web應用。若是在非portlet環境將視爲session做用域。
配置方式和基本的做用域相同,只是必需要有web環境支持,並配置相應的容器監聽器或攔截器從而能應用這些做用域,目前先熟悉概念,後續集成web時講解具體使用,你們只須要知道有這些做用域就能夠了。
對比已經學過的servlet 生命週期(容器啓動裝載並實例化servlet類,初始化servlet,調用service方法,銷燬servlet)。
一樣對於Spring容器管理的bean也存在生命週期的概念
在Spring中,Bean的生命週期包括Bean的定義、初始化、使用和銷燬4個階段
在Spring中,一般是經過配置文檔的方式來定義Bean的。
在一個配置文檔中,能夠定義多個Bean。
默認在IOC容器加載時,實例化對象。
Spring bean 初始化有兩種方式:
方式一:在配置文檔中經過指定 init-method 屬性來完成。
public class RoleService { // 定義初始化時須要被調用的方法 public void init() { System.out.println("RoleService init..."); } }
<!-- 經過init-method屬性指定方法 --> <bean id="roleService" class="com.xxxx.service.RoleService" init-method="init"></bean>
方式二: 實現 org.springframework.beans.factory.InitializingBean 接口。
public class RoleService implements InitializingBean { @Override public void afterPropertiesSet() throws Exception { System.out.println("RoleService init..."); } }
<bean id="roleService" class="com.xxxx.service.RoleService" ></bean>
Bean對象實例化過程是在Spring容器初始化時被實例化的,但也不是不可改變的,能夠經過 lazy-init=「true」 屬性延遲bean對象的初始化操做,此時再調用getBean 方法時纔會進行bean的初始化操做
方式一:使用 BeanFactory
// 獲得Spring的上下文環境 BeanFactory factory = new ClassPathXmlApplicationContext("spring.xml"); RoleService roleService = (RoleService) factory.getBean("roleService");
方式二:使用 ApplicationContext
// 獲得Spring的上下文環境 ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml"); RoleService roleService = (RoleService) ac.getBean("roleService");
實現銷燬方式(Spring容器會維護bean對象的管理,能夠指定bean對象的銷燬所要執行的方法)。
步驟一:實現銷燬方式(Spring容器會維護bean對象的管理,能夠指定bean對象的銷燬所要執行的方法)
<bean id="roleService" class="com.xxxx.service.RoleService" destroy-method="destroy"></bean>
**步驟二:**經過 AbstractApplicationContext 對象,調用其close方法實現bean的銷燬過程
AbstractApplicationContext ctx=new ClassPathXmlApplicationContext("spring.xml"); ctx.close();
IOC/DI-控制反轉和依賴注入 將對象實例化的建立過程轉交給外部容器(IOC容器 充當工廠角色)去負