細說Spring——IoC詳解(自動裝配和加載外部配置文件)

一、自動裝配

使用過Spring框架的都應該很經常的使用一個注解就就是@Autowired,我們可以通過使用該注解為一個容器中的類自動裝配需要的依賴,現在我們就來復習一下怎么使用@Autowired注解為來自動裝配依賴吧。
BookController

@Controller
public class BookController {
    @Autowired
    private BookService bookService;
}

BookService


@Service
public class BookService {

    @Qualifier("bookDao")
    @Autowired
    private BookDao bookDao2;

    public void print() {
        System.out.println(bookDao2);
    }

    @Override
    public String toString() {
        return "BookService{" +
            "bookDao=" + bookDao2 +
            '}';
    }
}

BookDao

@Repository
public class BookDao {
    private String lable = "1";

    public String getLable() {
        return lable;
    }

    public void setLable(String lable) {
        this.lable = lable;
    }

    @Override
    public String toString() {
        return "BookDao{" +
            "lable='" + lable + '\'' +
            '}';
    }
}

我們可以看到controller中裝配了service,service中裝配了dao,現在看一下配置類:

@Configuration
@ComponentScan({"com.jiayifan.dao", "com.jiayifan.service", "com.jiayifan.bean"})
public class MainConfigOfAutowired {
}

然后是測試類:

public class IOCTest_Autowired {

    @Test
    public void test01() {
        //1、創建IOC容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowired.class);
        BookService bookService = applicationContext.getBean(BookService.class);

        System.out.println(bookService);

    }
}

測試結果:


這里寫圖片描述

上面就是@Autowired注解的最基礎的用法,可是大家可以考慮一下@Autowired是按照什么樣的規則來幫我們的組件裝配依賴的嗎,我們今天主要就來學習一下怎么控制@Autowired幫我們裝配依賴。
首先我們需要知道@Autowired標注的依賴,Spring會先去容器中按照類型進行匹配,如果只找到一個,那么就把找到的組件注入到當前的目標組件中,如果沒有找到的話就會報錯,我們可以通過@Autowired(required = false)required屬性的值設置為false來消除這種錯誤,因為@Autowired注解默認當前的依賴是必須的。如果再容器中找到了兩個同樣類型的組件,那么Spring會如何選擇呢,難道是剪刀石頭布嗎?
當然不是,Spring會按照在目標組件中依賴組件的屬性名作為依賴組件的名字來選擇,比如我們在service中依賴的dao屬性名為private BookDao bookDao;,所以Spring就會把名字為bookDao的組件注入service,我們當然也可以自己制定這種選擇的規則,下面我們就來看一下如何實現吧:
首先配置類:

@Configuration
@ComponentScan({"com.jiayifan.dao", "com.jiayifan.service", "com.jiayifan.bean"})
public class MainConfigOfAutowired {

    @Bean("bookDao2")
    public BookDao bookDao() {

        BookDao bookDao = new BookDao();
        bookDao.setLable("2");
        return bookDao;
    }

}

我們可以發現我們即使用了包掃描,又在配置類中使用@Bean注解添加了一個dao組件,現在容器中有兩個dao組件,一個名字是bookDao,另一個名字是bookDao2,而servcie中的屬性名為bookDao,現在我們就像使用bookDao2,我們就可以通過在service中使用@Qualifier("bookDao2")注解來指定我們想要那個組件當做依賴:

@Service
public class BookService {

    @Qualifier("bookDao2")
    @Autowired()
    private BookDao bookDao;

    public void print() {
        System.out.println(bookDao);
    }

    @Override
    public String toString() {
        return "BookService{" +
            "bookDao=" + bookDao +
            '}';
    }
}

測試一下:

這里寫圖片描述

我們看到兩個不同的dao中的lable屬性是不同的,現在service中的daoi是bookDao2
我們同樣可以使用一個@Primary注解來選擇首要的組件:

@Configuration
@ComponentScan({"com.jiayifan.dao", "com.jiayifan.service", "com.jiayifan.bean"})
public class MainConfigOfAutowired {

    @Primary
    @Bean("bookDao2")
    public BookDao bookDao() {

        BookDao bookDao = new BookDao();
        bookDao.setLable("2");
        return bookDao;
    }

}

@Qualifier("bookDao2")注解的優先級是比@Primary要高的。

通過上面的學習我們已經了解了在容器中有多個同類型組件的情況下怎么自己選擇需要的依賴,其實感覺并不是很有用,因為感覺還是容器中只有一個組件的情況比較多。
我們通常會把@Autowired注解標注到屬性上面,其實@Autowired還可以標注到其他的地方,我們來看一下:

  • 通過將@Autowired標注到set方法上,可以實現自動裝填
  • 通過將@Autowired標注到相應的有參構造器上,可以實現自動裝填,如果相應組件只有一個有參構造器,注解可以省略
  • 通過將@Autowired標注到set方法和有參構造器的參數上,可以實現自動裝填

二、加載外部配置文件

我們在使用Spring的過程中難免要使用到外部的配置文件,比如我們經常講數據庫的連接參數放到properties文件中,我們現在就來學習一下怎么使用注解加載外部配置文件,然后獲取外部配置文件中的值吧,首先我們的配置類:

@PropertySource(value = {"classpath:person.properties"})
@Configuration
public class MainConfigOfPropertyValue {

    @Bean
    public Person person() {
        return new Person();
    }
}

我們使用了@PropertySource(value = {"classpath:person.properties"})注解來加載外部的配置文件,然后我們看一下如何調用配置文件中的值,我們這里有一個組件類:

public class Person {

    //使用@Value賦值
    //1、基本數值  2、SpEL #{}  3、可以寫${},取出配置文件(properties配置文件)中的值   
    @Value("張三")
    private String name;

    @Value("#{20 - 2}")
    private Integer age;

    @Value("${person.nickName}")
    private String nickName;

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    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;
    }

    @Override
    public String toString() {
        return "Person{" +
            "name='" + name + '\'' +
            ", age=" + age +
            ", nickName='" + nickName + '\'' +
            '}';
    }
}

我們使用@Value注解來調用配置文件中的值。
測試類:

public class IOCTest_PropertyValue {

    @Test
    public void test01() {
        //1、創建IOC容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfPropertyValue.class);
        printBeans();
        System.out.println("====================");
        Person person = (Person) applicationContext.getBean("person");
        System.out.println(person);
    }

    private void printBeans() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for(String name : beanDefinitionNames) {
            System.out.println(name);
        }
    }
}

測試結果:


這里寫圖片描述
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,869評論 18 139
  • 1.1 spring IoC容器和beans的簡介 Spring 框架的最核心基礎的功能是IoC(控制反轉)容器,...
    simoscode閱讀 6,749評論 2 22
  • Spring Boot 參考指南 介紹 轉載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,941評論 6 342
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong閱讀 22,522評論 1 92
  • 類數組對象,對應于傳遞給函數的參數。function(x,y,z){var x = arguments[0];va...
    Menoen閱讀 130評論 0 0