亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Bean的管理與SpringBoot自動裝配原理解讀

 更新時間:2024年11月04日 16:11:24   作者:薛定諤的鹽.  
在SpringBoot項目中,啟動時自動創(chuàng)建IOC容器并初始化bean對象,支持通過依賴注入獲取,Bean可以通過name或類型獲取,支持單例和非單例等多種作用域,對于第三方Bean,推薦在配置類中用@Bean標識方法進行定義

1、Bean管理

默認情況下,SpringBoot項目在啟動的時候會自動的創(chuàng)建IOC容器,并且在啟動的過程當中會自動的將bean對象都創(chuàng)建好,存放在IOC容器當中。

應(yīng)用程序在運行時需要依賴什么bean對象,就直接進行依賴注入就可以了。

1.1 獲取Bean

要想主動從IOC容器中獲取到bean對象,需要先拿到IOC容器

想獲取到IOC容器,直接將IOC容器對象注入進來就可以了

@Autowired
private ApplicationContext applicationContext; //IOC容器對象

在IOC容器中提供了一些方法,可以主動從IOC容器中獲取到bean對象,

介紹3種常用方式:

1.根據(jù)name獲取bean

Object getBean(String name)

2.根據(jù)類型獲取bean

<T> T getBean(Class<T> requiredType)

3.根據(jù)name獲取bean(帶類型轉(zhuǎn)換)

&lt;T&gt; T getBean(String name, Class&lt;T&gt; requiredType)
@SpringBootTest
class SpringbootTheoryApplicationTests {

    @Autowired
    private ApplicationContext applicationContext; //IOC容器對象

    //獲取bean對象
    @Test
    public void testGetBean(){
        //根據(jù)bean的名稱獲取
        MyController bean1 = (MyController) applicationContext.getBean("myController");
        System.out.println(bean1);

        //根據(jù)bean的類型獲取
        MyController bean2 = applicationContext.getBean(MyController.class);
        System.out.println(bean2);

        //根據(jù)bean的名稱 及 類型獲取
        MyController bean3 = applicationContext.getBean("myController", MyController.class);
        System.out.println(bean3);
    }

}

運行結(jié)果:

com.wbr.controller.MyController@2fa47368

com.wbr.controller.MyController@2fa47368

com.wbr.controller.MyController@2fa47368

可以看到三個bean的打印結(jié)果都是一樣的,說明IOC容器當中的bean對象只有一個。

默認情況下,IOC中的bean對象是單例

1.2 Bean的作用域

IOC容器中,默認bean對象是單例模式(只有一個實例對象)。

想要設(shè)置bean對象為非單例就需要設(shè)置bean的作用域。

在Spring中支持五種作用域,后三種在web環(huán)境才生效:

作用域說明
singleton容器內(nèi)同名稱的bean只有一個實例(單例)(默認)
prototype每次使用該bean時會創(chuàng)建新的實例(非單例)
request每個請求范圍內(nèi)會創(chuàng)建新的實例
session每個會話范圍內(nèi)會創(chuàng)建新的實例
application每個應(yīng)用范圍內(nèi)會創(chuàng)建新的實例

可以借助Spring中的@Scope注解來進行配置作用域

測試一:

Controller類

//當我們未加@Scope注解時,默認bean的作用域為:@Scope("singleton") (單例模式)
@Lazy //延遲加載(第一次使用bean對象時,才會創(chuàng)建bean對象并交給ioc容器管理)
@RestController
public class MyController {

    @Autowired
    private MyService myService;

    public MyController(){
        System.out.println("MyController 構(gòu)造方法執(zhí)行了...");
    }
}

測試類

@SpringBootTest
class SpringbootTheoryApplicationTests {

    @Autowired
    private ApplicationContext applicationContext; //IOC容器對象

    //獲取bean對象
    @Test
    public void testGetBean(){
        //根據(jù)bean的名稱獲取
        MyController bean1 = (MyController) applicationContext.getBean("myController");
        System.out.println(bean1);

        //根據(jù)bean的類型獲取
        MyController bean2 = applicationContext.getBean(MyController.class);
        System.out.println(bean2);

        //根據(jù)bean的名稱 及 類型獲取
        MyController bean3 = applicationContext.getBean("myController", MyController.class);
        System.out.println(bean3);
    }
}

運行結(jié)果:

MyController 構(gòu)造方法執(zhí)行了...
com.wbr.controller.MyController@3835d3fd
com.wbr.controller.MyController@3835d3fd
com.wbr.controller.MyController@3835d3fd

