你知道springboot的自動裝載機制嗎?一篇文章讓你豁然開朗!!!

之前學完ssm的時候,當時做了一個簡單的小網站,非常開心,但是對於那些配置文件剛開始還是有些頭疼。後來學習到springboot,就感覺太清爽了!!!去nmd配置文件,我們只需要在application.properties配置一些mybatis、數據源、端口、視圖解析器等就可以了。開發一個小網站很快就完成了。

不知道大家第一次接觸springboot是什麼感覺,我第一感覺就是不用配置那麼多配置文件了。但是真的不用配置了嗎?爲什麼不需要我們配置了呢?大家想過這個問題嗎?這裏有一個叫做springboot自動裝載機制

1、讓我們來認識兩個接口

public interface ImportSelector {
    String[] selectImports(AnnotationMetadata var1);
}

這個接口對於自動裝載有着至關重要的位置!!!

ImportSelector接口是Spring導入外部配置的核心接口,在SpringBoot的自動化配置和@EnableXXX(功能性註解)中起到了決定性的作用。當在@Configuration標註的Class上使用@Import引入了一個ImportSelector實現類後,會把實現類中返回的Class名稱都定義爲bean。
 
public interface DeferredImportSelector extends ImportSelector {
 //...省略
}

DeferredImportSelector接口繼承ImportSelector,他和ImportSelector的區別在於裝載bean的時機上,DeferredImportSelector需要等所有的@Configuration都執行完畢後纔會進行裝載。

大家看完是不是一臉懵B?這說的是啥?人話?先帶着這些個問題,我們來看一個demo。

2、自己寫一個配置讓springboot加載,不使用@Configuration註解

我們的目標是用配置類,注入一個IOC對象。

先看一個實體


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.RequiredArgsConstructor;

@AllArgsConstructor
@Data
public class User {
    private String username;
    private Integer age;
}

定義一個配置類


import org.springframework.context.annotation.Bean;


public class UserConfiguration {

    @Bean
    public User getUser() {
        return new User("張三",18);
    }
}

看着啊,劃重點了!!!這裏的配置類沒有@Configuration註解吧,要是加上咱們還玩啥呀,對吧!!這裏如果能夠被springboot加載,那麼就能夠注入一個ioc對吧。這是我們最後驗證是否成功的重要標誌!!!

大佬要上線了!



import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

public class UserImportSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{UserConfiguration.class.getName()};
    }
}

看這個大佬的方法,new String[]{UserConfiguration.class.getName()。對應着我們上面配置類的名字。我們只需要把配置類的名字放到字符串數組裏就可以自動加載了。當然我們還需要一個@Import註解來幫助我們與Springboot建立連接!!

package com.springcloud.demo;

import org.springframework.context.annotation.Import;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target(ElementType.TYPE)
@Import(UserImportSelector.class)
public @interface EnableUserBean {
}
package com.springcloud.demo;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

@EnableUserBean
public class TestApplication {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new
                AnnotationConfigApplicationContext(TestApplication.class);
        User user = applicationContext.getBean(User.class);
        System.out.println(user);
    }
}

我們只需要在啓動的java程序的時候(可以是main方法)加上這個註解,我們的springboot就會去註解裏找@Import(UserImportSelector.class),找到UserImportSelector,通過它找到我們的配置類,然後就可以加載配置類了。就是這麼一個流程!!!

3、這個是怎麼加載的呢?

我們在這打一個斷點就能夠看到取到了,他首先會遞歸的獲取我們自定義導入的配置類的信息。

這裏麪包含了,你是哪個註解。註解在哪個類上的。

如果不是ImportSelector呢?

就當作@Configuration註解的配置類加載處理。

我們打斷點來看:

首先這裏的是ImportSelector

 之後是拿出來的configuration。

4、讓我們一起分析springboot自動加載自己的配置文件

先瞅一眼啓動類

點進去

再點!!

這個跟我們上面做的demo是不是一樣的了?又是熟悉的味道,又是熟悉的你!!!

再點!!!!

進入AutoConfigurationImportSelector的類。然後往下滑。

woc,這是什麼東西?熟悉吧,上面我們自定義的也有這個方法吧!!之後的加載是不是就和給大家截屏分析源代碼那塊串起來了?

但是現在是不是還有一個問題,就是怎麼獲得springboot自己配置的那些再jar裏面的配置類?

重點看一下這個代碼:

重點在於這個FACTORIES_RESOURCE_LOCATION。我們來看一下它的值

說白了就是在"META-INF/spring.factories"下面得到資源是不是?我們找到一個springboot的jar包看一下這裏面的文件!!一定是要有這個註解(EnableAutoConfiguration)的!!這個需要注意!

我們可以看到這個文件裏有配置的信息,key是我們的註解,value就是對應要加載的配置類。這樣就找到了對應的配置類。

 

至此,springboot自動裝載就整個打通了!!!

源碼:[email protected]:Zesystem/springclouddemoerueka.git

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章