@Bean注解和@Configuration、@Component注解組合使用的區(qū)別
一、@Bean的“full”模式和“l(fā)ite”模式
在一般常見情況下,@Bean注解在@Configuration類中聲明,稱之為“full”模式;當(dāng)@Bean注解和@Component注解組合使用時(shí),稱之為“l(fā)ite”模式。
這兩種組合使用的情況,初次看文檔時(shí)沒看明白,多看了幾次又跑了測(cè)試代碼,才大致理解了區(qū)別。
二、兩種模式的差異
如果只是把@Bean注解用在方法上,并且各個(gè)@Bean注解的方法之間沒有調(diào)用,上述兩種模式達(dá)到的效果基本相同,都可以把@Bean注解方法返回的對(duì)象作為bean注冊(cè)到容器中。
如果各個(gè)@Bean注解的方法之間有相互調(diào)用,那么兩種模式就會(huì)有很大的區(qū)別-與full模式下的@Configuration不同,lite模式下 @Bean方法互相調(diào)用無法聲明Bean之間的依賴關(guān)系。
這點(diǎn)在@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;
}
}
如上述所示代碼,我們有兩個(gè)類B和C,在@Configuration類中,使用兩個(gè)@Bean方法分別定義bean b 和bean c,但是需要注意的是new B(c()) 所在的@Bean方法調(diào)用了另一個(gè)@Bean方法。
測(cè)試主程序類:
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 確實(shí)是Spring容器中的bean。(其實(shí),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());
}
}
再看一下測(cè)試主程序類輸出結(jié)果:
c say:null
c say:I am a bean
false
可以看到bean b中的c只是一個(gè)普通的c對(duì)象,并不是Spring容器中的bean(b中的c沒有執(zhí)行bean的初始化回調(diào)方法也和單例池中的c bean不相等)。所以這種模式下,@Bean方法互相調(diào)用不能完成bean之間相互依賴關(guān)系的注入。
三、總結(jié)
綜上所述,在使用@Bean注解時(shí)需要注意兩種模式的區(qū)別,一般情況下@Bean都是和@Configuration注解搭配使用的。
但是@Configuration注解的類會(huì)被Spring使用CGLIB子類化,所以@Configuration注解的類不能用 final 修飾,而@Component注解沒有此限制。
如果使用@Bean注解和@Component注解組合需要完成bean之間相互依賴注入的話,官方推薦采用構(gòu)造方法或者方法級(jí)別的依賴注入,如下:
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);
}
}
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
在Windows系統(tǒng)下安裝Thrift的方法與使用講解
今天小編就為大家分享一篇關(guān)于在Windows系統(tǒng)下安裝Thrift的方法與使用講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-12-12
java中Map如何根據(jù)key的大小進(jìn)行排序詳解
這篇文章主要給大家介紹了關(guān)于java中Map如何根據(jù)key的大小進(jìn)行排序的相關(guān)資料,有時(shí)候我們業(yè)務(wù)上需要對(duì)map里面的值按照key的大小來進(jìn)行排序的時(shí)候我們就可以利用如下方法來進(jìn)行排序了,需要的朋友可以參考下2023-09-09
Spring?Security放行的接口Knife4j靜態(tài)資源的問題小結(jié)
這篇文章主要介紹了Spring?Security使用Knife4j靜態(tài)資源的問題小結(jié),項(xiàng)目中使用?Spring?Security?做身份認(rèn)證和授權(quán),使用?Knife4j?做接口調(diào)試,需要?Spring?Security?放行的接口記錄在?RequestMatcherConstant?類中,感興趣的朋友跟隨小編一起看看吧2024-02-02
SpringBoot集成xxl-job實(shí)現(xiàn)超牛的定時(shí)任務(wù)的步驟詳解
XXL-JOB是一個(gè)分布式任務(wù)調(diào)度平臺(tái),其核心設(shè)計(jì)目標(biāo)是開發(fā)迅速、學(xué)習(xí)簡單、輕量級(jí)、易擴(kuò)展,現(xiàn)已開放源代碼并接入多家公司線上產(chǎn)品線,開箱即用,本文給大家介紹了SpringBoot集成xxl-job實(shí)現(xiàn)超牛的定時(shí)任務(wù),需要的朋友可以參考下2023-10-10
基于javaweb+jsp的游泳館會(huì)員管理系統(tǒng)(附源碼)
這篇文章主要介紹了基于javaweb+jsp的游泳館會(huì)員管理系統(tǒng),開發(fā)工具eclipse/idea/myeclipse/sts等均可配置運(yùn)行,此源代碼社和課程設(shè)計(jì),大作業(yè)及畢業(yè)設(shè)計(jì)項(xiàng)目,需要的朋友可以參考下2022-04-04
Java 對(duì)HashMap進(jìn)行排序的三種常見方法
這篇文章主要介紹了Java 對(duì)HashMap進(jìn)行排序的三種常見方法,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下2020-10-10
詳解maven中profiles使用實(shí)現(xiàn)
本文主要介紹了maven中profiles使用實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02

