@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天、工作日等提供了便捷操作,此处仅做出简单示例,详请还请参见官方文档哈。
数据访问与事务
新增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)已正式发布,将会在下篇文章开启介绍,欢迎关注。