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