目录
3.2、消除歧义性——@Primary和@Qualifier
1、IoC容器简介
Spring IoC容器是一个管理Bean的容器,在Spring的定义中,它要求所有的IoC容器都需要实现接口BeanFactory,它是一个顶级容器接口。
Spring IoC容器允许我们按类型或名称获取Bean。
isSingleton方法判断Bean是否在Spring IoC中为单例。在Spring IoC容器中,默认情况下,Bean都是以单例存在。
2、装配Bean
2.1、通过扫描装配Bean
Spring允许我们进行扫描装配Bean到IoC容器中,对于扫描装配而言使用的注解是@Component和@Component。@Component是标明哪个类被扫描进入Spring IoC容器,而@ComponentScan则是标明采用何种策略去扫描装配Bean。
这里的注解@Component表明这个类将被Spring IoC容器扫描装配,其中的配置“user”则是作为Bean的名称,如果不配置这个字符串,那么IoC容器就会把类名第一个字母作为小写,其他不变作为Bean名称放入到IoC容器中;注解@Value则是指定具体的值,使得Spring IoC给与对应的属性注入对应的值。
这里加入了@ComponentScan,意味着它会进行扫描,但是它只会扫描类AppConfig所在的当前包和其子包,之前把User.java移到包com.springboot.chapter3.config就是这个原因。
2.2、自定义第三方Bean
3、依赖注入
@Autowired,是我们在Spring中常用的注解之一,它会根据属性的类型(by type)找到对应的Bean进行注入。
3.1、注解@Autowired
@Autowired提供这样的规则,首先它会根据类型找到对应的Bean,如果对应类型的Bean不是唯一的,那么它会根据其属性名称和Bean的名称进行匹配。如果匹配的上,就是使用该Bean;如果无法匹配,就会抛出异常。
@Autowired是一个默认必须找到对应Bean的注解,如果不能确定其标注属性一定会存在并且允许这个被标注属性为null,那么可以配置@Autowired属性required为false。
@Autowired(required = false)
它除了可以标注属性外,还可以标注方法。
@Override @Autowired public void setAnimal(Animal animal) { this.animal = animal; }
3.2、消除歧义性——@Primary和@Qualifier
@Primary
... @Component @Primary public class Cat implements Animal { ...... }
注解@Primary,它是一个修改优先权的注解,当Spring IoC容器中有多个同样类型的Bean时,进行依赖注入时会优先选择标注了@Primary的类实例。
@Qualifier
@Autowired @Qualifier("dog") private Animal animal = null;
@Qualifier,它的配置项value需要一个字符串去定义,它将与@Autowired组合在一起,通过类型和名称一起找到Bean。
3.3、带有参数的构造方法类的装配
4、生命周期
Bean的生命周期的过程,它大致分为Bean定义、Bean的初始化、Bean的生存期和Bean的销毁4个部分。Bean定义过程大致如下:
- Spring通过我们的配置,如@ComponentScan定义的扫描路径去找带有@Component的类,这个过程就是一个资源定位的过程。
- 一旦找到了资源,那么它就开始解析,并且将定义的信息保存起来。注意,此时还没有初始化Bean,也就没有Bean的实例,它有的仅仅是Bean的定义。
- 然后就会把Bean定义发布到Spring IoC容器中。此时,IoC容器也只有Bean的定义,还是没有Bean的实例生成。
ComponentScan中还有一个配置项lazyInit,只可以配置Boolean值,且默认值为false,也就是默认不进行延迟初始化,因此在默认情况下会对Bean进行实例化和依赖注入对应的属性值。
有时候Bean的定义可能使用的是第三方的类,此时可以使用注解@Bean来配置自定义初始化和销毁方法,如下所示:
@Bean(initMethod = "init", destroyMethod = "destroy")
5、使用属性文件
在Spring Boot中,我们现在Maven配置文件中加载依赖,如下所示,这样Spring Boot将创建读取属性文件的上下文。
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-configuration-processor --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
这是Spring Boot的默认文件,它会通过其机制读取到上下文中,这样可以引用它了。对于它的引用,有两种方法,首先是用Spring表达式。
有时候我们也可以使用注解@ConfigurationProperties,通过它使得配置上有所减少。
这里在注解@ConfigurationProperties中配置的字符串database,将与POJO的属性名称组成属性的全限定名去配置文件里查找,这样就能将对应的属性读入到POJO当中。
可以自定义xxx.properties属性文件,然后使用@PropertySource去定义的属性文件,把它加载到Spring的上下文中。
6、条件装配Bean
7、Bean的作用域
8、使用@Profile
在Spring中存在两个参数可以提供给我们配置,以修改启动Profile机制,一个是spring.profiles.active,另一个是spring.profiles.default。在这两个属性都没有配置的情况下,Spring将不会启动Profile机制,这就意味着@Profile标注的Bean将不会被Spring装配到IoC容器中。
Spring是先判断是否存在spring.profiles.active配置后,再去查找spring.profiles.default配置的,所以spring.profiles.active的优先级要大于spring.profiles.default。
在Java启动项目中,我们只需要如下配置就能够启动Profile机制:
JAVA_OPTS="-Dspring.profiles.active=dev"
按照Spring Boot的规则,假设把选项-Dspring.profiles.active的配置的值记为{profile},则它会用application-{profile}.properties文件去代替原来默认的application.properties文件,然后启动Spring Boot的程序。
9、引入XML配置Bean
注解@ImportResource,通过它可以引入对应的XML文件,用以加载Bean。有时候有些框架(如Dubbo)是基于Spring的XML方式进行开发的,这个时候需要引入XML的方式来实现配置。
10、使用Spring EL
为了更加灵活,Spring还提供了表达式语言Spring EL。通过Spring EL可以拥有更为强大的运算规则来更好的装配Bean。