Spring中@Configuration注解的Full模式和Lite模式詳解
前言
@Configuration 注解相信各位小伙伴經常會用到,但是大家知道嗎,這個注解有兩種不同的模式,一種叫做 Full 模式,另外一種則叫做 Lite 模式。
準確來說,Full 模式和 Lite 模式其實 Spring 容器在處理 Bean 時的兩種不同行為。
這兩種不同的模式在使用時候的表現完全不同,今天松哥就來和各位小伙伴捋一捋這兩種模式。
1. 概念梳理
首先我們先來看一下 Spring 官方文檔中對 Full 模式和 Lite 模式的一個介紹:

這個文檔主要講了這樣幾件事情:
- 我們可以通過在一個方法上添加 @Bean 注解,進而將該方法的返回值暴露給 Spring 容器,在這種場景下,@Bean 注解實際上就是一種通用的工廠方法機制。
- 當一個添加了 @Bean 注解的方法位于一個沒有添加 @Configuration 注解的類里邊時,那么這個添加了 @Bean 注解的方法在處理時就會按照 Lite 模式來處理。
- 當一個 Bean 被聲明在添加了 @Component 注解的類中,那么會按照 Lite 模式來處理。
- 當一個 Bean 被聲明在一個普通的類中時(plain old class),按照 Lite 模式來處理(這一點感覺和第二點差不多)。
- 在 Lite 模式下,@Bean 注解標記的方法最終不會被 CGLIB 進行代理,就是一個普通的工廠方法,因此,在 @Bean 標記的方法中,不能調用其他 @Bean 注解標記的方法,如果有需要,可以通過方法參數注入自己所需要的 Bean。
- 由于 Lite 模式下并不會使用 CGLIB,因此 @Bean 標記的方法可以是 final 類型的。
- 在大多數場景下,我們在一個 @Configuration 注解標記的類中,使用 @Bean 注解向 Spring 容器注冊一個 Bean,都是 Full 模式。
官網文檔的介紹還是有些抽象,接下來松哥通過具體的案例來和大家演示 Full 模式和 Lite 模式的差別。
2. Full 模式
先看 Full 模式,中文也可以稱之為 完整 模式,我們平時使用時,在一個配置類上添加 @Configuration 注解,且不添加任何額外屬性,這就是 Full 模式了。
Full 模式最大的特點是會給配置類通過 CGLIB 生成一個代理,所有被 @Bean 注解標記的方法將來都是通過代理方法進行調用。
假設我有如下配置類:
@Configuration
public class JavaConfig {
@Bean
User user() {
return new User();
}
}現在,我們去 Spring 容器獲取這個配置類:
public class JavaDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
JavaConfig config = ctx.getBean(JavaConfig.class);
System.out.println("config.getClass() = " + config.getClass());
}
}打印結果如下:

大家看到,最終從 Spring 容器中拿到的 JavaConfig 實例并不是原始的 JavaConfig 對象,而是一個被代理的 JavaConfig 對象。
為什么要代理呢?肯定是為了實現某些功能。
大家看下面這個案例:
@Configuration
public class JavaConfig {
@Bean
User user() {
User user = new User();
user.setDog(dog());
return user;
}
@Bean
Dog dog() {
return new Dog();
}
}在 Full 模式下,在 user() 方法中調用 dog() 方法的時候,調用的是一個代理對象的 dog 方法,在這個代理對象的 dog 方法中,會首先去檢查 Spring 容器中是否存在 Dog 對象,如果存在,則直接使用 Spring 容器中的 dog 對象,就不會真正去執(zhí)行 dog 方法而獲取到一個新的 dog 對象了,如果 Spring 容器中不存在 dog 對象,才會創(chuàng)建新的 dog 對象出來。
一言以蔽之,在 Full 模式下,user 中的 dog 對象和 dog 方法注冊到 Spring 容器的 dog 對象是同一個。
在 Full 模式下,由于要給當前類生成代理,然后去代理 @Bean 注解標記的方法,因此,這些 @Bean 注解標記的方法不能是 final 或者 private 類型的,因為 final 或者 private 類型的方法無法被重寫,也就沒法生成代理對象,如果添加了 final 或者 private 修飾符,那么會拋出如下異常:

