基于XML启动的可选方案是基于注解配置,其依靠字节编码的元数据组装组件,替代angle-bracket申明。作为使用XML描述bean的组装的替代,开发者将配置移动到组件类,通过在相关的类,方法,或者字段声明上使用注解。使用BeanPostProcessor结合注解是扩展Spring IoC容器的通用方式。例如,Spring2.0介绍了@Required 注解标识这个属性是必须的。Spring2.5 使得按照相同的方式驱动Spring的依赖注入成为可能。本质上,@Autowired
注解提供了相同的功能,但是更fine-graind控制和更广的应用。Spring2.5也增加了JSR-250的注解支持,比如@PostConstruct和@PreDestroy。Spring 3.0添加了JSR-330注解的支持(Java的依赖注入),其包含在javax.inject包中,比如@Inject和@Named。
注意:注解注入在XML注入前执行,那么后面的配置将覆盖前面的属性包装。
一如既往,你可以以独立的bean定义注册它们,但是了它们也可以在一个基于XML配置的Spring配置中注册(注意Context命名空间的包含物)。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
</beans>
注意:
<context:annotation-config/>
只在同一应用程序上下文(其定义的)中查找bean的注解。意味着,如果你为DispatchServlet将其放在一个WebApplicationContext中,其仅仅检查你的控制器的@Autowired bean,而不是你的services。
4.9.1 @Required
这个注解用在bean属性的setter方法上,如下例子:
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Required
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
这个注解简单地表示这个bean属性必须在配置时设置,通过bean定义的一个明确的属性值或者通过autowiring。如果这个bean属性没有设置,容器抛出异常;这个允许失败,避免空指针异常。也推荐在bean类自身上申明,例如,置入一个init方法。这样做确保当在容器外部使用这个类时那些必须的引用和值已经设置了。
4.9.2 @AutoWired
如你所期望地,你可以应用@AutoWired注解到传统的setter方法上。
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
注意:
JSR-330 @Inject注解能用于替代Spring的@AutoWied注解
你也可以在任意名字的或者多参数的方法上应用这些注解。
public class MovieRecommender {
@Autowired
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
你可以在构造器和字段上应用@AutoWired
public class MovieRecommender {
@Autowired
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
它也可能提供来自ApplicationContext的一个特别的类型的所有的beans,通过添加注解到一个字段或者方法,它们可能是数组类型。
public class MovieRecommender {
@Autowired
private MovieCatalog[] movieCatalogs;
// ...
}
其同样应用于集合类型。
public class MovieRecommender {
private Set<MovieCatalog> movieCatalogs;
@Autowired
public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
// ...
}
甚至是Maps类型可以autowired,只要是key是String类型。Map 值将包含所有bean的类型,并且关键字将包含相关bean的名字
public class MovieRecommender {
private Map<String, MovieCatalog> movieCatalogs;
@Autowired
public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
// ...
}
Spring 2.5 made it possible to follow that same generalapproach to drive Spring's dependency injection(有待重新翻译)
默认地,无论何时没有替补的beans可用,autowiring失败;默认的行为是将注解的方法,构造器和字段标识为Required依赖。这个行为就可以改变。
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired(required=false)
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
注意:
每个类只有一个注解的构造器可以标识为required,但是了更多的非必须的构造器可以被注解。在那种情况下,每一个可以作为候选者并且Spring使用greediest构造器,它的依赖可以满足,那个构造器有最多的参数。
最好使用@Autowired的required属性而不是@Required注解。Required属性表示这个属性对于autowiring的目的不是必须的。如果其不能autowired,就忽略这个属性。在另一方面,@Required,在这方面更强悍,其通过容器支持的任何方式设置这个属性。如果没有值注入,将抛出对应的异常。
你也可以在接口上使用@Autowired,这些接口有:BeanFactory,ApplicationContext,Environment,ResourceLoader,ApplicationEventPublisher,和MessageSource。这些接口和其扩展接口,比如
ConfigurableApplicationContext或者ResourcePatternResolver,自动分解,没有特殊的启动需要。
public class MovieRecommender {
@Autowired
private ApplicationContext context;
public MovieRecommender() {
}
}
注意:
@AutoWired,@Inject,@Resource,和@Value注解由Spring的BeanPostProcessor实现类处理,意味着你不能在你的自己的BeanPostProcessor或者BeanFactoryPostProcessor上使用这些注解。这些类必须借助XML或者Spring的@Bean方法来wire up。
4.9.5 @Resource
Spring也支持在bean属性或者setter方法上使用JSR-250@Resource注解实现注入。这是一个通用模式,在JavaEE5和6中,例如在JSF1.2管理的bean或者JAX-WS2.0版本中。Spring也支持Spring管理的beans。
@Resource 获取一个name属性,并且默认地,Spring以这个值作为要注入的bean名。换句话说,其遵循by-name语义,如下所示:
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Resource(name="myMovieFinder")
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
如果名字没有明确指定,默认名从那个字段名或者方法名中推断出。如果是字段,就获取这个字段名;如果是setter方法,其获取bean的属性名。那么下面的例子将movieFinder注入到它的setter方法中。
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Resource
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
注意:
由注解提供的名字由CommonAnnotationBeanPostProcessor
注意的ApplicationContext分解为一个bean名。这个名字可以通过JNDI分解,如果你明确配置了SimpleJndiBeanFactory。然而,推荐依赖默认的行为并且简单地使用Spring的JNDI查询能力保护间接的级别(the level of indirection)。