一、Spring簡介 1、Spring介紹 Spring 是一款主流的 Java EE 輕量級開源框架 ,Spring 由“Spring 之父”Rod Johnson 提出並創立,其目的是用於簡化 Java 企業級應用的開發難度和開發周期。Spring的用途不僅限於伺服器端的開發。從簡單性、可測試性 ...
一、Spring簡介
1、Spring介紹
Spring 是一款主流的 Java EE 輕量級開源框架 ,Spring 由“Spring 之父”Rod Johnson 提出並創立,其目的是用於簡化 Java 企業級應用的開發難度和開發周期。Spring的用途不僅限於伺服器端的開發。從簡單性、可測試性和松耦合的角度而言,任何Java應用都可以從Spring中受益。Spring 框架除了自己提供功能外,還提供整合其他技術和框架的能力。
Spring 自誕生以來備受青睞,一直被廣大開發人員作為 Java 企業級應用程式開發的首選。時至今日,Spring 儼然成為了 Java EE 代名詞,成為了構建 Java EE 應用的事實標準。
2、使用Spring的原因
官方解釋:https://spring.io/why-spring
Spring使Java編程對每個人來說更快、更容易、更安全。 Spring對速度、簡單性和生產率的關註使它成為世界上最流行的Java框架。 spring給整個行業帶來等了春天,為我們軟體的開髮帶來了極大的便利。
參考:snyk發佈的2021年JVM 生態系統報告(2022年的還沒有發佈)
Java 世界仍然是 Spring 主導的世界,超過一半的市場使用 Spring Boot,幾乎三分之一使用 Spring MVC。總的來說,我們看到我們生活在一個高度由 Spring 主導的宇宙中,這似乎表明 Spring 的人們在為社區服務方面做得很好。
- Spring is everywhere
Spring 框架提供靈活的類庫受到世界各地開發人員的信任。無論是流媒體電視、線上購物、還是無數其他創新的解決方案,Spring每天都為數百萬終端用戶提供愉快的體驗。Spring也有來自所有科技巨頭的貢獻,包括阿裡巴巴、亞馬遜、谷歌、微軟等。
- Spring is flexible
Spring 靈活而全面的擴展能力和第三方庫讓開發人員可以構建幾乎任何可以想象到的應用程式。 Spring框架的控制反轉(IoC)和依賴註入(DI)特性為一系列廣泛的特性和功能提供了基礎。 無論您是在為web構建安全的、響應式的、基於雲的微服務,還是為企業構建複雜的流數據流,Spring都有工具可以提供幫助。
- Spring is productive
Spring Boot 改變了您處理Java編程任務的方式,從根本上簡化了您的體驗。 Spring Boot結合了應用程式上下文和自動配置的嵌入式web伺服器等必要條件,使microservice開發變得輕而易舉。 為了更快,您可以將Spring Boot與Spring Cloud豐富的支持庫、伺服器、模式和模板組合在一起,以創紀錄的時間將整個基於微服務的架構安全地部署到雲中。
- Spring is fast
我們的工程師非常關心性能。 在Spring中,預設情況下,您會註意到快速啟動、快速關閉和優化執行。 Spring項目也越來越多地支持reactive(nonblocking)編程模型,以獲得更高的效率。 開發人員的生產力是Spring的超級力量。 Spring Boot幫助開發人員輕鬆地構建應用程式,而且比其他競爭範式要輕鬆得多。
- Spring is secure
Spring在處理安全問題方面十分可靠。 Spring代碼的貢獻者與安全專業人員一起修補和測試任何報告的漏洞。 第三方依賴關係也被密切監控,並定期發佈更新,以幫助您的數據和應用程式儘可能安全。 此外,Spring Security使您更容易集成行業標準的安全方案,並交付可靠的預設安全解決方案。
- Spring is supportive
Spring社區是一個龐大的、全球性的、多樣化的社區,涵蓋了所有年齡和能力的人,從完全的初學者到經驗豐富的專業人士。 無論你處在人生的哪個階段,你都能找到幫助你進入下一個階段的支持和資源。
3、Spring提供的功能
總結:Spring發展到現在已經不再是一個單純的應用框架,而是逐漸發展成為一個由多個不同子項目(模塊)組成的成熟技術,例如 Spring Framework、SpringBoot、Spring Cloud、Spring Data、Spring Security 等。
Spring提供的所有項目組成:https://spring.io/projects
這些子項目涵蓋了從企業級應用開發到雲計算等各方面的內容,能夠幫助開發人員解決軟體發展過程中不斷產生的各種實際問題,給開發人員帶來了更好的開發體驗。
Spring Framework 是其它子項目的基礎,可以理解成 Spring 的項目也只是在 Spring Framework 的基礎上對其進行擴展實現的。故我們也稱 Spring Framework 為 Spring 框架。框架本身的好處是重用性,其它項目不用重覆開發Spring Framework已經實現的功能,對其添磚加瓦,形成自己特色的項目就好。
而且我們所說的Spring MVC其實也屬於Spring Framework核心項目之一;只是因為使用頻率最高且強調web功能,所以我們會拆出來成為Spring MVC 框架。
4、Spring Framework組成
官網介紹:https://spring.io/projects/spring-framework#overview
上圖中包含了 Spring 框架的所有模塊,這些模塊可以滿足一切企業級應用開發的需求,在開發過程中可以根據需求有選擇性地使用所需要的模塊。下麵分別對這些模塊的作用進行簡單介紹。
- Spring Core(核心容器)
spring core提供了IOC,DI,Bean配置裝載創建的核心實現。核心概念: Beans、BeanFactory、、ApplicationContext。
- spring-core :IOC和DI的基本實現
- spring-beans:BeanFactory和Bean的裝配管理(BeanFactory)
- spring-context:Spring context上下文,即IOC容器(AppliactionContext)
- spring-expression:spring表達式語言
- Spring AOP
- spring-aop:面向切麵編程的應用模塊,整合ASM,CGLib,JDK Proxy
- spring-aspects:集成AspectJ,AOP應用框架
- spring-instrument:動態Class Loading模塊
- Spring Data Access
- spring-jdbc:spring對JDBC的封裝,用於簡化jdbc操作
- spring-orm:java對象與資料庫數據的映射框架
- spring-oxm:對象與xml文件的映射框架
- spring-jms: Spring對Java Message Service(java消息服務)的封裝,用於服務之間相互通信
- spring-tx:spring jdbc事務管理
- Spring Web
- spring-web:最基礎的web支持,建立於spring-context之上,通過servlet或listener來初始化IOC容器
- spring-webmvc:實現web mvc
- spring-websocket:與前端的全雙工通信協議
- spring-webflux:Spring 5.0提供的,用於取代傳統java servlet,非阻塞式Reactive Web框架,非同步,非阻塞,事件驅動的服務,Netty,Undertow和Servlet 3.1+容器等伺服器上運行
- Spring Message
- Spring-messaging:spring 4.0提供的,為Spring集成一些基礎的報文傳送服務
- Spring test
- spring-test:集成測試支持,主要是對junit的封裝
5、Spring Framework特點
- 非侵入式:使用 Spring Framework 開發應用程式時,Spring 對應用程式本身的結構影響非常小。對領域模型可以做到零污染;對功能性組件也只需要使用幾個簡單的註解進行標記,完全不會破壞原有結構,反而能將組件結構進一步簡化。這就使得基於 Spring Framework 開發應用程式時結構清晰、簡潔優雅。
- 控制反轉:IoC——Inversion of Control,翻轉資源獲取方向。把自己創建資源、向環境索取資源變成環境將資源準備好,我們享受資源註入。
- 面向切麵編程:AOP——Aspect Oriented Programming,在不修改源代碼的基礎上增強代碼功能。
- 容器:Spring IoC 是一個容器,因為它包含並且管理組件對象的生命周期。組件享受到了容器化的管理,替程式員屏蔽了組件創建過程中的大量細節,極大的降低了使用門檻,大幅度提高了開發效率。
- 組件化:Spring 實現了使用簡單的組件配置組合成一個複雜的應用。在 Spring 中可以使用 XML 和 Java 註解組合這些對象。這使得我們可以基於一個個功能明確、邊界清晰的組件有條不紊的搭建超大型複雜應用系統。
- 一站式:在 IoC 和 AOP 的基礎上可以整合各種企業應用的開源框架和優秀的第三方類庫。而且 Spring 旗下的項目已經覆蓋了廣泛領域,很多方面的功能性需求可以在 Spring Framework 的基礎上全部使用 Spring 來實現。
Spring框架版本:Spring6要求JDK最低版本是JDK17
二、IoC概述
1、背景介紹
介紹IOC之前我們先對其背景進行介紹,也即對象的創建史!
1) 普通new實例
在實際項目設計過程中,介面是一個重要組成元素,不同層之間的操作需要通過介面來調用。利用介面,可以實現子類的隱藏,也可以更好地描述不同層之間的操作標準。Java中要想獲得介面對象,需要通過關鍵字new來實現。下麵的案例不要研究其業務意義,只是一個測試demo!
public interface ConnectionMessage {
public String select();
}
public class MySQLMessageImpl implements ConnectionMessage {
@Override
public String select() {
System.out.println("連接---查詢MySQL資料庫信息");
return "";
}
}
public class MyTest {
public static void main(String[] args) {
ConnectionMessage message = new MySQLMessageImpl();
message.select();
}
}
以上是使用MySQL操作的模擬程式,如果切換為PostgreSQL就需要修改其使用類!
public class MyTest {
public static void main(String[] args) {
//ConnectionMessage message = new MySQLMessageImpl();
ConnectionMessage message = new PostgreSQLMessageImpl();
message.select();
}
}
這就是所謂的耦合,調用的時候要修改代碼,即直接new , 顯然不符合面向對象的設計原則---------開閉原則
2.1)普通工廠
針對上面的情況我們可以使用工廠方式,創建一個BeanFactory.java文件
public class BeanFactory {
public static ConnectionMessage select(){
return new MySQLMessageImpl();
}
}
這樣使用的時候就變成下麵這樣
public class MyTest {
public static void main(String[] args) {
// ConnectionMessage message = new MySQLMessageImpl();
// ConnectionMessage message = new PostgreSQLMessageImpl();
ConnectionMessage message = BeanFactory.select();
message.select();
}
}
上圖的思想沒問題,但是我們的代碼還尚有問題,即BeanFactory裡面還是有代碼耦合
2.2)反射工廠1.0
我們接下來可以利用反射完善一下!
public class BeanFactory {
private static ConnectionMessage message;
public static ConnectionMessage select() throws Exception {
Class<?> clazz = Class.forName("com.ty.demo.dao.impl.MySQLMessageImpl");
message = (MySQLMessageImpl) clazz.getDeclaredConstructor().newInstance();
return message;
}
}
這樣比直接new好多了,減少了工廠內獲取對象的耦合,但是獲取類限定名的時候還是需要進行修改!
2.3)反射工廠2.0
下麵我們可以用properties屬性配置文件存儲文件限定名,把具體的類限定名和代碼相分離,未來只需要修改此配置文件即可!
public class BeanFactory {
private static ConnectionMessage message;
//創建Properties對象來載入properties屬性配置文件
private static Properties environment = new Properties();
private static InputStream resource;
static {
//載入bean.properties配置文件
resource = BeanFactory.class.getResourceAsStream("/bean.properties");
try {
environment.load(resource);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static ConnectionMessage select() throws Exception {
Class<?> clazz = Class.forName(environment.getProperty("mysqlMessage"));
message = (MySQLMessageImpl) clazz.getDeclaredConstructor().newInstance();
return message;
}
}
2.3)通用工廠
上面我們的工廠方法基本設計完成了,但是還有點小問題,那就是每次都需要在BeanFactory工廠類寫一個與其對應的對象創建工廠方法,這時我們設計一個通用的工廠方法
public class BeanFactory {
//創建Properties對象來載入properties屬性配置文件
private static Properties environment = new Properties();
private static InputStream resource;
static {
//載入bean.properties配置文件
resource = BeanFactory.class.getResourceAsStream("/bean.properties");
try {
environment.load(resource);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* @param key 配置文件對應的mysqlMessage和postgresqlMessage
* @return
*/
public static Object getBean(String key) {
Object returnedObject = null;
try {
Class<?> clazz = Class.forName(environment.getProperty(key));
returnedObject = clazz.getDeclaredConstructor().newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return returnedObject;
}
}
一個通用工廠就完成了,但是這種方式你還需要先自己提供工廠類和方法,我們如果用Spring的話,工廠類不用我們手動實現,Spring提供了工廠,使我們可以將更多精力放在核心代碼的開發處理上。
2、IoC---控制反轉
簡介:控制反轉(Inversion of Control,縮寫為IoC),它不是一門技術,而是面向對象編程中的一種設計思想,可以用來降低代碼之間的耦合度,能夠指導我們如何設計出松耦合、更優良的程式。
核心: 將對象的創建權交出去,將對象和對象之間關係的管理權交出去,由第三方容器來負責創建與維護 。
目標:降低程式耦合度,提高程式擴展力
控制反轉,反轉的是什麼?
- 將對象的創建權利交出去,即不在程式中採用硬編碼的方式來new對象,而是交給第三方容器負責
- 將對象和對象之間關係的維護權交出去,交給第三方容器負責
實現方式:依賴註入(Dependency Injection)與依賴查找(Dependency Lookup)
- 依賴註入:Spring創建對象的過程中,將對象依賴屬性通過配置進行註入,常見的實現方式:
- set註入
- 構造註入
總結:
- IOC 就是一種控制反轉的思想, 而 DI 是對IoC的一種具體實現
- Bean管理:Bean對象的創建,以及Bean對象中屬性的賦值(或者叫做Bean對象之間關係的維護)
相關名詞
容器:可以管理對象的生命周期、對象與對象之間的依賴關係
實體類:
- POJO(Plain Old Java Object):是Martin Fowler、Rebecca Parsons和Josh MacKenzie在2000年的一次演講的時候提出來的。按照Martin Fowler的解釋是“Plain Old Java Object”,從字面上翻譯為“純潔老式的Java對象”,但大家都使用“簡單java對象”來稱呼它。POJO的內在含義是指:那些沒有繼承任何類、也沒有實現任何介面,更沒有被其它框架侵入的java對象。不允許有業務方法,也不能攜帶connection之類的方法,實際就是普通JavaBeans。
- JavaBean:是一種JAVA語言寫成的可重用組件。JavaBean符合一定規範編寫的Java類,不是一種技術,而是一種規範。大家針對這種規範,總結了很多開發技巧、工具函數。符合這種規範的類,可以被其它的程式員或者框架使用。它的方法命名,構造及行為必須符合特定的約定:
1、所有屬性為private。
2、這個類必須有一個公共的預設構造函數。即是提供無參數的構造器。
3、這個類的屬性使用getter和setter來訪問,其他方法遵從標準命名規範。
4、這個類應是可序列化的。實現serializable介面。
因為這些要求主要是靠約定而不是靠實現介面,所以許多開發者把JavaBean看作遵從特定命名約定的POJO。
POJO與JavaBean的區別:
POJO | JavaBean | |
---|---|---|
許可權控制 | 沒有對成員提供太多控制 | 提供對成員的完全控制 |
可序列化 | 可以實現 | 應該實現 |
欄位訪問 | 具有任何可見性,可以直接訪問 | 欄位只有私人可見性,只能由getter和setter訪問 |
無參構造 | 可以沒有 | 必須具有 |
使用場景 | 當您不想限製成員並讓用戶完全訪問您的實體時使用它 | 當您要向用戶提供您的實體,但僅向實體的一部分提供服務時,將使用它 |
POJO類和Bean均用於定義Java對象,以提高其可讀性和可重用性。POJO沒有其他限制,而bean是具有某些限制的特殊POJO。
- SpringBean:受Spring管理的對象,所有能受Spring容器管理的對象都可以成為SpringBean。Spring中的bean,是通過配置文件、javaconfig等的設置,由Spring自動實例化,用完後自動銷毀的對象。
SpringBean和JavaBean的區別:
JavaBean | SpringBean | |
---|---|---|
用處不同 | 更多地作為值傳遞參數 | 用處幾乎無處不在,任何組件都可以被稱為bean |
寫法不同 | 作為值對象,要求每個屬性都提供getter和setter方法 | 只需為接受設值註入的屬性提供setter方法 |
生命周期不同 | 傳統javabean作為值對象傳遞,不接受任何容器管理其生命周期 | spring管理其生命周期行為 |
Entity Bean:是域模型對象,用於實現O/R映射,負責將資料庫中的表記錄映射為記憶體中的Entity對象,事實上,創建一個Entity Bean對象相當於新建一條記錄,刪除一個 Entity Bean會同時從資料庫中刪除對應記錄,修改一個Entity Bean時,容器會自動將Entity Bean的狀態和資料庫同步。
三、入門程式
1、引入依賴
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>6.0.4</version>
</dependency>
當引入Spring-webmvc依賴之後,表示將Spring的基礎依賴也一起引入了
有的教程可能引得是spring-context依賴,此依賴是除了web部分其餘的基礎依賴都會引進來,它們一般是在Spring MVC的時候再引入spring-webmvc依賴。
2、創建java類
public class HelloWorld {
public void sayHello(){
System.out.println("hello world");
}
}
3、創建配置文件
在resources目錄創建一個 Spring 配置文件 bean.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">
<!--
配置HelloWorld所對應的bean,表示將HelloWorld的對象交給Spring的IOC容器管理
通過bean標簽配置IOC容器所管理的bean
屬性:
id:設置bean的唯一標識
class:設置bean所對應類型的全限定名
-->
<bean id="hello" class="com.ty.demo.bean.HelloWorld"></bean>
</beans>
4、測試程式
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
context.getBean("hello", HelloWorld.class).sayHello();
}
}
5、簡單分析
這裡我們這是簡單介紹一下基本原理,Spring整個Bean的創建過程很複雜,之後再一點點介紹!
- 底層利用通過反射機制調用無參數構造方法
- Spring創建對象就像之前我們使用Properties的步驟類似,它使用的是dom4j解析beans.xml文件,從中獲取class屬性值,類的全類名;然後通過反射機制調用無參數構造方法創建對象
Class.forName("com.ty.demo.bean.HelloWorld").getDeclaredConstructor().newInstance()
- 創建好的對象存儲在ConcurrentHashMap中
bean對象最終存儲在spring容器中,在spring源碼底層就是一個map集合,存儲bean的map在DefaultListableBeanFactory類中:
Spring容器載入到Bean類時 , 會把這個類的描述信息, 以包名加類名的方式存到beanDefinitionMap 中,
Map<String,BeanDefinition>
- 其中 String是Key , 預設是類名首字母小寫 ,
- BeanDefinition , 存的是類的定義(描述信息) ,
- 我們通常叫BeanDefinition介面為 : bean的定義對象。
6、SpringTest測試
前面通過ApplicationContext啟動了Spring容器,並實現了配置文件的載入,但這樣處理並不能體現出Spring的運行特征。為了更好地還原現實的開發場景,可利用SpringTest依賴庫和JUnit實現測試環境下的Spring容器啟動,且可以使用@Autowired代替getBean方法實現自動註入。
引入依賴
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>6.0.4</version>
</dependency>
測試程式
@ContextConfiguration(locations = {"classpath:bean.xml"})
@ExtendWith(SpringExtension.class)
public class MyTest {
@Autowired
private HelloWorld helloWorld;
@Test
void testHelloWorld() {
helloWorld.sayHello();
}
}
- @ContextConfiguration:表示Spring配置文件所在的目錄。本程式通過classpath進行載入,由於src/main/resources屬於源目錄,所以目錄中保存的所有資源將自動設置在CLASSPATH之中
- @ExtendWith(SpringExtension.class):表示要使用的測試工具類型。
- @Autowired:自動註入
7、整合logback日誌
在項目開發中,日誌十分的重要,不管是記錄運行情況還是定位線上問題,都離不開對日誌的分析。日誌記錄了系統行為的時間、地點、狀態等相關信息,能夠幫助我們瞭解並監控系統狀態,在發生錯誤或者接近某種危險狀態時能夠及時提醒我們處理,同時在系統產生問題時,能夠幫助我們快速的定位、診斷並解決問題。
引入依賴
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.5</version>
<scope>test</scope>
</dependency>
測試程式
作者:貓的薛定諤出處:https://www.cnblogs.com/hanyu-2020/
---------------------------------------------------------
個性簽名:獨學而無友,則孤陋而寡聞。做一個靈魂有趣的人!
如果覺得這篇文章對你有小小的幫助的話,記得在右下角點個“推薦”哦,博主在此感謝!
本文內容若有疏漏請多多包涵,如有錯誤麻煩請指正,如有想法交流非常歡迎在下方評論!