基于注解的注入方式会在xml注入方式之前执行,因此,如果对一个Bean同时做了基于注解的配置和xml配置,xml配置会覆盖注解配置
可以通过context:annotation-config/来隐式的注入bean,但是需要注意,context:annotation-config/只查找定义在与它相同的application Context中的Bean的注释,也就是说,如果将它定义在dispatcherServlet的WebApplicationContext中,则他只检查Controller层中的@Autowired,而不检查Service层中的。
@Autowired
@Autowired注解可以用在构造函数上,从spring4.3开始,如果一个Bean只有一个构造函数,则不需要在构造函数上加此注解,但是如果有多个构造函数,则需要在至少一个构造函数上加@Autowired注解,告诉容器使用哪一个进行初始化。
public class MyBean {
private String beanName;
@Autowired
public MyBean(String beanName) {
this.beanName = beanName;
}
}
@Autowired注解可以用在setter方法上
public class MyBean {
private String beanName;
@Autowired
public void setBeanName(String beanName) {
this.beanName = beanName;
}
}
也可以用在方法上
public class MyBean {
private Target target;
private Method method;
@Autowired
public void prepare(Target target, Method method) {
this.target = target;
this.method = method;
}
}
可以用在字段上
public class MyBean {
@Autowired
private Target target;
@Autowired
private Method[] methodArray;
}
如果想要对注入的集合中的元素进行排序,则目标Bean可以实现org.springframework.core.Ordered接口,或者使用@Order、@Priority注解来指定顺序。需要注意,若指定了顺序,可能会导致某些依赖关系不正确,此时可以通过@DependsOn来指定依赖关系。
若被注入项是可选的,可以使用@Autowired(required = false)来标注。也可以使用java8的Optional来声明,如下
public class MyBean {
private Target target;
@Autowired
public void setBeanName(Optional<Target> targetOptional) {
this.target = targetOptional.get();
}
}
或者可以使用@Nullable注解
public class MyBean {
private Target target;
@Autowired
public void setBeanName(@Nullable Target target) {
this.target = target;
}
}
@Configuration
public class MyConfig {
@Bean
@Primary
public Target targetA() {
return new Target("One");
}
@Bean
public Target targetB() {
return new Target("TWO");
}
}
public class Client {
@Autowired
private Target target;
// ...
}
此时,Client中注入的即为Target("One"),此注解等同于如下xml配置
<bean class="example.Target" primary="true" />
public class Client {
@Autowired
@Qualifier("targetA")
private Target target;
// ...
}
也可以用在构造函数或方法的参数上
public class MyBean {
private Target target;
private Method method;
@Autowired
public void prepared(@Qualifier("targetB") Target target, Method method) {
this.target = target;
this.method = method;
}
}
对应的xml配置如下
<bean class="example.Target" >
<qualifier value="targetA" />
</bean>
<bean class="example.Target" >
<qualifier value="targetB" />
</bean>
在类型匹配中,如果要根据Bean的名称来进行选择,不需要使用@Qualifier,@Autowired本身可以在类型匹配的候选对象中按Bean的名称进行选择。
但是,在需要通过Bean名称选择注入Bean的时候,不推荐使用@Autowired,使用JSR-250的@Resource更准确一些,因为当指定了bean的名称时,它从语义上被定义为通过唯一名称来标识特定的目标组件,而忽略声明的类型。只有当没有指定bean的名称,并且通过字段名或setter名找不到对应的Bean时,才会通过类型匹配。但是@Autowired具有不同的语义,它是先按照类型进行筛选,然后在筛选过的候选Bean中按照名称来定位。
可以自定义限定符注解,如下
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MyQualifier {
String value();
}
public class MyBean {
@Autowired
@MyQualifier("targetA")
private Target target;
private Method method;
@Autowired
public void prepared(@MyQualifier("targetB") Target target, Method method) {
this.target = target;
this.method = method;
}
}
<bean class="example.Target" >
<qualifier type="MyQualifier" value="targetA"/>
</bean>
<bean class="example.Target" >
<qualifier type="example.MyQualifier" value="targetB"/>
</bean>
也可以使用没有值的注解,通过类型来进行筛选,如下
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MyQualifier {
}
public class MyBean {
@Autowired
@MyQualifier
private Target target;
private Method method;
}
<bean class="example.Target" >
<qualifier type="MyQualifier"/>
</bean>
也可以为注解设置多个属性,如果在装配Bean的时候指定了多个属性值,则Bean必须匹配了所有属性值才能被视为装配的候选,如下
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MyQualifier {
String value();
Condition condition();
}
public enum Condition {
NAME,
SEX,
AGE
}
public class MyBean {
@Autowired
@MyQualifier(value="targetA", condition=Condition.NAME)
private Target target;
private Method method;
}
<bean class="example.Target" >
<qualifier type="MyQualifier">
<attribute key="value" value="targetA" />
<attribute key="condition" value="NAME" />
</qualifier>
</bean>
@Configuration
public class MyConfig {
@Bean
public StringStore stringStore() {
return new StringStore();
}
@Bean
public IntegerStore integerStore() {
return new IntegerStore();
}
}
public interface Store<T> {
T getValue();
}
public IntegerStore implements Store<Integer> {
public Integer getValue() {
return 0;
}
}
public StringStore implements Store<String> {
public String getValue() {
return "0";
}
}
public class Client {
@Autowired
private Store<String> s1;
@Autowired
private Store<Integer> s2;
}
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface DeerQualifier {
}
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface FoxQualifier {
}
<context:annotation-config />
<bean id="customAutowireConfigurer" class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
<property name="customQualifierTypes">
<set>
<value>example.DeerQualifier</value>
<value>example.FoxQualifier</value>
</set>
</property>
</bean>
<bean class="example.AnimalService"/>
<bean class="example.Fox">
<qualifier type="FoxQualifier"/>
</bean>
<bean class="example.Deer">
<qualifier type="DeerQualifier"/>
</bean>
public interface Animal {
void printName();
}
public class Deer implements Animal {
@Override
public void printName() {
System.out.println("--- Deer ---");
}
}
public class Fox implements Animal {
@Override
public void printName() {
System.out.println("--- Fox ---");
}
}
@Service
public class AnimalService {
@Autowired
@DeerQualifier
private Animal animal;
public Animal getAnimal() {
return animal;
}
}
<bean class="xxx" autowire-candidate="false/true"/>
<beans default-autowire-candidate=“false/true”></beans>
@Qualifier
原文:https://www.cnblogs.com/kuromaru/p/12834344.html