原文地址:http://www.baeldung.com/spring-core-annotations 此篇为译文,由于英语水平有限,可能对原文的理解有误,欢迎指正,不甚感激!
1. 概览
我们可以利用org.springframework.beans.factory.annotation和org.springframework.context.annotation这两个包提供的注解功能使用Spring的依赖注入。
我们经常称它为”Spring core annotations”,我将在本教程对此进行回顾。
2. DI有关的注解
2.1. @Autowired
我们可以使用@Autowired注解标记需要Spring去解析和注入的依赖项。
构造函数注入:
|  |  | 
Setter注入:
|  |  | 
字段注入:
|  |  | 
@Autowired注解有一个布尔类型的名为required的参数,默认值为true。它可以调整Spring在没有找到所需的bean时的行为,当值为true时,会抛出异常,值为false时,则什么都不会发生,只不过在调用“注入”的变量时,可能会得到一个null引用。
Note:如果使用的时构造函数注入,那么所有构造函数的参数都是必须的。
从Spring4.3版本开始,我们可以直接省略@Autowired注解,就可以实现依赖的注入,除非我们声明了两个或以上的构造函数,这时才需要指定一个构造函数用@Autowired修饰。
更多的信息可以阅读我们的其他文章@Autowired和constructor injection
2.2. @Bean
@Bean标记一个实例化Spring bean的工厂方法:
|  |  | 
当需要返回类型的新实例时,Spring会调用这些方法。
返回的bean的name和工厂方法的名称一致,如果想要不同的名称,可以在@Bean注解中传入一个String类型的值,这个值会作为返回的bean的name:
|  |  | 
Note:用@Bean注解标记的所有方法,必须在@Configuration标记的类中。
2.3. @Qualifier
我们使用@Qualifier与@Autowired注解,在一些使用不明确的情况下,提供所需的bean name或者bean id。
举个例子,下面的两个bean实现了同一个接口:
|  |  | 
如果Spring需要注入一个Vehicle bean,但是Vehicle有多个定义(实现),在这个案例中,我们可以使用@Qualifier注解显示的提供一个bean name。
使用构造函数注入:
|  |  | 
使用setter注入:
|  |  | 
或者:
|  |  | 
使用字段注入:
|  |  | 
更多的信息,请阅读这篇文章
2.4. @Required
@Required注解用来在setter方法上标记我们想通过XML填入的依赖:
|  |  | 
|  |  | 
否则,会抛出BeanInitializationException异常。
2.5. @Value
我们可以使用@Value注解将属性值注入到bean中,@Value注解兼容构造函数注入、setter注入、字段注入。
构造函数注入:
|  |  | 
setter注入:
|  |  | 
或者:
|  |  | 
字段注入:
|  |  | 
当然了,注入静态值是没有用的,不过我们可以在@Value中使用“占位字符串”的方式,写入一个外部定义的源数据。例如,在.properties或者.yaml文件。
假设有以下的.properties文件:
|  |  | 
我们可以将engine.fuelType的值注入:
|  |  | 
我们还可以使用@Value的SpEL表达式,关于更多的高级用法,可以阅读我们关于@Value的文章。
2.6. @DependsOn
我们可以使用@DependsOn注解标注Spring在初始化当前(被@DependsOn标记)的bean之前,先初始化其他bean。通常情况下,这个依赖注入的关系是自动完成的,Spring会查找bean之间的显式的依赖关系自动初始化。
我们仅仅需要在初始化隐式依赖关系bean的时候使用@DependsOn注解,例如JDBC驱动加载或者静态变量初始化(静态变量会先于类加载,所以需要提前初始化其他的bean,博主注)。
我们可以使用@DependsOn指定一个当前bean依赖的另一个bean的名字,@DependsOn注解的参数需要一个String类型的数组(或者String字符串):
|  |  | 
另外的,如果我们使用@Bean注解定义一个bean,那么这个工厂方法应该使用@DependsOn注解:
|  |  | 
2.7. @Lazy
我们使用@Lazy注解标记我们想要延迟初始化的bean,默认情况,Spring会在application context startup/bootstrapping时第一时间创建单例bean。然而,有时我们不需要在application startup时创建bean。
@Lazy注解的行为有些不同,取决与我们在什么位置使用它,我们可以在下列情况使用:
- 用在@Bean标记的工厂方法上,会延迟该方法的调用(对应的,工厂方法中的bean也会延迟创建)。
- @Configuration标记的类和@Bean标记的方法都会收到影响。
- 用在@Component标记的类上,如果它不是一个@Configuration类,那么就会被延迟初始化。
- 用在@Autowired标记的构造函数、setter方法或者字段上面,可以延迟加载这个依赖。
@Lazy注解有一个bool类型的参数,默认值为true,这个参数会改变@Lazy注解的行为。
例如,在一个全局设置为懒加载时,第一时间加载;或者配置具体的@Bean工厂方法先于@Configuration类加载:
|  |  | 
更近一步的阅读,请查阅this article。
2.8. @Lookup
用@Lookup注解的方法告诉Spring在我们调用它时返回方法返回类型的一个实例。
更多的信息请查看关于Lookup注解的文章can be found in this article
2.9. @Primary
有时我们需要定义同类型的多个bean,这时Spring的依赖注入时不会成功的,因为Spring并不知道我们需要注入哪一个bean。
我们可能已经知道该问题的解决选项:使用@Qualifier标记所有的连接点,并且指定bean的name。
然而大多数时候我们只需要一个具体的bean,并不需要其他的bean,这时我们可以使用@Primary注解简化这个案例:我们可以用@Primary标注那个最常使用的bean,当注入点没有使用@Qualifier指定注入bean名称时,默认选择这个bean:
|  |  | 
在上面的例子中,Car是被@Primary标记的,因此在Driver类中,Spring会默认注入Car bean。当然了在Biker bean中vehicle变量会赋值一个Bike对象,因为它是被@Qualifier明确指定为bike name的bean。
2.10. @Scope
我们可以使用@Scope注解定义@Component或者Bean的作用域。作用域可以是singleton、prototype、request、session、globalSession中的一个,或者自定义的作用域。
举例:
|  |  | 
3. 上下文配置注解
我们可以使用本节描述的内容来对应用上下文进行配置。
3.1. @Profile
如果我们希望Spring仅在特定配置文件处于活动状态时才使用@Component类或@Bean方法,我们可以用@Profile来标记它,我们可以在@Profile注解的参数中传入配置文件的名称。
|  |  | 
你可以从这篇文章中获取更多关于@Profile的信息。
3.2. @Import
使用@Import注解可以使用具体的@Configuration类而不是使用组件扫描,我们可以提供一个@Configuration类给@Import作为参数:
|  |  | 
博主注:@Import注解其实就是把多个分散的@Configuration配置类给整合到一起,使用的时候用这个一个类就可以了,举个例子:
|  |  | 
3.3. @ImportResource
我们可以使用该注解导入指定的XML配置,可以使用具体的XML文件的本地路径、或者别名作为该注解的参数:
|  |  | 
3.4. @PropertySource
通过这个注解,我们可以为应用程序定义属性文件:
|  |  | 
@PropertySource利用Java 8的repeating annotations功能,这意味着我们可以使用多种手段标记一个类:
|  |  | 
3.5. @PropertySources
我们可以使用这个注解来指定多个@PropertySource配置:
|  |  | 
注意,从Java 8开始,我们可以通过repeating annotations功能实现上述功能。
4. 总结
在本文中,我们看到了最常见的Spring核心注解概述。 我们看到了如何配置bean注入和应用程序上下文,以及如何为组件扫描标记类。这些例子都可以在我们的GitHub上获得。
