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