一句話概括就是 @Configuration 中所有帶 @Bean 注解的方法都會被動態代理,因此呼叫該方法回傳的都是同一個實體,
理解:呼叫@Configuration類中的@Bean注解的方法,回傳的是同一個示例;而呼叫@Component類中的@Bean注解的方法,回傳的是一個新的實體,
注意:上面說的呼叫,而不是從spring容器中獲取! 見最下面的示例 1 及 示例 2
下面看看實作的細節,
@Configuration 注解:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
String value() default "";
}
從定義來看, @Configuration注解本質上還是@Component,因此 <context:component-scan/> 或者 @ComponentScan 都能處理@Configuration注解的類,
@Configuration標記的類必須符合下面的要求:
- 配置類必須以類的形式提供(不能是工廠方法回傳的實體),允許通過生成子類在運行時增強(cglib 動態代理),
- 配置類不能是final 類(沒法動態代理),
- 配置注解通常為了通過
@Bean注解生成 Spring 容器管理的類, - 配置類必須是非本地的(即不能在方法中宣告,不能是 private),
- 任何嵌套配置類都必須宣告為static,
@Bean方法可能不會反過來創建進一步的配置類(也就是回傳的 bean 如果帶有@Configuration,也不會被特殊處理,只會作為普通的 bean),
@Bean 注解方法執行策略
推薦一個開源免費的 Spring Boot 最全教程:
https://github.com/javastacks/spring-boot-best-practice
先給一個簡單的示例代碼:
@Configuration
public class MyBeanConfig {
@Bean
public Country country(){
return new Country();
}
@Bean
public UserInfo userInfo(){
return new UserInfo(country());
}
}
相信大多數人第一次看到上面 userInfo() 中呼叫 country()時,會認為這里的 Country和上面 @Bean方法回傳的 Country 可能不是同一個物件,因此可能會通過下面的方式來替代這種方式:
@Autowiredprivate Country country;
實際上不需要這么做(后面會給出需要這樣做的場景),直接呼叫country() 方法回傳的是同一個實體,
@Component 注解
@Component注解并沒有通過 cglib 來代理@Bean 方法的呼叫,因此像下面這樣配置時,就是兩個不同的 country,
@Component
public class MyBeanConfig {
@Bean
public Country country(){
return new Country();
}
@Bean
public UserInfo userInfo(){
return new UserInfo(country());
}
}
有些特殊情況下,我們不希望 MyBeanConfig被代理(代理后會變成WebMvcConfig$$EnhancerBySpringCGLIB$$8bef3235293)時,就得用 @Component,這種情況下,上面的寫法就需要改成下面這樣:
@Component
public class MyBeanConfig {
@Autowired
private Country country;
@Bean
public Country country(){
return new Country();
}
@Bean
public UserInfo userInfo(){
return new UserInfo(country);
}
}
這種方式可以保證使用的同一個 Country 實體,
示例 1:呼叫@Configuration類中的@Bean注解的方法,回傳的是同一個示例
第一個bean類
package com.xl.test.logtest.utils;
public class Child {
private String name = "the child";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
第二個bean類
package com.xl.test.logtest.utils;
public class Woman {
private String name = "the woman";
private Child child;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Child getChild() {
return child;
}
public void setChild(Child child) {
this.child = child;
}
}
@Configuration類
package com.xl.test.logtest.utils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Configuration
//@Component
public class Human {
@Bean
public Woman getWomanBean() {
Woman woman = new Woman();
woman.setChild(getChildBean()); // 直接呼叫@Bean注解的方法方法getChildBean()
return woman;
}
@Bean
public Child getChildBean() {
return new Child();
}
}
測驗類 I
本測驗類為一個配置類,這樣啟動專案是就可以看到測驗效果,更加快捷;也可以使用其他方式測驗見下面的測驗類 II
package com.xl.test.logtest.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Man {
@Autowired
public Man(Woman wn, Child child) {
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
System.out.println(wn.getChild() == child ? "是同一個物件":"不是同一個物件");
}
}
啟動專案,查看輸出結果:

測驗類 II
package com.xl.test.logtest.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.xl.test.logtest.utils.Child;
import com.xl.test.logtest.utils.Woman;
@RestController
public class LogTestController {
@Autowired
Woman woman ;
@Autowired
Child child;
@GetMapping("/log")
public String log() {
return woman.getChild() == child ? "是同一個物件":"不是同一個物件";
}
}
瀏覽器訪問專案,查看結果;輸入localhost:8080/log

示例 2 :呼叫@Component類中的@Bean注解的方法,回傳的是一個新的實體,
測驗代碼,只需要將@Configuration改為@Component即可!其他的均不變
package com.xl.test.logtest.utils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
//@Configuration
@Component
public class Human {
@Bean
public Woman getWomanBean() {
Woman woman = new Woman();
woman.setChild(getChildBean()); // 直接呼叫@Bean注解的方法方法getChildBean()
return woman;
}
@Bean
public Child getChildBean() {
return new Child();
}
}
測驗 :

控制臺和瀏覽器展示,均符合預期!
原文:blog.csdn.net/qq_29025955/article/details/128818957
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2022最新版)
2.勁爆!Java 協程要來了,,,
3.Spring Boot 2.x 教程,太全了!
4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!
5.《Java開發手冊(嵩山版)》最新發布,速速下載!
覺得不錯,別忘了隨手點贊+轉發哦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/546280.html
標籤:其他
上一篇:三天吃透Kafka面試八股文