注意事項:

  • IOC容器中的bean默認使用的作用域:singleton (單例)
  • 默認singleton的bean,在容器啟動時被創(chuàng)建,可以使用@Lazy注解來延遲初始化(延遲到第一次使用時)

測試二:

給MyController加上@Scope("prototype")注解:

@Lazy //延遲加載(第一次使用bean對象時,才會創(chuàng)建bean對象并交給ioc容器管理)
@Scope("prototype")
@RestController
public class MyController {

    @Autowired
    private MyService myService;

    public MyController(){
        System.out.println("MyController 構(gòu)造方法執(zhí)行了...");
    }
}

再次運行測試方法得到以下結(jié)果:

MyController 構(gòu)造方法執(zhí)行了...
com.wbr.controller.MyController@73aae7a
MyController 構(gòu)造方法執(zhí)行了...
com.wbr.controller.MyController@3856d0cb
MyController 構(gòu)造方法執(zhí)行了...
com.wbr.controller.MyController@2125535d

注意事項:

  • prototype的bean,每一次使用該bean的時候都會創(chuàng)建一個新的實例
  • 實際開發(fā)當中,絕大部分的Bean是單例的,也就是說絕大部分Bean不需要配置scope屬性

1.3 第三方Bean

情況1:自定義類上加上@Component以及它的這三個衍生注解@Controller、@Service、@Repository,用來聲明這個bean對象。

情況2:這個類它不是我們自己編寫的,而是我們引入的第三方依賴當中提供的。

我們可以使用 ObjectMapper 作為第三方依賴。ObjectMapper 是 Jackson 庫中的核心類,用于在 Java 對象和 JSON 之間進行轉(zhuǎn)換。

當我們需要使用到ObjectMapper對象時,應(yīng)該如何進行依賴注入?

由于第三方提供的類是只讀的。無法在第三方類上添加@Component注解或衍生注解。

解決方案1:在啟動類上添加用@Bean標識的方法

啟動類:

@SpringBootApplication
public class SpringbootTheoryApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootTheoryApplication.class, args);
    }

    //聲明第三方bean
    @Bean //將當前方法的返回值對象交給IOC容器管理, 成為IOC容器bean
    public ObjectMapper objectMapper(){
        return new ObjectMapper();
    }
}

測試類:

@SpringBootTest
class SpringbootWebConfig2ApplicationTests {

    @Autowired
    private ObjectMapper objectMapper;

    // 第三方bean的管理
    @Test
    public void testThirdBean() throws Exception {
        // 將 JSON 字符串轉(zhuǎn)換為 Java 對象
        String json = "{\"name\":\"zhangsan\",\"age\":21}";
        Person person = objectMapper.readValue(json, Person.class);

        System.out.println(person.getName() + " : " + person.getAge());
    }

    // 用于測試的簡單 POJO 類
    static class Person {
        private String name;
        private int age;


        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }
    }
}

運行結(jié)果:

zhangsan : 21

注意事項:

  • 以上在啟動類中聲明第三方Bean的作法,不建議使用(項目中要保證啟動類的純粹性)

解決方案2:在配置類中定義@Bean標識的方法

  • 如果需要定義第三方Bean時, 通常會單獨定義一個配置類
@Configuration //聲明一個配置類
public class ObjectMapperConfig {
    
    @Bean
    public ObjectMapper objectMapper() {
        return new ObjectMapper();
    }
}

注釋掉SpringBoot啟動類中創(chuàng)建第三方bean對象的代碼,重新執(zhí)行測試方法:

zhangsan : 21

在方法上加上一個@Bean注解,Spring 容器在啟動的時候,它會自動的調(diào)用這個方法,并將方法的返回值聲明為Spring容器當中的Bean對象。

注意事項 :

  • 通過@Bean注解的name或value屬性可以聲明bean的名稱,如果不指定,默認bean的名稱就是方法名。
  • 如果第三方bean需要依賴其它bean對象,直接在bean定義方法中設(shè)置形參即可,容器會根據(jù)類型自動裝配。

2、SpringBoot原理

SpringBoot框架之所以使用起來更簡單更快捷,是因為SpringBoot框架底層提供了兩個非常重要的功能:一個是起步依賴,一個是自動配置。

2.1 起步依賴

