首頁 > 軟體

SpringBoot2底層註解@Configuration設定類詳解

2022-05-28 14:00:06

SpringBoot2底層註解@Configuration設定類

一、設定類

@Configuration這個註解作用就是告訴 springboot 這是一個設定類。

這個設定已經不陌生了,在之前 spring 相關的使用全註解方式時,就使用到了設定類。

在設定類裡,可以使用@Bean標記在方法上,給容器註冊元件,預設也是單範例的。

@Configuration //告訴SpringBoot這是一個設定類 == 組態檔
public class MyConfig {
    @Bean("user1") //給容器中新增元件。以方法名作為元件的id。返回型別就是元件型別。返回的值,就是元件在容器中的範例
    public User user01(){
        return new User("pingguo", 20);
    }
    @Bean("pet1")
    public Pet tomcatPet(){
        return new Pet("tomcat");
    }
}

主執行類還是之前範例中的,列印出所有元件的名稱。

可以看到,有上面註冊的 2 個元件:user1、pet1。

二、設定類本身也是元件

在主執行類的 main 方法裡,加一個獲取設定類的輸出:

@SpringBootApplication(scanBasePackages = "com.pingguo")
public class MainApplication {
    public static void main(String[] args) {
        // 返回IOC容器
        final ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
        // 檢視容器裡的元件
        final String[] beanDefinitionNames = run.getBeanDefinitionNames();
        for (String name: beanDefinitionNames) {
            System.out.println(name);
        }
        // 從容器中獲取元件
        MyConfig bean = run.getBean(MyConfig.class);
        System.out.println("設定類也是元件:" + bean);
    }
}

執行 main 方法,

可以看到最後一個輸出,說明設定類本身也是個元件。

三、proxyBeanMethods 屬性

從springboot2.0之後,@Configuration 中多了一個屬性 proxyBeanMethods,用來代理 bean 的。

預設值是true,也就是說該設定類會被代理(CGLIB),在同一個組態檔中呼叫其它被@Bean註解標註的方法獲取物件時,springboot 總會檢查容器中是否存在這個元件。

如果容器中存在,直接取。不存在的話,才會去建立,保證單範例。

現在看下false的情況。

@Configuration(proxyBeanMethods = false) //改成 false
public class MyConfig {
    @Bean("user1") //給容器中新增元件。以方法名作為元件的id。返回型別就是元件型別。返回的值,就是元件在容器中的範例
    public User user01(){
        return new User("pingguo", 20);
    }
    @Bean("pet1")
    public Pet tomcatPet(){
        return new Pet("tomcat");
    }
}

在主執行程式裡多從呼叫方法獲取物件,判斷一下物件是否相等。

@SpringBootApplication(scanBasePackages = "com.pingguo")
public class MainApplication {
    public static void main(String[] args) {
        // 返回IOC容器
        final ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
        // 檢視容器裡的元件
        final String[] beanDefinitionNames = run.getBeanDefinitionNames();
        for (String name: beanDefinitionNames) {
            System.out.println(name);
        }
        // 從容器中獲取元件
        MyConfig bean = run.getBean(MyConfig.class);
        System.out.println("設定類也是元件:" + bean);
        User user1 = bean.user01();
        User user2 = bean.user01();
        System.out.println(user1 == user2);
    }
}

看最後的輸出,會是 false。

這裡引出 2 個名詞:Full 全模式,Lite 輕量級模式。

  • Full (proxyBeanMethods = true) : 該模式下注入容器中的同一個元件無論被取出多少次都是同一個bean範例,即單範例物件,
  • 在該模式下 SpringBoot 每次啟動都會判斷檢查容器中是否存在該元件。
  • Lite (proxyBeanMethods = false): 該模式下注入容器中的同一個元件無論被取出多少次都是不同的bean範例,即多範例物件,

在該模式下 SpringBoot 每次啟動會跳過檢查容器中是否存在該元件。

那麼這個是用來解決什麼場景的問題呢?答案:元件依賴。

有元件依賴的場景

看下2個實體類:User、Pet。

public class User {
    private String name;
    private Integer age;
    private Pet pet;
... ...

固定程式碼部分:有參構造、無參構造、get和set方法、toString方法,就省去了。

public class Pet {
    private String name;
... ...

修改下設定類裡的方法:

@Configuration(proxyBeanMethods = true)
public class MyConfig {
    @Bean("user1") 
    public User user01(){
        User pingguo = new User("pingguo",20);
        pingguo.setPet(tomcatPet());
        return pingguo;
    }
    @Bean("pet1")
    public Pet tomcatPet(){
        return new Pet("tomcat");
    }
}

到main方法測試一下:

// 依賴關係
    User user01 = run.getBean("user1", User.class);
    Pet pet1 = run.getBean("pet1", Pet.class);
    System.out.println("依賴:" + (user01.getPet() == pet1));

這裡就是判斷當proxyBeanMethods = true的情況下,User物件的 pet,是不是容器中的 pet。

如果是,那麼結果就是true。

此時再將proxyBeanMethods = false,重新執行一下,結果會是 false:

那麼這 2 個模式分別在什麼時候用呢?

當在你的同一個Configuration設定類中,注入到容器中的 bean 範例之間有依賴關係時,建議使用 Full 全模式。

當在你的同一個Configuration設定類中,注入到容器中的 bean 範例之間沒有依賴關係時,建議使用 Lite 輕量級模式,以提高 springboot 的啟動速度和效能。

以上就是SpringBoot2底層註解@Configuration設定類詳解的詳細內容,更多關於SpringBoot2註解@Configuration的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com