3. Lite 模式
再來看 Lite 模式,這種模式可以認為是一種精簡模式。
怎么開啟呢?我們可以去除配置類上的 @Configuration 注解,或者去除之后添加 @Component 注解,又或者使用 @ComponentScan、@ImportResource、@Import 等注解標記類,那么最終都是 Lite 模式:
@Component
public class JavaConfig {
@Bean
final User user() {
User user = new User();
user.setDog(dog());
return user;
}
@Bean
Dog dog() {
return new Dog();
}
}此時就是 Lite 模式,現在我們去 Spring 容器中獲取這個配置類:
public class JavaDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
JavaConfig config = ctx.getBean(JavaConfig.class);
System.out.println("config.getClass() = " + config.getClass());
}
}最終打印結果如下:

大家看到,我們從 Spring 容器中拿到的就是原始的對象,而不是一個被代理過的對象。因此:
- 由于 @Bean 注解標記的方法沒有被代理,因此,該方法可以是 final 也可以是 private,運行時都不會報錯。
- 由于 @Bean 方法沒有被代理,因此在 user 方法中調用 dog 方法的時候,就直接調用了,這就導致 user 中的 dog 和最終 dog 方法注冊到 Spring 容器中的 dog 不是同一個。
針對第二點,如果想要確保 user 中的 dog 和 Spring 容器中的 dog 是同一個,那么可以通過參數將所需要的對象注入進來,類似下面這樣:
@Component
public class JavaConfig {
@Bean
final User user(Dog dog) {
User user = new User();
user.setDog(dog);
return user;
}
@Bean
Dog dog() {
return new Dog();
}
}當 Spring 容器調用 user 方法初始化 User 對象時,發(fā)現該方法還有參數,因此會去容器中查找這個參數,找到了直接使用。
另外,我們也可以在類上添加 @Configuration 注解,但是通過修改屬性值來啟用 Lite 模式:
@Configuration(proxyBeanMethods = false)
public class JavaConfig {
@Bean
final User user(Dog dog) {
User user = new User();
user.setDog(dog);
return user;
}
@Bean
Dog dog() {
return new Dog();
}
}如果設置了 proxyBeanMethods 屬性為 false,那么也就是 Lite 模式了,其實我們從屬性名稱上也能看出來端倪:是否代理 @Bean 注解標記的方法。
4. 小結
總結一下:
- Lite 模式下,配置類中的方法就是普通方法,可以是 final 類型,也可以是 private。
- Lite 模式下,不需要通過 CGLIB 生成動態(tài)代理類,所以啟動速度會快一些。
- Lite 模式下,一個 @Bean 方法調用另外一個 @Bean 方法,會導致同一個 Bean 被初始化兩次。
- Full 模式下,會給配置類生成一個動態(tài)代理類,配置類中的所有方法都將被動態(tài)代理,因此配置類中的方法不能是 final 或者 private 的。
- Full 模式下,一個 @Bean 方法調用另外一個 @Bean 方法,動態(tài)代理方法會先去容器中檢查是否存在該 Bean,如果存在,則直接使用容器中的 Bean,否則才會去創(chuàng)建新的對象。
日常開發(fā)中,我們使用較多的是 Full 模式。
到此這篇關于Spring中@Configuration注解的Full模式和Lite模式詳解的文章就介紹到這了,更多相關@Configuration注解的Full模式和Lite模式內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- Spring中的@Configuration詳解
- SpringBoot中@EnableAutoConfiguration和@Configuration的區(qū)別
- SpringBoot中的@Configuration注解詳解
- 關于Spring中的@Configuration中的proxyBeanMethods屬性
- 詳解@ConfigurationProperties如何裝載到Spring容器中
- 詳解Spring中@Component和@Configuration的區(qū)別
- Spring關于@Configuration配置處理流程
- 關于SpringBoot的@ConfigurationProperties注解和松散綁定、數據校驗
相關文章
Java集合框架實戰(zhàn)HashMap與HashSet的使用案例
本文通過兩個案例詳細介紹了HashMap和HashSet在Java中的應用,通過這些案例,我們學習了如何選擇合適的集合類型、重寫equals和hashCode方法、利用泛型和并發(fā)集合等最佳實踐,感興趣的朋友跟隨小編一起看看吧2025-11-11
SpringBoot2零基礎到精通之自動配置底層分析及小技巧
SpringBoot是一種整合Spring技術棧的方式(或者說是框架),同時也是簡化Spring的一種快速開發(fā)的腳手架,本篇讓我們一起學習自動配置的底層分析與一些開發(fā)中的小技巧2022-03-03
java.net.SocketException:?Connection?reset異常的幾種原因分析和解決方法
這篇文章主要介紹了java.net.SocketException:?Connection?reset異常的幾種原因分析和解決方法,這個錯誤通常是由于連接被遠程主機關閉導致的,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2025-09-09

