首页 > 编程语言 > 详细

Spring Core 官方文档阅读笔记(四)

时间:2020-05-06 10:19:33      阅读:67      评论:0      收藏:0      [点我收藏+]
  1. 基于注解的注入方式会在xml注入方式之前执行,因此,如果对一个Bean同时做了基于注解的配置和xml配置,xml配置会覆盖注解配置

  2. 可以通过context:annotation-config/来隐式的注入bean,但是需要注意,context:annotation-config/只查找定义在与它相同的application Context中的Bean的注释,也就是说,如果将它定义在dispatcherServlet的WebApplicationContext中,则他只检查Controller层中的@Autowired,而不检查Service层中的。

  3. @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;
    }
}
  1. @Primary
    当同一类型有多个注入项时,在使用时可以通过@Primary注解指定特定的实例,如下
@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" />
  1. @Qualifier
    当希望更细致的控制Bean的选择过程,可以使用@Qualifier注解,基本用法如下:
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>
  1. 可以使用泛型来做为自动装配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;
}
  1. CustomAutowireConfigurer
    可以通过CustomAutowireConfigurer来自定义限定符注解,如下
@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;
	}
} 
  1. 通过三种方法可以设置Bean定义是否做为候选项
<bean class="xxx" autowire-candidate="false/true"/>
<beans default-autowire-candidate=“false/true”></beans>
@Qualifier
  1. @PostConstruct和@PreDestory可以在构造器执行完毕后和实例销毁前执行自定义逻辑

Spring Core 官方文档阅读笔记(四)

原文:https://www.cnblogs.com/kuromaru/p/12834344.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!