注解方式和xml方式均可配置spring,注解方式比xml方式先解析,它们满足覆盖原则,因此,对于相同的配置部分,xml方式会覆盖注解方式
使用注解,首先要在xml配置中声明对注解进行处理的类,我们可以用bean定义来声明它们,也可以使用下列方式一次声明所有注解:
声明的注解处理类包括:AutowiredAnnotationBeanPostProcessor, CommonAnnotationBeanPostProcessor, PersistenceAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor。
@Required:应用在setter方法下,表示该属性不允许为空,如果为空,容器将会抛出异常
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Required
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
@Autowired注解在之前的自动装配章节已经介绍,不在赘述
@Primary:当有多个bean满足匹配结果时,具有@Primary注解的bean将被使用,看一个例子:
@Configuration
public class MovieConfiguration {
@Bean
@Primary
public MovieCatalog firstMovieCatalog() { ... }
@Bean
public MovieCatalog secondMovieCatalog() { ... }
// ...
}
public class MovieRecommender {
@Autowired
private MovieCatalog movieCatalog;
// ...
}
根据类型进行匹配,此时有多个匹配结果,MovieRecommender将选择有@Primary注解的firstMovieCatalog,如果使用xml,可以利用
@Qualifier:与@Primary不同,@Qualifier的使用更加灵活,通过指定bean的标识符,@Qualifier在有多种匹配结果的情况下,会通过bean的名字进行优先匹配:
public class MovieRecommender {
@Autowired
@Qualifier("main")
private MovieCatalog movieCatalog;
// ...
}
当有多种匹配结果时,将优先选择标识符为main的bean,@Qualifier也可用于函数参数:
public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(@Qualifier("main")MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
在xml中使用qualifier标签表明标识符:
@Qualifier也可用于collections,所有标识符相同的bean将被注入,例如Set
Spring的CommonAnnotationBeanPostProcessor也可以识别JSR250的注解,但是这些注解不包括在Spring包内,在Maven项目中,需要自己添加相应依赖
@Resource:与使用类型匹配的@Autowired不同,@Resource使用名字匹配,@Resource只能用于属性和setter方法上(
@Resource和@Autowired的区别:两者的运行机制不一样,@Resource根据bean的名称直接匹配进行依赖注入,@Autowired先根据类型匹配确定范围,然后根据@qualify配置的标识符或是@primary在范围内进行选择,@Resource只能用于属性、只有一个参数的setter方法,@Autowired允许自我引用(即自己注入自己),当根据类型有多种匹配结果时,自我引用的优先级最低,@Resource根据名称也可能获得bean自己的引用,但是是代理
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Resource(name="myMovieFinder")
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
名为myMovieFinder的Bean将注入
如果我们没有指定name值,那么将会使用默认值,用在属性上,将用属性名进行匹配,用在setter方法上,将用bean的属性的名字进行匹配:
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Resource
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
名为movieFinder的bean将匹配
CommonAnnotationBeanPostProcessor将name的值解析为bean的名称,@Resource注解允许注解BeanFactory、ApplicationContext、ResourceLoader、ApplicationEventPublisher、MessageSource接口
public class MovieRecommender {
@Resource
private CustomerPreferenceDao customerPreferenceDao;
@Resource
private ApplicationContext context;
public MovieRecommender() {
}
// ...
}
上述代码中,首先查找名为customerPreferenceDao的bean,接着进行类型匹配,注入类型为CustomerPreferenceDao的Bean
@PostConstruct:在初始化前先先调用该方法
@PreDestroy:在销毁对象前先调用该方法
public class CachingMovieLister {
@PostConstruct
public void populateMovieCache() {
// populates the movie cache upon initialization...
}
@PreDestroy
public void clearMovieCache() {
// clears the movie cache upon destruction...
}
}