SpringBoot 中常见的模式注解有以下五种:

  • @Component
  • @Service
  • @Controller
  • @Repository
  • @Configuration
    前面四种,在目前的 Springboot 版本中并没有明显的区别,都是将组件注入到容器中,只是在如果没有明确的标记是 Controller、Service 或者 Repository的情况下,就使用 Component注解。但是最后的 @Configuration 与上面的注解把组件加入到容器中的方式有所不同,前面四种注解都是 Spring 通过扫描就可以添加到容器中,而 Configuration 是配置类,是需要手工处理;但是如果要一次性将多个组件添加到容器中,则只能使用 @Configuration。那么该注解如何使用呢?如下代码:
  1. 创建一个 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 进行注入到容器中,两个类中的成员变量nameage哪个能赋值呢?

@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 原则,将变化隔离到配置文件中,也就是如果有变化的话,去修改配置文件而不是去修改代码。配置类其实类似一种配置文件,那为什么要隔离到配置文件中呢?

  1. 配置文件集中性
  2. 配置文件清晰(没有业务逻辑)