本文基於Spring 5.2.15-RELEASE
關於Spring設定類的Full模式和Lite模式,如果沒有仔細閱讀過原始碼或者官方檔案的話,估計很多人都不知道這個概念。所以我們先來解釋下這兩個概念。
@Configuration
public class DataSourceConfig {
...
@Bean
public DataSource dataSource() {
...
return dataSource;
}
@Bean(name = "transactionManager")
public DataSourceTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
...
}
DataSourceConfig就是一個在Spring中非常常見的設定類,這個設定類本身也會被註冊成Spring容器中的一個Bean。上面這種設定方式預設的就是Full模式。為什麼預設是Full模式呢?其實祕密就藏在@Configuration
這個註解中。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
@AliasFor(annotation = Component.class)
String value() default "";
// 預設會通過Cglib對產生Bean的方法進行增強
boolean proxyBeanMethods() default true;
}
這個註解有一個屬性proxyBeanMethods
。這個屬性的值預設是true,會通過Cglib對這個設定類進行增強,增強後這個設定類就顯得比較「重」,因此叫Full模式。如果我們將這個屬性設定成false的話,這個設定類產生的Bean就是原始的物件,比較「輕量級」,叫Lite模式。因此,Full模式和Lite模式最本質的區別是:設定類本身的Bean物件會不會被Cglib增強。
這裡再強調一個概念:Full模式和Lite模式都是說DataSourceConfig這個設定類是Full模式或者Lite模式。
上面提到,將@Configuration的proxyBeanMethods屬性設定成false就Lite模式的設定類,其實還有很多其他的場景也屬於Lite模式。整理下來,大致有以下這些場景:
@Component
註解@ComponentScan
註解@Import
註解@ImportResource
註解@Configuration(***proxyBeanMethods = false***)
自Spring5.2(對應Spring Boot 2.2.0)開始,內建的幾乎所有的
@Configuration
設定類都被修改為了@Configuration(proxyBeanMethods = false)
,以此來降低啟動時間,為Cloud Native繼續做準備。
優點:
缺點:
@Configuration(proxyBeanMethods = false)
public class DataSourceConfig {
...
@Bean
public DataSource dataSource() {
...
return dataSource;
}
@Bean(name = "transactionManager")
public DataSourceTransactionManager transactionManager() {
// 此處的dataSource()呼叫就是一次普通的方法呼叫,不會參照Spring IOC容器中的單列Bean
return new DataSourceTransactionManager(dataSource());
}
...
}
這個問題可以這樣解決
@Configuration(proxyBeanMethods = false)
public class DataSourceConfig {
...
@Bean
public DataSource dataSource() {
...
return dataSource;
}
@Bean(name = "transactionManager")
// 通過方法引數參照Spring容易中的Bean
public DataSourceTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource;
}
...
}
標註有@Configuration
或者@Configuration(***proxyBeanMethods = true***)
的類被稱為Full模式的設定類。
優點:
缺點:
Spring的設定類分成Full和Lite兩種模式。
在Lite模式下
private/final
等進行修飾在Full模式下
private/final
等進行修飾(因為方法需要被重寫,所以不能私有和final。defualt/protected/public都可以哦)從上面的介紹可以看出來,Lite模式很大程度上是為了減少啟動開銷,提升程式的啟動速度。所以如果你對程式的啟動速度很敏感,就使用Lite模式,但是一定要記住此時的設定類已經不是經過Cglib增強過的類了。