1.spring介紹java
Spring 是分層的 Java SE/EE 應用 full-stack 輕量級開源框架,以 IoC(Inverse Of Control: 反轉控制)和 AOP(Aspect Oriented Programming:面向切面編程)爲內核,提供了展示層 Spring MVC 和持久層 Spring JDBC 以及業務層事務管理等衆多的企業級應用技術,還能整合開源世界衆多著名的第三方框架和類庫,逐漸成爲使用最多的 Java EE 企業應用開源框架。web
2.Spring的優點spring
(1)方便解耦,簡化開發編程
經過 Spring 提供的 IoC 容器,能夠將對象間的依賴關係交由 Spring 進行控制,避免硬編碼所形成的過分程序耦合。用戶也沒必要再爲單例模式類、屬性文件解析等這些很底層的需求編寫代碼,可 以更專一於上層的應用。設計模式
(2)AOP 編程的支持tomcat
經過 Spring 的 AOP 功能,方便進行面向切面的編程,許多不容易用傳統 OOP 實現的功能能夠經過 AOP 輕鬆應付。session
(3)聲明式事務的支持數據結構
能夠將咱們從單調煩悶的事務管理代碼中解脫出來,經過聲明式方式靈活的進行事務的管理, 提升開發效率和質量。框架
(4)方便程序的測試maven
能夠用非容器依賴的編程方式進行幾乎全部的測試工做,測試再也不是昂貴的操做,而是隨手可作的事情。
(5)方便集成各類優秀框架
Spring 能夠下降各類框架的使用難度,提供了對各類優秀框架(Struts、Hibernate、Hessian、Quartz 等)的直接支持。
(6)下降 JavaEE API 的使用難度
Spring 對 JavaEE API(如 JDBC、JavaMail、遠程調用等)進行了薄薄的封裝層,使這些 API 的使用難度大爲下降。
(7)Java 源碼是經典學習範例
Spring 的源代碼設計精妙、結構清晰、匠心獨用,到處體現着大師對 Java 設計模式靈活運用以及對 Java 技術的高深造詣。它的源代碼無心是 Java 技術的最佳實踐的範例。
3.Spring的體系結構
4.耦合性介紹
耦合性(Coupling),也叫耦合度,是對模塊間關聯程度的度量。耦合的強弱取決於模塊間接口的複雜性、調用模塊的方式以及經過界面傳送數據的多少。模塊間的耦合度是指模塊之間的依賴關係,包括控制關係、調用關係、數據傳遞關係。模塊間聯繫越多,其耦合性越強,同時代表其獨立性越差( 下降耦合性,能夠提升其獨立性)。耦合性存在於各個領域,而非軟件設計中獨有的,可是咱們只討論軟件工程中的耦合。
在軟件工程中,耦合指的就是就是對象之間的依賴性。對象之間的耦合越高,維護成本越高。所以對象的設計應使類和構件之間的耦合最小。軟件設計中一般用耦合度和內聚度做爲衡量模塊獨立程度的標準。劃分模塊的一個準則就是高內聚低耦合。
(1)內容耦合。當一個模塊直接修改或操做另外一個模塊的數據時,或一個模塊不經過正常入口而轉入另外一個模塊時,這樣的耦合被稱爲內容耦合。內容耦合是最高程度的耦合,應該避免使用之。
(2)公共耦合。兩個或兩個以上的模塊共同引用一個全局數據項,這種耦合被稱爲公共耦合。在具備大量公共耦合的結構中,肯定到底是哪一個模塊給全局變量賦了一個特定的值是十分困難的。
(3) 外部耦合 。一組模塊都訪問同一全局簡單變量而不是同一全局數據結構,並且不是經過參數表傳遞該全局變量的信息,則稱之爲外部耦合。
(4) 控制耦合 。一個模塊經過接口向另外一個模塊傳遞一個控制信號,接受信號的模塊根據信號值而進行適當的動做,這種耦合被稱爲控制耦合。
(5)標記耦合 。若一個模塊 A 經過接口向兩個模塊 B 和 C 傳遞一個公共參數,那麼稱模塊 B 和 C 之間存在一個標記耦合。
(6) 數據耦合。模塊之間經過參數來傳遞數據,那麼被稱爲數據耦合。數據耦合是最低的一種耦合形式,系統中通常都存在這種類型的耦合,由於爲了完成一些有意義的功能,每每須要將某些模塊的輸出數據做爲另外一些模塊的輸入數據。
(7) 非直接耦合 。兩個模塊之間沒有直接關係,它們之間的聯繫徹底是經過主模塊的控制和調用來實現的。
總之,耦合是影響軟件複雜程度和設計質量的一個重要因素,在設計上咱們應採用如下原則:若是模塊間必須存在耦合,就儘可能使用數據耦合,少用控制耦合,限制公共耦合的範圍,儘可能避免使用內容耦合。
4.程序的耦合
耦合:程序間的依賴關係
包括:
類之間的依賴
方法間的依賴
解耦:下降程序間的依賴關係
實際開發中:應該作到:編譯期不依賴,運行時才依賴。
解耦的思路:
第一步:使用反射來建立對象,而避免使用new關鍵字。
第二步:經過讀取配置文件來獲取要建立的對象全限定類名
5.IOC原理
Inverse Of Control: 反轉控制
原來:咱們在獲取對象時,都是採用 new 的方式。是主動的。
如今:咱們獲取對象時,同時跟工廠要,有工廠爲咱們查找或者建立對象。是被動的。
這種被動接收的方式獲取對象的思想就是控制反轉,它是 spring 框架的核心之一。
明確 ioc 的做用:削減計算機程序的耦合(解除咱們代碼中的依賴關係)。
5.spring基於XML的IOC環境搭建和入門
spring5 版本是用 jdk8編寫的,因此要求咱們的 jdk 版本是 8 及以上。同時 tomcat 的版本要求 8.5及以上。
(1)建立一個maven的純java工程,在pom文件中,添加spring依賴
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.2.RELEASE</version> </dependency> </dependencies>
(2)建立業務層接口和實現類
<1>業務層接口
package service; /** * 帳戶業務層的接口 */ public interface IAccountService { /** * 模擬保存帳戶 */ void saveAccount(); }
<2>實現類
package service.impl; import dao.IAccountDao; import dao.impl.AccountDaoImpl; import service.IAccountService; /** * 帳戶的業務層實現類 */ public class AccountServiceImpl implements IAccountService { private IAccountDao accountDao = new AccountDaoImpl(); public void saveAccount(){ accountDao.saveAccount(); } }
(3)建立持久層接口和實現類
<1>持久層接口
package dao; /** * 帳戶的持久層接口 */ public interface IAccountDao { /** * 模擬保存帳戶 */ void saveAccount(); }
<2>實現類
package dao.impl; import dao.IAccountDao; /** * 帳戶的持久層實現類 */ public class AccountDaoImpl implements IAccountDao { public void saveAccount(){ System.out.println("保存了帳戶"); } }
(4)建立bean.xml,讓 spring 管理資源,在配置文件中配置 service 和 dao
<!--把對象的建立交給spring來管理-->
spring對bean的管理細節
1.建立bean的三種方式
2.bean對象的做用範圍
3.bean對象的生命週期
(1)建立Bean的兩種方式
第一種方式:使用默認構造函數建立。
在spring的配置文件中使用bean標籤,配以id和class屬性以後,且沒有其餘屬性和標籤時。
採用的就是默認構造函數建立bean對象,此時若是類中沒有默認構造函數,則對象沒法建立。注意:這裏說的沒有默認構造函數,是指構造函數被修改,而默認的構造函數又沒有。
下面的代碼是沒有默認的構造函數的:
package service.impl; import dao.IAccountDao; import dao.impl.AccountDaoImpl; import service.IAccountService; /** * 帳戶的業務層實現類 */ public class AccountServiceImpl implements IAccountService {//帶參數的構造函數 public AccountServiceImpl(String name) { } public void saveAccount(){ //accountDao.saveAccount(); System.out.println("AccountServiceImpl中的saveAccount方法執行了"); } }
下面的代碼是有構造函數的。
package service.impl; import dao.IAccountDao; import dao.impl.AccountDaoImpl; import service.IAccountService; /** * 帳戶的業務層實現類 */ public class AccountServiceImpl implements IAccountService { //默認的構造函數 public AccountServiceImpl() { } //帶參數的構造函數 public AccountServiceImpl(String name) { } public void saveAccount(){ //accountDao.saveAccount(); System.out.println("AccountServiceImpl中的saveAccount方法執行了"); } }
注意:如下的代碼是有默認的構造方法的
package service.impl; import dao.IAccountDao; import dao.impl.AccountDaoImpl; import service.IAccountService; /** * 帳戶的業務層實現類 */ public class AccountServiceImpl implements IAccountService { public void saveAccount(){ //accountDao.saveAccount(); System.out.println("AccountServiceImpl中的saveAccount方法執行了"); } }
使用默認構造函數建立的配置方式:
<bean id="accountDao" class="dao.impl.AccountDaoImpl"></bean>
第二種方式: 使用普通工廠中的方法建立對象(使用某個類中的方法建立對象,並存入spring容器)
InstanceFactory.java這個類模擬一個工廠類,建立jar包找那個的某個類的對象。
package factory; import service.IAccountService; import service.impl.AccountServiceImpl; /** * 模擬一個工廠類(該類多是存在於jar包中的,咱們沒法經過修改源碼的方式來提供默認構造函數) */ public class InstanceFactory { public IAccountService getAccountService(){ return new AccountServiceImpl(); } }
使用普通工廠中的方法建立對象的配置方法:
<!--第二種方式: 使用普通工廠中的方法建立對象(使用某個類中的方法建立對象,並存入spring容器)--> <bean id="instanceFactory" class="factory.InstanceFactory"></bean> <bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>
(2)bean的做用範圍調整
bean標籤的scope屬性:
做用:用於指定bean的做用範圍
取值: 經常使用的就是單例的和多例的
singleton:單例的(默認值)
prototype:多例的
request:做用於web應用的請求範圍
session:做用於web應用的會話範圍
global-session:做用於集羣環境的會話範圍(全局會話範圍),當不是集羣環境時,它就是session
<bean id="accountService" class="service.impl.AccountServiceImpl" scope="prototype"></bean>
測試效果:
package ui; import dao.IAccountDao; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import service.IAccountService; import service.impl.AccountServiceImpl; /** * 模擬一個表現層,用於調用業務層 */ public class Client { /** * 獲取spring的Ioc核心容器,並根據id獲取對象 * * ApplicationContext的三個經常使用實現類: * ClassPathXmlApplicationContext:它能夠加載類路徑下的配置文件,要求配置文件必須在類路徑下。不在的話,加載不了。(更經常使用) * FileSystemXmlApplicationContext:它能夠加載磁盤任意路徑下的配置文件(必須有訪問權限) * * AnnotationConfigApplicationContext:它是用於讀取註解建立容器的,是明天的內容。 * * 核心容器的兩個接口引起出的問題: * ApplicationContext: 單例對象適用 採用此接口 * 它在構建核心容器時,建立對象採起的策略是採用當即加載的方式。也就是說,只要一讀取完配置文件立刻就建立配置文件中配置的對象。 * * BeanFactory: 多例對象使用 * 它在構建核心容器時,建立對象採起的策略是採用延遲加載的方式。也就是說,何時根據id獲取對象了,何時才真正的建立對象。 * @param args */ public static void main(String[] args) { //1.獲取核心容器對象 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); //2.根據id獲取Bean對象,注意id是在bean.xml文件配置的 IAccountService as1 = (IAccountService)ac.getBean("accountService"); IAccountService as2 = (IAccountService)ac.getBean("accountService"); System.out.println(as1==as2); } }
控制檯輸出:
(3)bean對象的生命週期
單例對象
出生:當容器建立時對象出生
活着:只要容器還在,對象一直活着
死亡:容器銷燬,對象消亡
總結:單例對象的生命週期和容器相同
多例對象
出生:當咱們使用對象時spring框架爲咱們建立
活着:對象只要是在使用過程當中就一直活着。
死亡:當對象長時間不用,且沒有別的對象引用時,由Java的垃圾回收器回收
<?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"> <!--把對象的建立交給sping來管理--> <bean id="accountService" class="service.impl.AccountServiceImpl"></bean> <bean id="accountDao" class="dao.impl.AccountDaoImpl"></bean> </beans>
(5)表現層
package ui; import dao.IAccountDao; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import service.IAccountService; import service.impl.AccountServiceImpl; /** * 模擬一個表現層,用於調用業務層 */ public class Client { /** * 獲取spring的Ioc核心容器,並根據id獲取對象 * * ApplicationContext的三個經常使用實現類: * ClassPathXmlApplicationContext:它能夠加載類路徑下的配置文件,要求配置文件必須在類路徑下。不在的話,加載不了。(更經常使用) * FileSystemXmlApplicationContext:它能夠加載磁盤任意路徑下的配置文件(必須有訪問權限) * * AnnotationConfigApplicationContext:它是用於讀取註解建立容器的,是明天的內容。 * * 核心容器的兩個接口引起出的問題: * ApplicationContext: 單例對象適用 採用此接口 * 它在構建核心容器時,建立對象採起的策略是採用當即加載的方式。也就是說,只要一讀取完配置文件立刻就建立配置文件中配置的對象。 * * BeanFactory: 多例對象使用 * 它在構建核心容器時,建立對象採起的策略是採用延遲加載的方式。也就是說,何時根據id獲取對象了,何時才真正的建立對象。 * @param args */ public static void main(String[] args) { //1.獲取核心容器對象 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); // ApplicationContext ac = new FileSystemXmlApplicationContext("C:\\Users\\zhy\\Desktop\\bean.xml"); //2.根據id獲取Bean對象,注意id是在bean.xml文件配置的 IAccountService as = (IAccountService)ac.getBean("accountService"); IAccountDao adao = ac.getBean("accountDao", IAccountDao.class); System.out.println(as); System.out.println(adao); as.saveAccount(); } }
控制檯輸出: