SpringBoot 之 IOC

1、IoC的作用

IoC(控制反轉),主要的作用就是降低代碼之間的耦合程度。

2、Bean的裝配

使用Spring boot生成對象需要幾個步驟:
1、爲需要生成對象的類打上@Component的註解標記,這些類會被放到IoC容器中。Component註解有一個Value屬性,指定這個類用於被檢索的名字,如果不指定,默認是把類名的首字母小寫其餘不變作爲檢索名。在這些類的屬性上打上@Value註解可以爲屬性賦值。
2、定義一個配置文件類,加上@Configuration註解,這個類用於掃描IoC容器,找到需要裝配的Bean。如果希望自動裝配,不需要再配置文件中用@Bean手動配置,則在配置文件類中打上@ComponentScan註解標記。
3、測試裝配,實例化一個ApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class),傳入配置文件,利用ctx中的getBean方法得到裝配好的對象。

代碼樣例:

1、放入IoC容器的類:

package com.xiayto.springbootlearn.chapter3.aclazz;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component(value = "player")
public class Player {

    @Value("xiayto")
    private String name;

    @Value("100")
    private Double hp;

    public String getName() {
        return name;
    }

    public Double getHp() {
        return hp;
    }

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

    public void setHp(Double hp) {
        this.hp = hp;
    }
}

這裏要注意,屬性要加上getter和setter的方法,才能裝配成功。

2、配置文件類:

package com.xiayto.springbootlearn.chapter3.aconfig;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = "com.xiayto.springbootlearn.chapter3.aclazz")
public class Config {
}

這裏的basePackages,可以指定掃描的路徑,只會掃描路徑下標記了@Component的類

3、測試:

package com.xiayto.springbootlearn.chapter3.atest;

import com.xiayto.springbootlearn.chapter3.aclazz.Player;
import com.xiayto.springbootlearn.chapter3.aconfig.Config;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class IoCTest {

    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
        Player player = ctx.getBean(Player.class);
        System.out.println(player.getName());
        System.out.println(player.getHp());
    }
}

3、自定義第三方Bean

想把第三方的包裏面的類放到IoC容器裏面,這時可以在配置類中,寫生成類對象的方法,然後用@Bean註解標註。

代碼例子:
首先引入第三方的包:

<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-dbcp2</artifactId>
</dependency>
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
</dependency>

然後在配置文件中寫生成方法,並加上Bean的註解:

package com.xiayto.springbootlearn.chapter3.aconfig;

import org.apache.commons.dbcp2.BasicDataSourceFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.util.Properties;


@Configuration
@ComponentScan(basePackages = "com.xiayto.springbootlearn.chapter3.aclazz")
public class Config {

    @Bean(name = "dataSource")
    public DataSource getDataSource(){
        Properties pros = new Properties();
        pros.setProperty("driver", "com.mysql.jdbc.Driver");
        pros.setProperty("url", "jdbc:mysql://localhost:3306/chapter3");
        pros.setProperty("username", "root");
        pros.setProperty("password", "123456");
        DataSource dataSource = null;
        try {
            dataSource = BasicDataSourceFactory.createDataSource(pros);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dataSource;
    }
}

4、依賴注入

IoC除了可以生成實例對象,還可以解決IoC容器中,Bean之間的依賴問題,具體的做法是:
1、打上@Autowrited註解,實現Bean中的屬性的自動注入
2、同樣的,所有用於注入的類(包括被注入的類)打上@Component放入IoC容器中,容器自動掃描尋找注入的Bean。
3、尋找注入的過程如果出現多個Bean滿足注入條件,用@Primary@Qualifier,其中@Primary註解用於提升優先級,當多個Bean滿足注入條件優先選擇@Primary標註的Bean,而@Qualifier用於指定注入的Bean。

代碼例子:
這是一個動物服務人的例子,讓動物自動裝配到人的對象中:

package com.xiayto.springbootlearn.chapter3.dependencyInjection.IoCContainerClass;

import com.xiayto.springbootlearn.chapter3.dependencyInjection.Animal;
import com.xiayto.springbootlearn.chapter3.dependencyInjection.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class NormalMan implements Person {

    @Autowired
    private Animal animal = null;

    @Override
    public void service() {
        this.animal.use();
    }

    @Override
    public void setAnimal(Animal animal) {
        this.animal = animal;
    }
}

其中實現接口只是爲了加快書寫速度,需要自動注入對象的屬性前加上@Autowrited的註解。

寫動物類:

package com.xiayto.springbootlearn.chapter3.dependencyInjection.IoCContainerClass;

import com.xiayto.springbootlearn.chapter3.dependencyInjection.Animal;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

@Component
@Primary
public class Dog implements Animal {
    @Override
    public void use() {
        System.out.println("狗用於看門口");
    }
}

狗這個動物就會裝配到ManLikeCat的實例對象中,這裏假設一般人都喜歡狗,狗打上了@Primary的註解,優先裝配狗。如果存在多種動物,我想裝備別的動物,就需要用到@Qualifier這個註解:

package com.xiayto.springbootlearn.chapter3.dependencyInjection.IoCContainerClass;

import com.xiayto.springbootlearn.chapter3.dependencyInjection.Animal;
import com.xiayto.springbootlearn.chapter3.dependencyInjection.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class ManLikeCat implements Person {

    private Animal animal = null;

    @Override
    public void service() {
        this.animal.use();
    }

    @Override
    @Autowired
    @Qualifier("cat")
    public void setAnimal(Animal animal) {
        this.animal = animal;
    }
}

在另一個人的屬性上,使用@Qualifier指定需要裝配的Bean,@Autowired註解不僅可以用在屬性上,也可以用在設置屬性的方法上。

5、屬性文件注入

Pom文件中加入

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
 </dependency>

系統會自動從application.properties讀取屬性值,例如可以在application.properties設定server.port=8097。

如果要自己設定屬性文件:
1、新建一個<屬性文件名>.properties,寫上屬性值
2、在配置文件中加入屬性文件地址@PropertySource("classpath:<屬性文件名>.properties")
3、在Bean的屬性上,利用 @Value("${database.username}")注入屬性

代碼例子:
1、新建屬性文件,jdbc.properties:

database.username=root2
database.password=1234567

2、配置文件中加入屬性文件地址

package com.xiayto.springbootlearn.chapter3.aconfig;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
@ComponentScan(basePackages = "com.xiayto.springbootlearn.chapter3.*")
@PropertySource("classpath:jdbc.properties")
public class Config {
}

3、在Component上利用Value註解設置屬性

package com.xiayto.springbootlearn.chapter3.propertiesTest;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class PropertiesTest {

    @Value("${database.username}")
    private String username = null;

    @Value("${database.password}")
    private String password = null;

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    @Value("${database.username}")
    public void setUsername(String username) {
        this.username = username;
    }

    @Value("${database.password}")
    public void setPassword(String password) {
        this.password = password;
    }
}

4、測試:

package com.xiayto.springbootlearn.chapter3.propertiesTest;


import com.xiayto.springbootlearn.chapter3.aconfig.Config;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class IoCPropertiesTest {

    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
        PropertiesTest pt = ctx.getBean(PropertiesTest.class);
        System.out.println(pt.getUsername());
        System.out.println(pt.getPassword());
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章