Spring概述
什麼是Spring?
Spring是目前比較火的一個全棧輕量級的開源框架,以ICO(Inverse Of Control 即控制反轉)和AOP(Aspect Oriented Programming 即面向切面編程)爲核心,以能夠黏合各大第三方框架著稱,是現在Java EE企業中應用最多的框架之一。
Spring的發展
Spring的發展與EJB(Enterprise Java Beans)的發展離不開關係,它的出現可以說是爲了解決EJB在J2EE中的開發的問題。
1997 年 IBM 提出了 EJB 的思想
1998 年, SUN 制定開發標準規範 EJB1.0
Rod Johnson(spring 之父)深入研究了EJB在實際開發中存在的問題,於2017 年 9 月份發佈了 spring 的最新版本 spring 5.0 通用版(GA)
Spring的優點
Spring在實際開發中具有以下的優點:
方便解耦,簡化開發 | 通過IOC機制在很大程度上削減了程序的耦合。 |
---|---|
AOP 編程的支持 | 可以彌補傳統的OOP編程的短板 |
聲明式事務的支持 | 通過聲明式方式靈活的進行事務的管理 |
方便程序的測試 | 用非容器依賴的編程方式進行幾乎所有的測試工作 |
方便集成各種優秀框架 | 提供了對各種優秀框架的直接支持 |
降低 JavaEE API 的使用難度 | Spring 對 JavaEE API進行了封裝,使這些 API 的使用難度大爲降低 |
Spring的體系結構
這是從spring官網下載的圖片
Spring IOC
什麼是耦合?
耦合是對模塊間關聯程度的度量,是指模塊之間的依賴關係,包括控制關係、調用關係、數據傳遞關係。模塊間聯繫越多,其耦合性越強,同時表明其獨立性越差,在軟件工程中,耦合指的就是就是對象之間的依賴性。對象之間的耦合越高,維護成本越高。因此對象的設計應使類和構件之間的耦合最小。
什麼是Spring IOC?
IOC是spring的一種核心機制,全稱Inversion of Control即控制反轉,它將對象創建的工作交給了框架控制,取代了傳統的對象內部控制,示圖如下:
傳統模式
IOC模式
SpringIOC的作用
削減計算機程序的耦合(解除我們代碼中的依賴關係),但是隻能做到削減,不能做到消除。 實際開發中應該做到:編譯期不依賴,運行時才依賴。
解耦的思路:
- 第一步:使用反射來創建對象,而避免使用new關鍵字。
- 第二步:通過讀取配置文件來獲取要創建的對象全限定類名
Spring IOC的核心容器(ApplicationContext+BeanFactory)
BeanFactory和Application的區別:
聯繫:
BeanFactory 是 Spring 容器中的頂層接口。
ApplicationContext 是它的子接口。
區別:
ApplicationContext:只要一讀取配置文件,默認情況下就會創建對象。
BeanFactory:什麼使用什麼時候創建對象
ApplicationContext的三個常用實現子類
- ClassPathXmlApplicationContext:它可以加載類路徑下的配置文件,但配置文件必須在類路徑下。不然加載不了,較爲常用。
- FileSystemXmlApplicationContext:它可以加載磁盤任意路徑下的配置文件,但需要全路徑。
- AnnotationConfigApplicationContext:它是用於讀取註解創建容器的。
用核心容器創建Bean對象:
1.創建核心容器關聯相應的配置文件
2.使用核心容器根據id獲取對象
1.BeanFactory
Resource resource=new ClassPathResource("bean.xml");
BeanFactory beanFactory=new XmlBeanFactory(resource);
AccoutService accoutService = (AccoutService)beanFactory.getBean("accoutService");
AccoutService accoutService1 = (AccoutService)beanFactory.getBean("accoutService");
System.out.println(accoutService==accoutService1);
2.ApplicationContext
ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
AccoutService accoutService = (AccoutService)ac.getBean("accoutService");
AccoutDao dao=(AccoutDao)ac.getBean("accoutDao",AccoutDao.class);
System.out.println(accoutService);
System.out.println(dao);
Spring實例化Bean的三種方式
1.使用默認構造函數創建
在spring的配置文件中使用bean標籤,配以id和class屬性之後,且沒有其他屬性和標籤時,採用的就是默認構造函數創建bean對象,此時如果類中沒有默認構造函數,則對象無法創建。
<bean id="accountService" class="com.gzgs.service.impl.AccountServiceImpl"></bean>
2.使用工廠的模式創建
<bean id="inStanceFactory" class="com.gzgs.factory.InstanceFactory"></bean>
<bean id="accoutService" factory-bean="inStanceFactory" factory-method="getAccountService"></bean>
3.使用工廠中的靜態方法創建對象
<bean id="accountService" class="com.gzs.factory.StaticFactory" factory-method="getAccountService"></bean>
Spring Bean
Spring Bean的作用範圍
bean標籤的scope屬性:
作用:用於指定bean的作用範圍
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl" scope="prototype"></bean>
scope屬性取值:
singleton:單例的(默認)
prototype:多例的
request:作用於web應用的請求範圍
session:作用於web應用的會話範圍
global-session:作用於集羣環境的會話範圍(全局會話範圍),當不是集羣環境時,它就是session
常用的就是單例的和多例的
Spring Bean的生命週期
單例對象
出生:當容器創建時對象出生
活着:只要容器還在,對象一直活着
死亡:容器銷燬,對象消亡
總結:單例對象的生命週期和容器相同
多例對象
出生:當我們使用對象時spring框架爲我們創建
活着:對象只要是在使用過程中就一直活着。
死亡:當對象長時間不用,且沒有別的對象引用時,由Java的垃圾回收器回收
Spring的依賴注入
依賴注入(Dependency Injection)在當前類需要用到其他類的對象,由spring爲我們提供,我們只需要在配置文件中說明依賴關係的維護,這就是依賴注入。
依賴注入能實現的入住類型
- 基本類型和String
- 其他在註解配置過或在配置文件中的bean類型
- 複雜類型/集合類型
依賴注入的方式
- 使用構造函數注入
- 使用set方法注入
- 使用註解注入
使用構造函數注入
使用的標籤:constructor-arg
標籤出現的位置:bean標籤的內部
標籤中的屬性
type:用於指定要注入的數據的數據類型,該數據類型也是構造函數中某個或某些參數的類型
index:用於指定要注入的數據給構造函數中指定索引位置的參數賦值。索引的位置是從0開始
name:用於指定給構造函數中指定名稱的參數賦值
value:用於提供基本類型和String類型的數據
ref:用於指定其他的bean類型數據。它指的就是在spring的Ioc核心容器中出現過的bean對象
- 優勢:
在獲取bean對象時,注入數據是必須的操作,否則對象無法創建成功。 - 弊端:
改變了bean對象的實例化方式,使我們在創建對象時,如果用不到這些數據,也必須提供。
代碼示例
<bean id="accoutService" class="com.gzgs.service.impl.AccoutServiceImpl">
<constructor-arg name="name" value="張三"></constructor-arg>
<constructor-arg name="age" value="15"></constructor-arg>
<constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>
<bean id="now" class="java.util.Date"></bean>
使用set方法注入
涉及的標籤:property
出現的位置:bean標籤的內部
標籤的屬性
name:用於指定注入時所調用的set方法名稱
value:用於提供基本類型和String類型的數據
ref:用於指定其他的bean類型數據。它指的就是在spring的Ioc核心容器中出現過的bean對象
優勢:
創建對象時沒有明確的限制,可以直接使用默認構造函數,有要求在Bean的方法中要有set方法。
弊端:
如果有某個成員必須有值,則獲取對象是有可能set方法沒有執行。
代碼示例
<bean id="now" class="java.util.Date"></bean>
<bean id="accoutService" class="com.gzgs.service.impl.AccoutServiceImpl">
<property name="name" value="李四"></property>
<property name="age" value="18"></property>
<property name="birthday" ref="now"></property>
</bean>
複雜類型的注入/集合類型的注入
用於給List結構集合注入的標籤:
< list> < array> < set>
用於個Map結構集合注入的標籤:
< map> < props>
如果結構相同,標籤可以互換,如list、array、set
代碼示例
<bean id="accoutService" class="com.gzgs.service.impl.AccoutServiceImpl">
<property name="myStrs">
<set>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</set>
</property>
<property name="myList">
<array>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</array>
</property>
<property name="mySet">
<list>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</list>
</property>
<property name="myMap">
<props>
<prop key="testC">ccc</prop>
<prop key="testD">ddd</prop>
</props>
</property>
<property name="myProps">
<map>
<entry key="testA" value="aaa"></entry>
<entry key="testB">
<value>BBB</value>
</entry>
</map>
</property>
</bean>