springboot @Configuration和@Componment的區(qū)別及說(shuō)明
@Configuration和@Componment的區(qū)別
@Configuration
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Configuration { @AliasFor( annotation = Component.class ) String value() default ""; }
public class Car { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } public class Driver { private int id; private String name; private Car car; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } } import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MyTestConfig { @Bean public Driver driver() { Driver driver = new Driver(); driver.setId(1); driver.setName("driver"); driver.setCar(car()); return driver; } @Bean public Car car() { Car car = new Car(); car.setId(1); car.setName("car"); return car; } } import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Component public class MyTestConfig { @Bean public Driver driver() { Driver driver = new Driver(); driver.setId(1); driver.setName("driver"); driver.setCar(car()); return driver; } @Bean public Car car() { Car car = new Car(); car.setId(1); car.setName("car"); return car; } }
上面兩段代碼除MyTestConfig類(lèi)上的注解不同之外其他都相同,但Spring對(duì)兩者的處理方式是完全不一樣的。
第一段代碼會(huì)像我們期望的一樣正常運(yùn)行
因?yàn)閐river()這段代碼中driver.setCar(car())方法會(huì)由Spring代理執(zhí)行,
Spring發(fā)現(xiàn)方法所請(qǐng)求的Bean已經(jīng)在容器中,那么就直接返回容器中的Bean。
所以全局只有一個(gè)Car對(duì)象的實(shí)例。
第二段代碼在執(zhí)行driver()
時(shí)driver.setCar(car())不會(huì)被Spring代理,會(huì)直接調(diào)用car()方法獲取一個(gè)全新的Car對(duì)象實(shí)例,所以全局會(huì)有多個(gè)Car對(duì)象的實(shí)例
造成這種差異的原因如下:
概括就是 @Configuration 中所有帶 @Bean
注解的方法都會(huì)被動(dòng)態(tài)代理,因此調(diào)用該方法返回的都是同一個(gè)實(shí)例。
其工作原理是:如果方式是首次被調(diào)用那么原始的方法體會(huì)被執(zhí)行并且結(jié)果對(duì)象會(huì)被注冊(cè)到Spring上下文中,之后所有的對(duì)該方法的調(diào)用僅僅只是從Spring上下文中取回該對(duì)象返回給調(diào)用者。
在上面的第二段代碼中
driver.setCar(car())只是純JAVA方式的調(diào)用,多次調(diào)用該方法返回的是不同的對(duì)象實(shí)例。
要修正第二段代碼中的問(wèn)題,可以使用@Autowired如下所示:
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 @Component public class MyTestConfig2 { @Autowired Car car; @Bean public Driver driver() { Driver driver = new Driver(); driver.setId(1); driver.setName("driver"); driver.setCar(car); return driver; } @Bean public Car car() { Car car = new Car(); car.setId(1); car.setName("car"); return car; } }
總結(jié)
1. 通過(guò)@Configuration或者@Componment注解的類(lèi)默認(rèn)是非懶加載,可以使用@Lazy或者在@Bean上@Lazy開(kāi)啟懶加載;
2. 通過(guò)@Configuration注解的類(lèi)默認(rèn)會(huì)被CGLIB動(dòng)態(tài)代理,所有被 @Bean 注解標(biāo)記的方法將來(lái)都是通過(guò)代理方法進(jìn)行調(diào)用,在該類(lèi)中使用@Bean時(shí)為單列;
3. 通過(guò)@Componment注解的類(lèi)默認(rèn)不會(huì)產(chǎn)生動(dòng)態(tài)代理,在該類(lèi)中使用@Bean,是多實(shí)例的。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring 4.0新功能:@Conditional注解詳細(xì)介紹
Spring Boot的強(qiáng)大之處在于使用了Spring 4框架的新特性:@Conditional注釋?zhuān)俗⑨屖沟弥挥性谔囟l件滿(mǎn)足時(shí)才啟用一些配置。下面這篇文章主要給大家介紹了關(guān)于Spring4.0中新功能:@Conditional注解的相關(guān)資料,需要的朋友可以參考下。2017-09-09java 數(shù)據(jù)結(jié)構(gòu)中棧和隊(duì)列的實(shí)例詳解
這篇文章主要介紹了java 數(shù)據(jù)結(jié)構(gòu)中棧和隊(duì)列的實(shí)例詳解的相關(guān)資料,主要使用數(shù)組與線(xiàn)性表的方法來(lái)實(shí)現(xiàn),需要的朋友可以參考下2017-09-09Mybatis如何使用動(dòng)態(tài)語(yǔ)句實(shí)現(xiàn)批量刪除(delete結(jié)合foreach)
這篇文章主要介紹了Mybatis如何使用動(dòng)態(tài)語(yǔ)句實(shí)現(xiàn)批量刪除(delete結(jié)合foreach),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03Springboot+Mybatis實(shí)現(xiàn)分頁(yè)加條件查詢(xún)功能
這篇文章主要為大家詳細(xì)介紹了Springboot+Mybatis實(shí)現(xiàn)分頁(yè)加條件查詢(xún),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04java Collection 之List學(xué)習(xí)介紹
本篇文章小編為大家介紹,java Collection 之List學(xué)習(xí)介紹。需要的朋友參考下2013-04-04java實(shí)現(xiàn)簡(jiǎn)單的ATM項(xiàng)目
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單的ATM項(xiàng)目,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-10-10Java數(shù)據(jù)結(jié)構(gòu)中雙向鏈表的實(shí)現(xiàn)
這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)中雙向鏈表的實(shí)現(xiàn),雙向鏈表是一種常見(jiàn)的數(shù)據(jù)結(jié)構(gòu),它允許在鏈表中的任意位置進(jìn)行高效的插入和刪除操作,需要的朋友可以參考下2022-05-05