基于注解的容器配置
首先使用注解和xml配置,本质上没有好坏之分,只有适合不适合之分。如果你觉得哪个顺手就用哪个,或者都用。
首先要使用anotation-config 需要在xml中配置
<context:annotation-config/>:该句自动的注册AutowiredAnnotationBeanPostProcessor, CommonAnnotationBeanPostProcessor, PersistenceAnnotationBeanPostProcessor, RequiredAnnotationBeanPostProcessor处理器。
当然如果直接配置了
<context:component-scan base-package="com.javaconfig.domain"/> 那么也就是默认配置了<context:annotation-config/>,所以只需要定义这个,没必要定义上面的那个。
@Required
注解适用于bean属性的setter方法并且它指示,受影响的bean属性必须在配置时被填充在XML配置文件中,否则容器将抛出BeanInitializationException
如下例子:
被注入类定义
public class Instrument {
public void play() {
System.out.println("play instrument.");
}
}
注入类
public class Player {
private Instrument instrument;
public void play() {
instrument.play();
}
public Instrument getInstrument() {
return instrument;
}
@Required
public void setInstrument(Instrument instrument) {
this.instrument = instrument;
}
}
<bean id="instrument" class="com.domain.Instrument"/>
<bean id="player" class="com.domain.Player" >
<!-- <property name="instrument" ref="instrument"></property> -->
</bean>
注意player里面的property是被注释掉的,如果所以这个时候会报错,取消注释恢复正常
@Autowired
默认按类型注入,如果存在0个或者多个待选类型,则会报错。能够被应用于fields,constructor,setter method.
对于被@Autowired标注的对象甚至可以是private类型。
@Component
public class Football {
@Override
public String toString() {
// TODO Auto-generated method stub
return "football";
}
}
public class FootballPlayer {
@Autowired
private Football football;
public void play(){
System.out.println("footballPlayer is playing " + football);
}
}
可以直接注入到私有的football field里,甚至不需要setter method。
可以同时注入多个依赖
public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(MovieCatalog movieCatalog, CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao; }
// ...
}
public class MovieRecommender { @Autowired
private MovieCatalog[] movieCatalogs;
// ...
}
这将把容器内注册的所有MovieCatalog注入其中,如果注入的类型是map,则会自动按照 name:object 注入 name即是bean的名字
@Autowired可选属性有required,每个类只能有一个required = true ,可以存在多个required = false 当遇到多个可以选择方案时候,spring 容器采用贪心策略注入。
@Primary
因为@Autowired 会导致个可能注入bean发生,这个时候可以用@Primary来申明 某个待注入bean 为最优方法
@Configuration
public class MovieConfiguration {
@Bean
@Primary
public MovieCatalog firstMovieCatalog() { ... } @Bean
public MovieCatalog secondMovieCatalog() { ... }
// ...
}
这个时候如果某个类需要注入MovieCatalog 需要注入bean的时候 会首先选择@Primary标注的
public class MovieRecommender { @Autowired
private MovieCatalog movieCatalog;
// ...
}
这个时候注入的就是firstMovieCatalog
@Qulifier
当你需要指定特定的某一个bean,成为待注入对象的时候 你可以使用@Qualifier来标注
public class MovieRecommender {
@Autowired
@Qualifier("main")
private MovieCatalog movieCatalog;
// ...
}
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; }
// ...
}
这个时候autowired 会注入main所限定名称的bean
你可以按照自己的需要定制属于自己的@Qulifier
比如
@Target({ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Genre {
String value();
}
public class MovieRecommender {
@Autowired
@Genre("Action")
private MovieCatalog actionCatalog; private MovieCatalog comedyCatalog;
@Autowired
public void setComedyCatalog(@Genre("Comedy") MovieCatalog comedyCatalog) { this.comedyCatalog = comedyCatalog;
}
// ...
}
效果等同于@Qulifier
一般情况下你并不需要指定那么详细,你只需要指定Anotaion的名字即可
@Target({ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Offline {
}
这个时候可以通过@Offline注入对应的bean
public class MovieRecommender {
@Autowired
@Offline
private MovieCatalog offlineCatalog;
// ...
}
甚至可以使用枚举来作为参数限定
@Target({ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MovieQualifier {
String genre();
Format format();
}
public enum Format { VHS, DVD, BLURAY
}
public class MovieRecommender {
}
@Autowired
@MovieQualifier(format=Format.VHS, genre="Action") private MovieCatalog actionVhsCatalog;
@Autowired
@MovieQualifier(format=Format.VHS, genre="Comedy") private MovieCatalog comedyVhsCatalog;
@Autowired
@MovieQualifier(format=Format.DVD, genre="Action") private MovieCatalog actionDvdCatalog;
@Autowired
@MovieQualifier(format=Format.BLURAY, genre="Comedy") private MovieCatalog comedyBluRayCatalog;
// ...}