SpringBoot 中常见的模式注解有以下五种:
- @Component
- @Service
- @Controller
- @Repository
- @Configuration
前面四种,在目前的 Springboot 版本中并没有明显的区别,都是将组件注入到容器中,只是在如果没有明确的标记是 Controller、Service 或者 Repository的情况下,就使用 Component注解。但是最后的 @Configuration 与上面的注解把组件加入到容器中的方式有所不同,前面四种注解都是 Spring 通过扫描就可以添加到容器中,而 Configuration 是配置类,是需要手工处理;但是如果要一次性将多个组件添加到容器中,则只能使用 @Configuration。那么该注解如何使用呢?如下代码:
- 创建一个 Hero 类,并实现一个 ISkill 接口
public interface ISkill {
void r();
}
public class Hero implements ISkill{
private String name;
private Integer age;
public Hero() {
System.out.println("实例化Hero对象");
}
@Override
public void r() {
System.out.println("Hero...");
}
}
如果我们要讲 Hero 类注入到容器中,直接在类上面打上 @Component 就可以实现,但是如果要使用 @Configuration 实现,则需要先创建一个配置类。
2. 创建一个 HeroConfiguration 配置类
@Configuration
public class HeroConfiguration {
@Bean
public ISkill hero() {
return new Hero();
}
}
配置类上需要有一个 @Configuration 注解,并且方法上需要 @Bean 注解。这种方法看上确实比@Component更复杂,那么它的作用是什么呢?其实在 SpringBoot 中解决变化(即将 new 的动作单独隔离开,尽量使代码保持稳定的状态)的最主要的就是用该注解。举个例子,Hero 类是通过@Configuration 进行注入到容器中,此外还要还有 Hero1 类是使用 @Component 进行注入到容器中,两个类中的成员变量name
和age
哪个能赋值呢?
@Component
public class Hero1 implements ISkill {
private String name;
private Integer age;
public Hero1(String name, Integer age) {
this.name = name;
this.age = age;
}
public Hero1() {
System.out.println("实例化Hero1对象");
}
@Override
public void r() {
System.out.println("Hero1......");
}
}
由于使用 @Component 注解所有的操作都是 IoC容器进行创建对象,所以根本没有办法去为变量赋值,但是使用@Configuration是可以的
public class Hero implements ISkill{
private String name;
private Integer age;
public Hero(String name, Integer age) {
this.name = name;
this.age = age;
}
public Hero() {
System.out.println("实例化Hero对象");
}
@Override
public void r() {
System.out.println("Hero...");
}
}
@Configuration
public class HeroConfiguration {
@Bean
public ISkill hero() {
return new Hero("gabriel", 18);
}
}
当然上面的实例只是一个很表象的说明,@Configuration 注解真正的作用其实是用来替换 Bean 的 xml 配置的,在 Spring 时代中的 xml 配置:
<bean id="benzCar" class="spring.impl.BenzCar"></bean>
<bean id="qqCar" class="spring.impl.QQCar"></bean>
<bean id="man" class="spring.impl.Man">
<property name="car" ref="benzCar"></property>
</bean>
在 HeroConfiguration 类上注解 @Configuration 就是用来代替配置文件中的<beans>, @Bean 就是用来代替 <bean>。那么为什么 Spring 会这么偏爱配置?本质上还是为遵循 OCP 原则,将变化隔离到配置文件中,也就是如果有变化的话,去修改配置文件而不是去修改代码。配置类其实类似一种配置文件,那为什么要隔离到配置文件中呢?
- 配置文件集中性
- 配置文件清晰(没有业务逻辑)