終于搞懂了 @Configuration 和 @Component 的區(qū)別
閱讀本文大概需要 3.5 分鐘。
來自:blog.csdn.net/qq_29025955/article/details/128818957
@Configuration 中所有帶 @Bean 注解的方法都會被動態(tài)代理,因此調(diào)用該方法返回的都是同一個實例。@Configuration類中的@Bean注解的方法,返回的是同一個示例;而調(diào)用@Component類中的@Bean注解的方法,返回的是一個新的實例。注意:上面說的調(diào)用,而不是從spring容器中獲取! 見最下面的示例 1 及 示例 2
@Configuration 注解:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
String value() default "";
}
@Configuration注解本質(zhì)上還是@Component,因此 <context:component-scan/> 或者 @ComponentScan 都能處理@Configuration注解的類。@Configuration標(biāo)記的類必須符合下面的要求:配置類必須以類的形式提供(不能是工廠方法返回的實例),允許通過生成子類在運行時增強(qiáng)(cglib 動態(tài)代理)。
配置類不能是final 類(沒法動態(tài)代理)。
配置注解通常為了通過
@Bean注解生成 Spring 容器管理的類,配置類必須是非本地的(即不能在方法中聲明,不能是 private)。
任何嵌套配置類都必須聲明為static。
@Bean方法可能不會反過來創(chuàng)建進(jìn)一步的配置類(也就是返回的 bean 如果帶有@Configuration,也不會被特殊處理,只會作為普通的 bean)。
@Bean 注解方法執(zhí)行策略
@Configuration
public class MyBeanConfig {
@Bean
public Country country(){
return new Country();
}
@Bean
public UserInfo userInfo(){
return new UserInfo(country());
}
}
userInfo() 中調(diào)用 country()時,會認(rèn)為這里的 Country和上面 @Bean方法返回的 Country 可能不是同一個對象,因此可能會通過下面的方式來替代這種方式:@Autowiredprivate Country country;
country() 方法返回的是同一個實例。@Component 注解
@Component注解并沒有通過 cglib 來代理@Bean 方法的調(diào)用,因此像下面這樣配置時,就是兩個不同的 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);
}
}
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;
}
}
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()); // 直接調(diào)用@Bean注解的方法方法getChildBean()
return woman;
}
@Bean
public Child getChildBean() {
return new Child();
}
}
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 ? "是同一個對象":"不是同一個對象");
}
}

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
@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()); // 直接調(diào)用@Bean注解的方法方法getChildBean()
return woman;
}
@Bean
public Child getChildBean() {
return new Child();
}
}

推薦閱讀:
互聯(lián)網(wǎng)初中高級大廠面試題(9個G) 內(nèi)容包含Java基礎(chǔ)、JavaWeb、MySQL性能優(yōu)化、JVM、鎖、百萬并發(fā)、消息隊列、高性能緩存、反射、Spring全家桶原理、微服務(wù)、Zookeeper......等技術(shù)棧!
?戳閱讀原文領(lǐng)?。?/span> 朕已閱


