不是井里沒有水,而是你挖的不夠深,本文已被 https://www.yourbatman.cn 收錄,里面一并有Spring技術堆疊、MyBatis、JVM、中間件等小而美的專欄供以免費學習,關注公眾號【BAT的烏托邦】逐個擊破,深入掌握,拒絕淺嘗輒止,
目錄
- ?前言
- ?正文
- 新特性/功能升級
- 通用升級
- 1、ASM升級到9.0
- 2、支持RxJava 3.0,過期對RxJava 1.0支持
- 通過spring.spel.ignore屬性可禁用SpEL模塊
- 核心容器
- 對@Scheduled升級:CronExpression
- CronExpression的使用
- @Scheduled中Cron運算式增強
- 其它增強
- 資料訪問與事務
- 新增JdbcTransactionManager類
- JdbcTemplate新增queryForStream()方法
- @Transactional的timeout屬性支持占位符取值
- Web升級
- CORS跨域配置類
- 通過spring.xml.ignore屬性可禁用xml決議模塊
- Spring MVC提升
- 提升URL匹配效率
- @ControllerAdvice可處理來自所有處理器的例外了
- Spring WebFlux提升
- Testing測驗提升
- ?總結
- ?推薦閱讀:
- ?關注A哥?

?前言
你好,我是YourBatman,
北京時間2020-10-27,Spring Framework 5.3.0版本正式發布,說明:Spring Framework 5.2.0.RELEASE的發布時間是2019-09哈,
注意:5.3.0版本號沒有
.RELEASE后綴喲,至于原因我前面寫的這篇文章給了你完整解釋哈:Spring改變版本號命名規則:此舉對非英語國家很友好
在Spring Boot大行其道的今天,似乎Spring Framework的版本升級受到的關注越來越少了,殊不知對Spring Boot有多了解始于對Spring Framework的了解程度,因此保持對后者的一定關注會是很有意義的,

?正文
Spring Framework 5.3.x是5.x版本的最后一個功能分支,此系列最低要求JDK8,且支持到了JDK15,以及還會擴展支持到明年的JDK17,
另外,對于剛剛發布的Spring Boot 2.4.0以及明年即將發布的Spring Boot 2.5.0均會基于此功能分支構建,官方建議:現在處在5.x / 4.x的用戶均升級到Spring Framework 5.3.x版本上來,因為它將是一個面向未來的分支,并且提供長期維護(持續到2024年,持續時間可謂是最長的),它是壽命同樣長的4.3.x分支系列產品的后繼產品,但此系列的壽命將在2020-12結束不再維護(畢竟真的很老了嘛),
說明:Spring團隊對于一般的功能分支,提供2-3年的維護,而對于4.3/5.3均提供了長達4年多的維護時間,這得益于它們是主版本號的最后一個功能分支
新特性/功能升級
誠如各位所知,Spring Framework是很多模塊技術的總和,因此在新特性/功能增強方面我們分模塊進行表述,
通用升級
1、ASM升級到9.0
ASM 9.0版本可是非常新的版本,如下圖:

<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>9.0</version>
</dependency>
Spring使用了最新版的ASM包,可謂緊跟潮流啊,
需要清楚的是Spring它并沒有引入這個jar哦,而是fork了一份源代碼放在spring-core里(報名改了,但內容基本沒沒變),這樣做更加高效:

至于ASM 9.0的新功能增強,有興趣可進入其官網閱讀即可,直達電梯:https://asm.ow2.io
2、支持RxJava 3.0,過期對RxJava 1.0支持
這些都是通過配接器ReactiveAdapterRegistry實作的,它支持了:Reactor、RxJava 2/3、CompletableFuture、Java 9+的Flow.Publisher等等,并且以把對RxJava 1.0的支持標記為過期,預計下個功能分支會移除,