假如沒有使用SpringBoot,用的是Spring框架進行web程序的開發(fā),此時我們就需要引入web程序開發(fā)所需要的一些依賴。

  • spring-webmvc依賴:這是Spring框架進行web程序開發(fā)所需要的依賴
  • servlet-api依賴:Servlet基礎(chǔ)依賴
  • jackson-databind依賴:JSON處理工具包

如果要使用AOP,還需要引入aop依賴、aspect依賴

項目中所引入的這些依賴,還需要保證版本匹配,否則就可能會出現(xiàn)版本沖突問題。

使用了SpringBoot,就不需要像上面這么繁瑣的引入依賴了。由于Maven的依賴傳遞。我們只需要引入一個依賴就可以了,那就是web開發(fā)的起步依賴:springboot-starter-web。

在web開發(fā)的起步依賴當中,就集成了web開發(fā)中常見的依賴:json、web、webmvc、tomcat等。我們只需要引入這一個起步依賴,其他的依賴都會自動的通過Maven的依賴傳遞進來。

2.2 SpringBoot自動裝配

話不多說,上源碼跟蹤圖??!

2.3 @Conditional

我們在跟蹤SpringBoot自動配置的源碼的時候,在自動配置類聲明bean的時候,除了在方法上加了一個@Bean注解以外,還會經(jīng)常用到一個注解,就是以Conditional開頭的這一類的注解。

以Conditional開頭的這些注解都是條件裝配的注解。下面我們就來介紹下條件裝配注解。

@Conditional注解:

  • 作用:按照一定的條件進行判斷,在滿足給定條件后才會注冊對應(yīng)的bean對象到Spring的IOC容器中。
  • 位置:方法、類

@Conditional本身是一個父注解,派生出大量的子注解:

  • @ConditionalOnClass:判斷環(huán)境中有對應(yīng)字節(jié)碼文件,才注冊bean到IOC容器。
  • @ConditionalOnMissingBean:判斷環(huán)境中沒有對應(yīng)的bean(類型或名稱),才注冊bean到IOC容器。
  • @ConditionalOnProperty:判斷配置文件中有對應(yīng)屬性和值,才注冊bean到IOC容器。

下面我們通過代碼來演示下Conditional注解的使用:

  • @ConditionalOnClass注解
@Configuration
public class HeaderConfig {
?
    @Bean
    @ConditionalOnClass(name="io.jsonwebtoken.Jwts")//環(huán)境中存在指定的這個類,才會將該bean加入IOC容器
    public HeaderParser headerParser(){
        return new HeaderParser();
    }
    
}
  • 測試類
@SpringBootTest
public class AutoConfigurationTests {
    @Autowired
    private ApplicationContext applicationContext;
?
    @Test
    public void testHeaderParser(){
        System.out.println(applicationContext.getBean(HeaderParser.class));
    }
}

執(zhí)行testHeaderParser()測試方法:

因為io.jsonwebtoken.Jwts字節(jié)碼文件在啟動SpringBoot程序時已存在,所以創(chuàng)建HeaderParser對象并注冊到IOC容器中。

  • @ConditionalOnMissingBean注解
@Configuration
public class HeaderConfig {
?
    @Bean
    @ConditionalOnMissingBean //不存在該類型的bean,才會將該bean加入IOC容器
    public HeaderParser headerParser(){
        return new HeaderParser();
    }
    
}

執(zhí)行testHeaderParser()測試方法:

SpringBoot在調(diào)用@Bean標識的headerParser()前,IOC容器中是沒有HeaderParser類型的bean,所以HeaderParser對象正常創(chuàng)建,并注冊到IOC容器中。

再次修改@ConditionalOnMissingBean注解:

@Configuration
public class HeaderConfig {
?
    @Bean
    @ConditionalOnMissingBean(name="deptController2")//不存在指定名稱的bean,才會將該bean加入IOC容器
    public HeaderParser headerParser(){
        return new HeaderParser();
    }
}

執(zhí)行testHeaderParser()測試方法:

因為在SpringBoot環(huán)境中不存在名字叫deptController2的bean對象,所以創(chuàng)建HeaderParser對象并注冊到IOC容器中。

再次修改@ConditionalOnMissingBean注解:

@Configuration
public class HeaderConfig {
?
    @Bean
    @ConditionalOnMissingBean(HeaderConfig.class)//不存在指定類型的bean,才會將bean加入IOC容器
    public HeaderParser headerParser(){
        return new HeaderParser();
    }
}
@SpringBootTest
public class AutoConfigurationTests {
    @Autowired
    private ApplicationContext applicationContext;
?
    @Test
    public void testHeaderParser(){
        System.out.println(applicationContext.getBean(HeaderParser.class));
    }
}

