Spring淺入淺出——不吹牛逼不裝逼
前言:
今天決定要開始總結框架了,雖然以前總結過兩篇,但是思維是變化的,而且也沒有什麼規定說總結過的東西就不能再總結了,是吧。這次總結我命名為淺入淺出,主要在於理解框架核心,輕鬆愉快使用框架。
核心思想
我們都學了物件導向,在生活中,當人們需要一件東西時,第一反應就是找東西,例如想吃麵包,現在有兩種情況,第一種是沒有面包店,第二種是有面包店。第一種情況就是我們之前一直遇到的情況,在沒有面包店的情況下,最直觀的做法可能就是你按照自己的口味製作麵包,也就是一個麵包需要主動製作,誰想吃了就自己New。而我主要說的是第二種情況,就是有面包店,你想吃麵包的時候找到麵包店,把自己的口味告訴店家,店家就可以給你做符合你口味的麵包了。注意:你並沒有製作麵包,而是由店家制作,但是完全符合你的口味。
這是一個很生活的例子,大家都明白,但這裡包含了Spring中很重要的思想——控制反轉,就是把製作麵包的主動權交給店家,麵包就是物件,店家相當於一個大容器,你想要什麼物件,就讓大容器去給你生產,這就是控制反轉思想。
再詳細點,當某個Java物件(呼叫者,例如你)需要呼叫另一個Java物件(被呼叫者,即被依賴物件,例如麵包)時,在傳統程式設計模式下,呼叫者通常會採用“New 被呼叫者”的程式碼方式來建立物件(例如你自己製作麵包)。這種方式會增加呼叫者與被呼叫者之間的耦合性,不利於後期程式碼的升級和維護。
當Spring框架出現後,物件的例項不再由呼叫者來建立,而是由 Spring容器(例如麵包店)來建立。Spring容器會負責控制程式之間的關係(例如麵包店負責控制你與麵包的關係),而不是由呼叫者的程式程式碼直接控制。這樣,控制權由呼叫者轉移到Spring容器,控制權發生了反轉,這就是Spring的控制反轉。
在之前,我們需要用構造方法或者set()方法給一些成員變數賦值,從Spring容器角度來看,Spring容器負責將被依賴物件賦值給呼叫者的成員變數,相當於為呼叫者注入它所依賴的例項,這就是Spring的依賴注入。
綜上所述,控制反轉是一種通過描述(在Spring中可以是XML或註解)並通過第三方去產生或獲取特定物件的方式。在Spring中實現控制反轉的是IoC容器,其實現方法是依賴注入。
Spring IoC容器
看完上面所述,我們知道實現控制反轉的是Spring IoC容器。Spring IoC容器的設計主要是基於BeanFactory和ApplicationContext兩個介面。
先說BeanFactory,它提供了完整的IoC服務支援,是一個管理Bean的工廠,主要負責初始化各種Bean。BeanFactory介面有多個實現類,其中比較常用的是org.springframework.beans.factory.xml.XmlBeanFactory,該類會根據XML配置檔案中的定義來裝配Bean.由於BeanFactory例項載入Spring配置檔案在實際開發中並不多見,只需瞭解即可,我也不過多解說了。
再說ApplicationContext,它是BeanFactory的子介面,也稱為應用上下文,ApplicationContext介面除了包含BeanFactory的所有功能以外,還新增了對國際化、資源訪問、事件傳播等內容的支援。建立ApplicationContext介面例項通常有三種方法:
1、 通過ClassPathXmlApplicationContext建立
2、 通過FileSystemXmlApplicatonContext建立
3、 通過Web伺服器例項化ApplicationContext容器
作為一個初學者,我覺得先會用第一種就可以了,所以我主要解說第一種,別的等你自己入門後自己看,我只做引導。
ClassPathXmlApplicationContext將從類路徑目錄(src根目錄)中尋找指定的XML配置檔案,如下程式碼:
public class Test { public static void main(String[] args) { //初始化SPring容器,載入配置檔案 ApplicationContext appCon = new ClassPathXmlApplicationContext("spring-config.xml"); //通過容器獲得test例項 TestDao tt = (TestDao) appCon.getBean("test"); tt.sayHello(); } }
依賴注入的型別
在Spring中實現IoC容器的方法是依賴注入,依賴注入的作用是在使用Spring框架建立物件時動態地將其所依賴的物件(例如屬性值)注入Bean元件中,Spring框架的依賴注入通常有兩種實現方式,一種是使用構造方法注入,另一種是使用屬性的setter方法注入。具體且看例項演示
例項演示
一、在pom.xml中匯入相應模組
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> <!--spring核心依賴--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>5.1.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.1.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.1.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.1.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>5.1.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.1.5.RELEASE</version> </dependency> </dependencies>
二、建立TestDao
package com.my.dao; public interface TestDao { public void sayHello(); }
三、建立TestDaoImpl
package com.my.dao.impl; import com.my.dao.TestDao; public class TestDaoImpl implements TestDao { @Override public void sayHello() { System.out.println("Hello Spring!!!"); } }
四、建立spring-config.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" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc" 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 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd "> <bean id="testDIDao" class="com.my.dao.impl.TestDaoImpl"/> </beans>
五、測試Test
package com.my.test; import com.my.dao.TestDao; import com.my.dao.impl.TestDaoImpl; import com.my.service.TestService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { //呼叫者自己建立物件 TestDao testDao = new TestDaoImpl(); testDao.sayHello(); //初始化SPring容器,載入配置檔案 ApplicationContext appCon = new ClassPathXmlApplicationContext("spring-config.xml"); //通過容器獲得test例項 TestDao tt = (TestDao) appCon.getBean("testDIDao"); tt.sayHello(); } }
六、測試結果
七、建立TestService
package com.my.service; public interface TestService { public void sayHello(); }
八、建立TestServiceImpl
package com.my.service.impl; import com.my.dao.TestDao; import com.my.service.TestService; public class TestServiceImpl implements TestService { private TestDao testDao; //構造方法,用於實現依賴注入介面物件TestDao public TestServiceImpl(TestDao testDao) { this.testDao = testDao; } @Override public void sayHello() { testDao.sayHello(); } }
九、在spring-config.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" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc" 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 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd "> <!--將指定類TestDaoImpl配置給Spring,讓Spring建立其例項--> <bean id="testDIDao" class="com.my.dao.impl.TestDaoImpl"/> <!--使用構造方法注入--> <bean id="testDIService" class="com.my.service.impl.TestServiceImpl" > <!--將TestDIDao注入到TestDIServiceImpl類的屬性testDao上--> <constructor-arg index="0" ref="testDIDao"/> </bean> </beans>
十、測試Test
package com.my.test; import com.my.dao.TestDao; import com.my.dao.impl.TestDaoImpl; import com.my.service.TestService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { //呼叫者自己建立物件 TestDao testDao = new TestDaoImpl(); testDao.sayHello(); //初始化SPring容器,載入配置檔案 ApplicationContext appCon = new ClassPathXmlApplicationContext("spring-config.xml"); //通過容器獲得test例項 TestDao tt = (TestDao) appCon.getBean("testDIDao"); tt.sayHello(); //通過容器獲取TestService例項,測試構造方法注入 TestService testService =(TestService) appCon.getBean("testDIService"); testService.sayHello(); } }
十一、測試結果
十二、使用屬性的setter方法注入
package com.my.service.impl; import com.my.dao.TestDao; import com.my.service.TestService; public class TestServiceImpl implements TestService { private TestDao testDao; //新增testDao屬性的setter方法,用於實現依賴注入 public void setTestDao(TestDao testDao){ this.testDao=testDao; } @Override public void sayHello() { testDao.sayHello(); } }
十三、在spring-config.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" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc" 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 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd "> <!--將指定類TestDaoImpl配置給Spring,讓Spring建立其例項--> <bean id="testDIDao" class="com.my.dao.impl.TestDaoImpl"/> <!--使用setter方法注入--> <bean id="testDIService" class="com.my.service.impl.TestServiceImpl"> <!--呼叫TestDIServiceImpl類的setter方法,將TestDao注入到TestServiceImpl類的屬性testDao上--> <property name="testDao" ref="testDIDao"></property> </bean> </beans>
十四、測試Test
package com.my.test; import com.my.dao.TestDao; import com.my.dao.impl.TestDaoImpl; import com.my.service.TestService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { //呼叫者自己建立物件 TestDao testDao = new TestDaoImpl(); testDao.sayHello(); //初始化SPring容器,載入配置檔案 ApplicationContext appCon = new ClassPathXmlApplicationContext("spring-config.xml"); //通過容器獲得test例項 TestDao tt = (TestDao) appCon.getBean("testDIDao"); tt.sayHello(); //通過容器獲取TestService例項,測試setter方法注入 TestService testService =(TestService) appCon.getBean("testDIService"); testService.sayHello(); } }
十五、測試結果
注入說明
在Src根目錄下建立Spring配置檔案spring-config.xml(檔名隨意,注意字尾.xml)。在配置檔案中,constructor-arg元素用於定義類構造方法的引數,index用於定義引數的位置,ref指定某個例項的引用,如果引數是常量值,ref由value代替。
特別連結
看完此篇後你覺得理解了,可以看看我以前寫的這幾篇部落格,會有幫助的
《沒有無緣無故的程式設計》https://www.cnblogs.com/zyx110/p/11297822.html
《路過別錯過》https://www.cnblogs.com/zyx110/p/11271820.html
《spring框架知多少》https://www.cnblogs.com/zyx110/p/11022891.html
《用IDEA開發Spring程式》https://www.cnblogs.com/zyx110/p/11023218.html
結束語
此篇Spring淺入淺出到此結束,作此篇是為了讓初學者放下心理枷鎖,先理解,其實挺好理解的,等你有信心後自己學習就可以了,希望能對一些朋友有所幫助,加油。
*****************************************************************************************************
我的部落格園地址:https://www.cnblogs.com/zyx110/
轉載請說明出處
我不能保證我所說的都是對的,但我能保證每一篇都是用心去寫的,我始終認同“分享的越多,你的價值增值越大”,歡迎大家關注我的技術分享“Java匹馬行天下”和學習心得分享“匹馬行天下”,在分享中進步,越努力越幸運,人生贏在轉折處,改變從現在開始!
支援我的朋友們記得點波推薦哦,您的肯定就是我前進的動力。