Springboot依賴注入筆記

結合Autowired和Service註解

public interface IUser {
    void say();
}

@Service
public class Student implements IUser {

    @Override
    public void say() {
        System.out.println("I'm a student");
    }
}

@Component
@Order(value = 3)
public class Entry implements CommandLineRunner {
    public Log log = LogFactory.getLog(Entry.class);

    @Autowired
    IUser user;

    @Override
    public void run(String... args) throws Exception {
        user.say();
    }
}

 

如果要在構造函數中就需要訪問注入的變量,那麼Autowired的位置就要放到構造函數上

@Component
@Order(value = 3)
public class TestService {
    private final IUser user;

    @Autowired
    public void TestService (IUser user) {
        user.say();
    }
}

 

自定義注入的掃描範圍

要注意Springboot掃描包的時候默認是從啓動類(一般是Application)目錄開始往下掃描,也就意味着如果Bean不在Application目錄的下層,是不會被掃描到的。

這種情況會提示:

Description:
Field xxx in xxxxxx required a bean of type 'xxxxxx' that could not be found.

Action:
Consider defining a bean of type 'xxxxxxxxxxxxxx' in your configuration.

 

不過這也不是無法改變的,我們手動指定掃描範圍即可:

@SpringBootApplication
@ComponentScan(basePackages={"springbootdemo.basic","anotherspringbootdemo.basic"})
public class Application {

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

範圍列表中不要忘記添加原來的目錄,及啓動類的包範圍。

另外,這個ComponentScan不是必須放到啓動類上,只要可以被掃描到即可。

 

通過Configuration的方式

通過Configuration也可以實現“跨域”的注入方式(即package不在一個範圍內)

/**
* Springboot會掃描標有Configuration註解的類
* 該類中標有Bean註解的方法,返回值會被作爲被注入項
* 至於這個Bean的注入項,在方法裏面return就是。
*/
@Configuration
public class TestConfig{
    
    @Bean
    public IUser user(){
        return new Teacher();
    }

    //有依賴關係的Bean也很簡單
    //這個IDepartment依賴IUser
    @Bean
    public IDepartment(){
        return new Development(user());
    } 
}

/*調用*/
public class TestClass{

    @Autowired
    IUser user;
    
    public void run(String... args) throws Exception {
        user.say();
    }
}

 

上面的Configuration雖然解決了“跨域”注入,但Configuration註解還是要求放到調用的項目中。

很多時候當我們需要依賴一個第三方jar包,並想要實現自動注入的時候,我們並不想再去手動寫Configuration,畢竟如果多個地方引用這個jar包,每一處都需要這樣處理。

能不能一勞永逸呢?

使用Springboot中的框架時,例如使用ES,我們發現雖然並沒有聲明ElasticSearchTemplate,但是卻可以直接使用

這裏有一篇不錯的講解 https://www.jianshu.com/p/346cac67bfcc

假設第三方項目是ProjectA,應用方是ProjectB

 現在ProjectA有 類TestTemplate

package ProjectA;

public class TestTemplate{

    public void test() {
        System.out.println("GO TEST");
    }
}

 

ProjectB需要注入並使用TestTemplate,當然肯定要先添加maven的依賴(忽略),調用邏輯

package ProjectB;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import springbootdemo.common.TestTemplate;

@Component
public class Entry implements CommandLineRunner {
    
    @Autowired
    private TestTemplate aa;

    @Override
    public void run(String... args) throws Exception {
        aa.test();
    }
}

 

這時候運行ProjectB的話肯定是會報錯的,因爲找不到TestTemplate的注入結果,即使在TestTemplate上添加註解也是一樣。

我們直接給出一個簡單的解決方案

①在ProjectA中新建一個自動配置類 TestAutoConfiguration

package ProjectA;

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TestAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public TestTemplate testTemplate(){
        return new TestTemplate();
    }
}

 

②在ProjectA的資源目錄src/main/resources下創建目錄META-INF/spring.factories

 

內容:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
ProjectA.TestAutoConfiguration

現在再執行,一切OK!

 

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