使用XML配置的优点是所有的Bean都能一目了然地列出来,并通过配置注入能直观地看到每个Bean的依赖。它的缺点是写起来非常繁琐,每增加一个组件,就必须把新的Bean配置到XML中。

    有没有其他更简单的配置方式呢?

    有!我们可以使用Annotation配置,可以完全不需要XML,让Spring自动扫描Bean并组装它们。

    我们把上一节的示例改造一下,先删除XML配置文件,然后,给和MailService添加几个注解。

    首先,我们给MailService添加一个@Component注解:

    这个@Component注解就相当于定义了一个Bean,它有一个可选的名称,默认是mailService,即小写开头的类名。

    1. @Component
    2. public class UserService {
    3. @Autowired
    4. MailService mailService;
    5. ...
    6. }

    使用@Autowired就相当于把指定类型的Bean注入到指定的字段中。和XML配置相比,@Autowired大幅简化了注入,因为它不但可以写在set()方法上,还可以直接写在字段上,甚至可以写在构造方法中:

    我们一般把@Autowired写在字段上,通常使用package权限的字段,便于测试。

    最后,编写一个AppConfig类启动容器:

    1. @ComponentScan
    2. public static void main(String[] args) {
    3. ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    4. UserService userService = context.getBean(UserService.class);
    5. User user = userService.login("bob@example.com", "password");
    6. System.out.println(user.getName());
    7. }
    8. }

    除了main()方法外,AppConfig标注了@Configuration,表示它是一个配置类,因为我们创建ApplicationContext时:

    使用的实现类是AnnotationConfigApplicationContext,必须传入一个标注了@Configuration的类名。

    此外,AppConfig还标注了@ComponentScan,它告诉容器,自动搜索当前类所在的包以及子包,把所有标注为@Component的Bean自动创建出来,并根据@Autowired进行装配。

    1. spring-ioc-annoconfig
    2. ├── pom.xml
    3. └── main
    4. └── java
    5. └── itranswarp
    6. └── learnjava
    7. ├── AppConfig.java
    8. └── service
    9. ├── MailService.java
    10. ├── User.java
    11. └── UserService.java

    使用Annotation配合自动扫描能大幅简化Spring的配置,我们只需要保证:

    • 每个Bean被标注为@Component并正确使用@Autowired注入;
    • 所有Bean均在指定包以及子包内。

    使用@ComponentScan非常方便,但是,我们也要特别注意包的层次结构。通常来说,启动配置AppConfig位于自定义的顶层包(例如com.itranswarp.learnjava),其他Bean按类别放入子包。

    如果我们想给UserService注入HikariDataSource,但是这个类位于com.zaxxer.hikari包中,并且HikariDataSource也不可能有@Component注解,如何告诉IoC容器创建并配置HikariDataSource?或者换个说法,如何创建并配置一个第三方Bean?

    从下载练习:使用Annotation配置IoC容器 (推荐使用快速下载)

    使用Annotation可以大幅简化配置,每个Bean通过@Component@Autowired注入;

    必须合理设计包的层次结构,才能发挥的威力。