<dependency>
<groupId>io.reactivex.rxjava3</groupId>
<artifactId>rxjava</artifactId>
<version>3.0.7</version>
</dependency>
可以看到RxJava 3.X也是非常非常新的,這點Spring做得不可為不好,
RxJava 3.X旨在用來替代RxJava 2,因此存在少量的二進制不兼容(簡單說:不向下兼容,但改動也沒那么的大),另外就是提供了基于Java 8 lambda友好的API,更加的普適了,
通過spring.spel.ignore屬性可禁用SpEL模塊
如果你的應用程式沒使用/不依賴于SpEL,那么可以通過屬性spring.spel.ignore來忽略掉它,SpEL是spring-expression是這個模塊提供支持的,其實很多時候我們并不需要使用到SpEL運算式(特別是在現在的注解驅動使用中),那么我們就可以通過設定此屬性值來禁用掉此模塊功能,為系統減負(降低啟動時間,節約記憶體),
SpEL模塊主要在兩個地方被使用,均可通過此屬性配置來關閉:
// 背景關系了支持SpEL運算式,比如@Value里
AbstractApplicationContext:
private static final boolean shouldIgnoreSpel = SpringProperties.getFlag("spring.spel.ignore");
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
...
if (!shouldIgnoreSpel) {
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
...
}
// 支持@EventListener(condition = 'SpEL')
EventListenerMethodProcessor:
public EventListenerMethodProcessor() {
if (shouldIgnoreSpel) {
this.evaluator = null;
} else {
this.evaluator = new EventExpressionEvaluator();
}
}
只需要在類路徑下的spring.properties檔案添加屬性spring.spel.ignore = true即可禁用掉SpEL模塊的加載,
小貼士:類路徑下的
spring.properties檔案是Spring Framework啟動自動就會加載的,詳可參見org.springframework.core.SpringProperties學習,
spring-expression模塊的初始化動作不輕,Spring提供此屬性我認為是在為云原生做不懈努力,但是,但是,但是,請你務必在確定沒有使用SpEL的情況下才去關閉此開關,否則弄出線上bug背個鍋就劃不來了,當然嘍,最好是能有個熟悉Spring的人hold住才去改它~
核心容器
此模塊最大的升級就是對Cron運算式進行了提升,
對@Scheduled升級:CronExpression
在Spring場景下,Cron運算式只能通過@Scheduled注解去實作,而在5.3.0版本引入了一個新的API:CronExpression用于決議Cron運算式(編程式),
CronExpression完全替代了CronSequenceGenerator(@Scheduled基于它實作)這個老的API,是因為后者基于java.util.Calendar實作的從而存在已知的一些問題,并且還沒法修復(畢竟是JDK的鍋嘛,Spirng團隊也無能為力),因此新的CronExpression就使用了java.time解決了問題并且還提供了新的好用功能,
CronExpression的使用
在之前我們想要一個Cron運算式都是借助@Scheduled來完成,現在可以使用CronExpression輕松編程式來做嘍:
public static void main(String[] args) {
CronExpression expression = CronExpression.parse("10 * * * * *");
LocalDateTime start = LocalDateTime.now();
for (int i = 0; i < 3; i++) {
start = expression.next(start);
System.out.println(start);
}
}
運行程式,控制臺輸出:
2020-11-15T11:28:10
2020-11-15T11:29:10
2020-11-15T11:30:10
該Cron運算式表示:每分鐘的第10秒鐘觸發,因此結果是符合預期的,該parse方法入參是Cron運算式的字串,該字串帶有六個以空格分隔的時間和日期欄位,各部分表示為:

當然啦,還有些 * ?這樣的通配符可以使用,具體的這里就不做過多介紹了,
@Scheduled中Cron運算式增強
我們經常會在@Scheduled使用Cron運算式,比如0 0 * * * *代表每個小時執行一次,對于這種常用的運算式這么寫確實非常不直觀,Spring 5.3.0新提出了宏的概念,讓你可以用一個英文單詞搞定,它由CronExpression提供支持:
CronExpression:
private static final String[] MACROS = new String[] {
"@yearly", "0 0 0 1 1 *",
"@annually", "0 0 0 1 1 *",
"@monthly", "0 0 0 1 * *",
"@weekly", "0 0 0 * * 0",
"@daily", "0 0 0 * * *",
"@midnight", "0 0 0 * * *",
"@hourly", "0 0 * * * *"
};
如:@Scheduled(cron = "@hourly")它就代表每小時執行一次,效果等同于@Scheduled(cron = "0 0 * * * *"),其它的等同效果如上所示,
其它增強
Spring還對最后xxx天、作業日等提供了便捷操作,此處僅做出簡單示例,詳請還請參見官方檔案哈,
| Cron運算式 | 含義 |
|---|---|
| 0 0 0 L * * | 每個月的最后一天午夜 |
| 0 0 0 L-3 * * | 每個月的第三天到最后一天午夜 |
| 0 0 0 * * 5L | 每個月的最后一個星期五午夜 |
| 0 0 0 * * THUL | 每個月最后一個星期四的午夜 |
| 0 0 0 1W * * | 每月第一個作業日的午夜 |
| 0 0 0 LW * * | 每個月最后一個作業日的午夜 |
| 0 0 0 ? * 5#2 | 每個月的第二個星期五午夜 |
| 0 0 0 ? * MON#1 | 每月的第一個星期一午夜 |
資料訪問與事務
新增JdbcTransactionManager類
它繼承自DataSourceTransactionManager,它主要是對doCommit、doRollback時產生的例外借助SQLExceptionTranslator實作轉換,簡單的說可以自定義這個轉換器來實作例外轉換嘍,這在5.3.0之前是寫死的:
5.3.0之前DataSourceTransactionManager:
@Override
protected void doCommit(DefaultTransactionStatus status) {
...
try {
con.commit();
} catch (SQLException ex) {
throw new TransactionSystemException("Could not commit JDBC transaction", ex);
}
}
5.3.0之后DataSourceTransactionManager:
@Override
protected void doCommit(DefaultTransactionStatus status) {
...
try {
con.commit();
} catch (SQLException ex) {
throw translateException("JDBC commit", ex);
}
}
// @since 5.3 默認實作是同之前版本使用的TransactionSystemException包裝
// 但子類JdbcTransactionManager對此方法實作了覆寫
protected RuntimeException translateException(String task, SQLException ex) {
return new TransactionSystemException(task + " failed", ex);
}
5.3.0新增的JdbcTransactionManager類:
@Override
protected RuntimeException translateException(String task, SQLException ex) {
DataAccessException dae = getExceptionTranslator().translate(task, null, ex);
if (dae != null) {
return dae;
}
return super.translateException(task, ex);
}
JdbcTemplate新增queryForStream()方法
這是5.3.0新增方法,這樣就可以允許在可關閉的物件上進行惰性迭代,提高查詢效率(不過JdbcTemplate貌似用得很少,至少國內是這樣),
@Transactional的timeout屬性支持占位符取值
在這之前,@Transactional注解timeout屬性的值只能寫死,現在可以寫成${...}從環境中動態取值了,方便許多且更富彈性,
Web升級
CORS跨域配置類
CorsConfiguration跨域配置類新增屬性allowedOriginPatterns,用于通過通配符模式宣告動態范圍的域,之前只有allowedOrigins只能寫死,
通過spring.xml.ignore屬性可禁用xml決議模塊
在Spring Boot大行其道的今天,面向元資料/注解編程成為了主流,基于xml配置的Spring應用越來越少,
為了加快啟動速度和減少記憶體開銷,Spring提供了spring.xml.ignore這個屬性來禁用掉xml決議模塊,如果你沒有用到xml功能的話,同樣的,我覺得這是Spring為云原生做的又一努力,
// 默認可以將.properties和xml配置加載到Properties類
PropertiesLoaderUtils:
private static final boolean shouldIgnoreXml = SpringProperties.getFlag("spring.xml.ignore");
public static void fillProperties(Properties props, Resource resource) throws IOException {
...
if (filename != null && filename.endsWith(XML_FILE_EXTENSION)) {
if (shouldIgnoreXml) {
throw new UnsupportedOperationException("XML support disabled");
}
props.loadFromXML(is);
}
...
}
ConfigurationClassBeanDefinitionReader:
ResourcePropertiesPersister:
如果禁用了,不僅僅不會去加載xml檔案,而且連相關的converters和codecs都不會去加載了,禁用方式為在類路徑下的spring.properties檔案里添加屬性spring.xml.ignore = true即可,
Spring MVC提升
提升URL匹配效率
眾所周知:Spring MVC中可以寫Ant分隔的URL,也就是我們常用的@PathVariable,使用起來非常方便,但是,基于Ant風格的URL存在性能問題,特別實在高并發情況下尤為明顯,不可忽視,
基于Ant風格的URL使用的AntPathMatcher進行匹配,Spring自己也知道它在高并發下存在著性能問題,在今年的早些時候官方也寫了篇博客描述這個現象:URL Matching with PathPattern in Spring MVC
在5.3.0版本后,基于Ant風格的URL的匹配效率有了非常大的提升,具體原理和使用方式限于篇幅,將在后面文章用專文詳解,
@ControllerAdvice可處理來自所有處理器的例外了
在過去@ControllerAdvice只能處理來自@Controller型別控制器的例外,但是我們知道Spirng MVC至少支持4種控制器型別,如HttpRequestHandler就是其中一種,從5.3.0版本開始就都可以用@ControllerAdvice來做攔截統一處理啦~
Spring WebFlux提升
- 提供一個新類
DefaultPartHttpMessageReader提供一個完全反應式的訊息閱讀器,它將緩沖區流轉換為Flux<Part> - 提供一個新類
PartHttpMessageWriter用于寫Flux<Part> - 為Apache Http Components提供一個新的
WebClient連接器
Testing測驗提升
- Spring的測驗框架現在已基于
JUnit Jupiter 5.7、JUnit 4.13.1、TestNG 7.3.0來構建(竟然還沒放棄JUnit4.x,推薦信專案使用JUnit Jupiter 5.x哈,好用多了) - RestTemplate的客戶端REST測驗支持Multipart data
- …
?總結
總的來說,Spirng Framework這次的升級著力點主要在啟動速度、性能使用上,作為5.x分支的最后一個功能分支,可圈可點,個人的升級建議是可以升也建議升,
當然,現在一般不會單獨升級Spring Framework的版本,而是隨著Spring Boot一起升級,截止稿前,Spirng Boot 2.4.0(基于Spring Framework 5.3.x)已正式發布,將會在下篇文章開啟介紹,歡迎關注,
?推薦閱讀:
- Spring改變版本號命名規則:此舉對非英語國家很友好
- JDK15正式發布,劃時代的ZGC同時宣布轉正
- IntelliJ IDEA 2020.2正式發布,諸多亮點總有幾款能助你提效
- Spring Boot 2.3.0正式發布:優雅停機、組態檔位置通配符新特性一覽
- 搞事情?Spring Boot今天一口氣發布三個版本
?關注A哥?
| Author | A哥(YourBatman) |
|---|---|
| 個人站點 | www.yourbatman.cn |
| yourbatman@qq.com | |
| 微 信 | fsx1056342982 |
活躍平臺 | ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
| 公眾號 | BAT的烏托邦(ID:BAT-utopia) |
| 知識星球 | BAT的烏托邦 |
| 每日文章推薦 | 每日文章推薦 |

CSDN認證博客專家
博客專家
專欄創作者
BAT的烏托邦
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/225277.html
標籤:AI
上一篇:開啟博客人生
下一篇:JSON物件與字串之間的轉換







