@Bean注解和@Configuration、@Component注解組合使用的區(qū)別
一、@Bean的“full”模式和“l(fā)ite”模式
在一般常見情況下,@Bean注解在@Configuration類中聲明,稱之為“full”模式;當@Bean注解和@Component注解組合使用時,稱之為“l(fā)ite”模式。
這兩種組合使用的情況,初次看文檔時沒看明白,多看了幾次又跑了測試代碼,才大致理解了區(qū)別。
二、兩種模式的差異
如果只是把@Bean注解用在方法上,并且各個@Bean注解的方法之間沒有調(diào)用,上述兩種模式達到的效果基本相同,都可以把@Bean注解方法返回的對象作為bean注冊到容器中。
如果各個@Bean注解的方法之間有相互調(diào)用,那么兩種模式就會有很大的區(qū)別-與full模式下的@Configuration不同,lite模式下 @Bean方法互相調(diào)用無法聲明Bean之間的依賴關系。
這點在@Bean注解源碼注釋上也有說明。
1、“full”模式下@Bean方法互相調(diào)用
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Configuration
public class Config {
@Bean()
public C c(){
return new C();
}
@Bean
public B b(){
return new B(c());
}
}
類B:
public class B {
public C c;
public B(C a){this.c=a;}
public void shutdown(){
System.out.println("b close...");
}
}
類C:
public class C {
private String name;
@PostConstruct
public void init(){
this.name = "I am a bean";
}
@Override
public String toString(){
return "c say:" + name;
}
}
如上述所示代碼,我們有兩個類B和C,在@Configuration類中,使用兩個@Bean方法分別定義bean b 和bean c,但是需要注意的是new B(c()) 所在的@Bean方法調(diào)用了另一個@Bean方法。
測試主程序類:
import com.dxc.opentalk.springtest.config.B;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@EnableAspectJAutoProxy
@ComponentScan("com.dxc.opentalk.springtest")
public class BootStrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext
= new AnnotationConfigApplicationContext(BootStrap.class);
B b = (B)applicationContext.getBean("b");
System.out.println(b.c);
System.out.println(applicationContext.getBean("c"));
System.out.println(applicationContext.getBean("c").equals(b.c));
}
}
程序輸出結(jié)果:
c say:I am a bean
c say:I am a bean
true
可以看出bean c 被注入到了bean b 中,bean b中的成員 c 確實是Spring容器中的bean。(其實,debug程序跟蹤Spring中的單例池更清晰,這里采用輸出結(jié)果說明)
2、“l(fā)ite”模式下@Bean方法互相調(diào)用
還是上面的代碼,我們只把Config類上的注解更換成@Component,其余代碼保持不變:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Component
public class Config {
@Bean()
public C c(){
return new C();
}
@Bean
public B b(){
return new B(c());
}
}
再看一下測試主程序類輸出結(jié)果:
c say:null
c say:I am a bean
false
可以看到bean b中的c只是一個普通的c對象,并不是Spring容器中的bean(b中的c沒有執(zhí)行bean的初始化回調(diào)方法也和單例池中的c bean不相等)。所以這種模式下,@Bean方法互相調(diào)用不能完成bean之間相互依賴關系的注入。
三、總結(jié)
綜上所述,在使用@Bean注解時需要注意兩種模式的區(qū)別,一般情況下@Bean都是和@Configuration注解搭配使用的。
但是@Configuration注解的類會被Spring使用CGLIB子類化,所以@Configuration注解的類不能用 final 修飾,而@Component注解沒有此限制。
如果使用@Bean注解和@Component注解組合需要完成bean之間相互依賴注入的話,官方推薦采用構(gòu)造方法或者方法級別的依賴注入,如下:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Component
public final class Config {
@Bean()
public C c(){
return new C();
}
@Bean
public B b(C c){//構(gòu)造方法注入
return new B(c);
}
}
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
在Windows系統(tǒng)下安裝Thrift的方法與使用講解
今天小編就為大家分享一篇關于在Windows系統(tǒng)下安裝Thrift的方法與使用講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12
Spring?Security放行的接口Knife4j靜態(tài)資源的問題小結(jié)
這篇文章主要介紹了Spring?Security使用Knife4j靜態(tài)資源的問題小結(jié),項目中使用?Spring?Security?做身份認證和授權(quán),使用?Knife4j?做接口調(diào)試,需要?Spring?Security?放行的接口記錄在?RequestMatcherConstant?類中,感興趣的朋友跟隨小編一起看看吧2024-02-02
SpringBoot集成xxl-job實現(xiàn)超牛的定時任務的步驟詳解
XXL-JOB是一個分布式任務調(diào)度平臺,其核心設計目標是開發(fā)迅速、學習簡單、輕量級、易擴展,現(xiàn)已開放源代碼并接入多家公司線上產(chǎn)品線,開箱即用,本文給大家介紹了SpringBoot集成xxl-job實現(xiàn)超牛的定時任務,需要的朋友可以參考下2023-10-10
基于javaweb+jsp的游泳館會員管理系統(tǒng)(附源碼)
這篇文章主要介紹了基于javaweb+jsp的游泳館會員管理系統(tǒng),開發(fā)工具eclipse/idea/myeclipse/sts等均可配置運行,此源代碼社和課程設計,大作業(yè)及畢業(yè)設計項目,需要的朋友可以參考下2022-04-04

