SpringBoot?@Configuration與@Bean注解使用介紹
之前我們都是通過(guò)xml的方式定義bean,里面會(huì)寫(xiě)很多bean元素,然后spring啟動(dòng)的時(shí)候,就會(huì)讀取bean xml配置文件,然后解析這些配置,然后會(huì)將這些bean注冊(cè)到spring容器中,供使用者使用。
Spring3.0開(kāi)始,@Configuration用于定義配置類,定義的配置類可以替換xml文件,一般和@Bean注解聯(lián)合使用。
@Configuration注解可以加在類上,讓這個(gè)類的功能等同于一個(gè)bean xml配置文件。
@Bean注解類似于bean xml配置文件中的bean元素,用來(lái)在spring容器中注冊(cè)一個(gè)bean。
demo示例
1.創(chuàng)建一個(gè)工程
2.創(chuàng)建bean文件夾并創(chuàng)建兩個(gè)示例用戶和部門(mén)
如下:
用戶
package com.example.ethan.bean; public class User { private String name; private Integer age; private Dept dept; public User() { } public User(String name, Integer age) { this.name = name; this.age = age; } public Dept getDept() { return dept; } public void setDept(Dept dept) { this.dept = dept; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
部門(mén)
package com.example.ethan.bean; public class Dept { private String name; public Dept(String name) { this.name = name; } }
3.創(chuàng)建配置類
使用@Configuration注解,并使用@Bean注解創(chuàng)建bean
package com.example.ethan.config; import com.example.ethan.bean.Dept; import com.example.ethan.bean.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration //告訴SpringBoot這是一個(gè)配置類 == 配置文件 public class ConfigDemo { @Bean //給容器中添加組件。以方法名作為組件的id。返回類型就是組件類型。返回的值,就是組件在容器中的實(shí)例 public User user01(){ User zhangsan = new User("zhangsan", 18); return zhangsan; } @Bean("my rd") public Dept rd(){ return new Dept("研發(fā)部"); } }
4.在主程序查看
編寫(xiě)主程序,查看容器中的Bean
package com.example.ethan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class EthanApplication { public static void main(String[] args) { // 返回ioc容器 ConfigurableApplicationContext run = SpringApplication.run(EthanApplication.class, args); // 查看容器組件 String[] beanDefinitionNames = run.getBeanDefinitionNames(); System.out.println("========================"); for (String name : beanDefinitionNames) { System.out.println(name); } } }
運(yùn)行后可以看到configDemo、user01、my rd都已經(jīng)被容器管理。
特點(diǎn)和特性
1.配置類本身也是組件,也會(huì)有被IOC容器管理的Bean,且是一個(gè)單實(shí)例的代理對(duì)象。
在主程序驗(yàn)證代碼如下:
ConfigDemo bean = run.getBean(ConfigDemo.class); System.out.println(bean);
// 結(jié)果:com.example.ethan.config.ConfigDemo$$EnhancerBySpringCGLIB$$24eef7b3@a619c2
可以看到得到的bean是一個(gè)CGLIB代理對(duì)象。
2.默認(rèn)被IOC容器管理@Bean注解產(chǎn)生的Bean是單實(shí)例的。
在主程序驗(yàn)證代碼如下:
Dept d1 = run.getBean("my rd", Dept.class); Dept d2 = run.getBean("my rd", Dept.class); System.out.println("組件:"+(d1 == d2)); // 組件:true
結(jié)果為true,證明@Bean注解產(chǎn)生的Bean是單實(shí)例的。
3.@configration的proxyBeanMethods屬性。
這個(gè)屬性默認(rèn)為true。他的意思就是,當(dāng)從容器獲取Bean時(shí),是否用上面第1點(diǎn)中的代理對(duì)象調(diào)用方法獲取bean。
增加驗(yàn)證如下:
ConfigDemo bean = run.getBean(ConfigDemo.class); System.out.println(bean); // 如果@Configuration(proxyBeanMethods = true)代理對(duì)象調(diào)用方法 User user = bean.user01(); User user1 = bean.user01(); System.out.println(user == user1);
當(dāng)configration的proxyBeanMethods=true時(shí),結(jié)果為true,否則結(jié)果為false。
也就是,當(dāng)proxyBeanMethods=true,使用代理對(duì)象獲取Bean,代理會(huì)攔截所有被@Bean修飾的方法,默認(rèn)情況(bean為單例)下確保這些方法只被調(diào)用一次,放進(jìn)容器,然后從容器查找到,就會(huì)直接使用,從而確保這些bean是同一個(gè)bean,即單例的。
否則,不使用代理對(duì)象獲取Bean,每次獲取都新建,所以兩個(gè)Bean不相等。
這樣做的主要目的是為了解決組件依賴問(wèn)題,比如下面的部門(mén)被用戶
依賴,可以保證用戶依賴的部門(mén)是單實(shí)例。
驗(yàn)證代碼如下:
首先讓用戶依賴部門(mén)
package com.example.ethan.config; import com.example.ethan.bean.Dept; import com.example.ethan.bean.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration(proxyBeanMethods=true) //告訴SpringBoot這是一個(gè)配置類 == 配置文件 public class ConfigDemo { @Bean //給容器中添加組件。以方法名作為組件的id。返回類型就是組件類型。返回的值,就是組件在容器中的實(shí)例 public User user01(){ User zhangsan = new User("zhangsan", 18); //user組件依賴了Dept組件 zhangsan.setDept(rd()); return zhangsan; } @Bean("my rd") public Dept rd(){ return new Dept("研發(fā)部"); } }
然后測(cè)試用戶依賴的組件是否是容器中的Bean
User user01 = run.getBean("user01", User.class); Dept dept = run.getBean("tom", Dept.class); System.out.println("用戶的寵物:"+(user01.getDept() == dept)); // // 用戶的部門(mén):true
測(cè)試可以看到,當(dāng)proxyBeanMethods=true時(shí),結(jié)果為true,否則為false。
當(dāng)proxyBeanMethods=true時(shí)也稱為 Full模式,否則稱為L(zhǎng)ite模式。
Full(proxyBeanMethods = true)【保證每個(gè)@Bean方法被調(diào)用多少次返回的組件都是單實(shí)例的】
Lite(proxyBeanMethods = false)【每個(gè)@Bean方法被調(diào)用多少次返回的組件都是新創(chuàng)建的】
組件依賴必須使用Full模式默認(rèn)。其他默認(rèn)是否Lite模式。
最佳實(shí)戰(zhàn)
- 配置 類組件之間無(wú)依賴關(guān)系用Lite模式加速容器啟動(dòng)過(guò)程,減少判斷
- 配置類組件之間有依賴關(guān)系,方法會(huì)被調(diào)用得到之前單實(shí)例組件,用Full模式
到此這篇關(guān)于SpringBoot @Configuration與@Bean注解使用介紹的文章就介紹到這了,更多相關(guān)SpringBoot @Configuration與@Bean內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java使用HttpUtils實(shí)現(xiàn)發(fā)送HTTP請(qǐng)求
這篇文章主要介紹了Java使用HttpUtils實(shí)現(xiàn)發(fā)送HTTP請(qǐng)求,HTTP請(qǐng)求,在日常開(kāi)發(fā)中,還是比較常見(jiàn)的,今天給大家分享HttpUtils如何使用,需要的朋友可以參考下2023-05-05java多線程中的生產(chǎn)者和消費(fèi)者隊(duì)列詳解
這篇文章主要介紹了java多線程中的生產(chǎn)者和消費(fèi)者隊(duì)列詳解,隊(duì)列,是一種數(shù)據(jù)結(jié)構(gòu),除了優(yōu)先級(jí)隊(duì)列和LIFO隊(duì)列外,隊(duì)列都是以FIFO(先進(jìn)先出)的方式對(duì)各個(gè)元素進(jìn)行排序的,需要的朋友可以參考下2024-01-01java多線程編程之Synchronized關(guān)鍵字詳解
這篇文章主要為大家詳細(xì)介紹了java多線程編程之Synchronized關(guān)鍵字,感興趣的朋友可以參考一下2016-05-05SpringSecurity登錄使用JSON格式數(shù)據(jù)的方法
這篇文章主要介紹了SpringSecurity登錄使用JSON格式數(shù)據(jù)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-02-02Spring?Boot?Reactor?整合?Resilience4j詳析
這篇文章主要介紹了Spring?Boot?Reactor整合Resilience4j詳析,文章通過(guò)引入pom包展開(kāi)詳細(xì)介紹,具有一定的參考價(jià)值,感興趣的小伙伴可以參考一下2022-09-09詳解Java如何實(shí)現(xiàn)加密或者解密PDF文檔
PDF文檔加密是一種用于保護(hù)文件內(nèi)容的功能。這篇文章主要介紹了Java實(shí)現(xiàn)加密或者解密PDF文檔的方法,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-03-03