執(zhí)行testHeaderParser()測試方法:

因為HeaderConfig類中添加@Configuration注解,而@Configuration注解中包含了@Component,所以SpringBoot啟動時會創(chuàng)建HeaderConfig類對象,并注冊到IOC容器中。

當IOC容器中有HeaderConfig類型的bean存在時,不會把創(chuàng)建HeaderParser對象注冊到IOC容器中。而IOC容器中沒有HeaderParser類型的對象時,通過getBean(HeaderParser.class)方法獲取bean對象時,引發(fā)異常:NoSuchBeanDefinitionException

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 解決Sentinel鏈路模式規(guī)則無效問題

    解決Sentinel鏈路模式規(guī)則無效問題

    本文介紹了如何在Spring Cloud Alibaba項目中使用Sentinel鏈路流控規(guī)則,并解決規(guī)則不生效的問題,通過關(guān)閉Sentinel過濾器,可以避免重復統(tǒng)計請求
    2025-01-01
  • SpringBoot實現(xiàn)優(yōu)雅停機的流程步驟

    SpringBoot實現(xiàn)優(yōu)雅停機的流程步驟

    優(yōu)雅停機(Graceful Shutdown) 是指在服務(wù)器需要關(guān)閉或重啟時,能夠先處理完當前正在進行的請求,然后再停止服務(wù)的操作,本文給大家介紹了SpringBoot實現(xiàn)優(yōu)雅停機的流程步驟,需要的朋友可以參考下
    2024-03-03
  • SpringBoot3安全管理操作方法

    SpringBoot3安全管理操作方法

    這篇文章主要介紹了SpringBoot3安全管理,在實際開發(fā)中,最常用的是登錄驗證和權(quán)限體系兩大功能,在登錄時完成身份的驗證,加載相關(guān)信息和角色權(quán)限,在訪問其他系統(tǒng)資源時,進行權(quán)限的驗證,保護系統(tǒng)的安全,文中有詳細的操作步驟,需要的朋友可以參考下
    2023-08-08
  • Java中的Random()函數(shù)及兩種構(gòu)造方法

    Java中的Random()函數(shù)及兩種構(gòu)造方法

    Java中存在著兩種Random函數(shù)分別是java.lang.Math.Random和java.util.Random,文中給大家介紹了random()的兩種構(gòu)造方法,感興趣的朋友跟隨小編一起看看吧
    2018-11-11
  • SpringBoot項目啟動后立馬自動關(guān)閉的解決方案

    SpringBoot項目啟動后立馬自動關(guān)閉的解決方案

    這篇文章主要介紹了SpringBoot項目啟動后立馬自動關(guān)閉的解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • java使用FileVisitor遍歷文件和目錄

    java使用FileVisitor遍歷文件和目錄

    這篇文章主要為大家詳細介紹了java使用FileVisitor遍歷文件和目錄,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • 基于Redis分布式鎖Redisson及SpringBoot集成Redisson

    基于Redis分布式鎖Redisson及SpringBoot集成Redisson

    這篇文章主要介紹了基于Redis分布式鎖Redisson及SpringBoot集成Redisson,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小小伙伴可以參考一下
    2022-09-09
  • SrpingDruid數(shù)據(jù)源加密數(shù)據(jù)庫密碼的示例代碼

    SrpingDruid數(shù)據(jù)源加密數(shù)據(jù)庫密碼的示例代碼

    本篇文章主要介紹了SrpingDruid數(shù)據(jù)源加密數(shù)據(jù)庫密碼的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • springboot-mybatis/JPA流式查詢的多種實現(xiàn)方式

    springboot-mybatis/JPA流式查詢的多種實現(xiàn)方式

    這篇文章主要介紹了springboot-mybatis/JPA流式查詢,本文給大家分享三種方式,每種方式結(jié)合示例代碼給大家講解的非常詳細,需要的朋友可以參考下
    2022-12-12
  • java動態(tài)代理(jdk與cglib)詳細解析

    java動態(tài)代理(jdk與cglib)詳細解析

    靜態(tài)代理:由程序員創(chuàng)建或特定工具自動生成源代碼,再對其編譯。在程序運行前,代理類的.class文件就已經(jīng)存在了
    2013-09-09

最新評論