Spring中的自动装配:@Autowired【基础】

自动装配

自动装配(autowiring):Spring自动满足bean之间的依赖。

隐式配置和自动装配组合在一起能发挥出强大的威力,它们能够将你的显式配置降低到最少。

用法:

现在需要构造一个Bean:person,Person类中含有Cat类型的成员变量(容器中已存在一个Cat类型的Bean:cat),利用@Autowired注解,Spring可以自动地将容器中的cat装配给这个成员变量

@Component
public class Cat {    }

@Component
public class Person {

	@Autowired
	private Cat cat;    //利用@Autowired自动装配
    
	...
}
原理:

在Spring创建对象的过程中,会为类里标有@Autowired注解的地方,默认按类型 (byType) 从容器中匹配一个bean注入进去

1、@Autowired注解可以标注的地方:成员变量上、构造器上、方法上

  • 用在成员变量上:
@Autowired
private UserService userService;   //Spring在容器中匹配一个类型为UserService的bean注进去
  • 用在构造器上:
private Book book;

@Autowired
public Student(Book book) {    //Spring会优先使用带有@Autowired的构造方法实例化对象(Bean的生命周期:构造方法的推断),方法使用的参数:在容器中匹配一个类型为Book的bean注进去       
    this.book = book;
}
  • 用在方法上(普通方法也可以,不一定非是set方法):
@Autowired
public void setBook(Book book) {  
    this.book = book;
}
问题1:

■ 若当前容器中没有匹配类型的bean,就会抛出异常。为了避免异常的出现,可以将@Autowired的required的值设为 false。

@Autowired(required = false)
private Book book;

将required属性设置为false时,Spring尝试自动装配,若没有该类型的bean,Spring将会让这个属性处于未装配的状态。
但是,把required属性设置为false时,你需要谨慎对待。如果在你的代码中没有进行null检查的话,那么这个处于未装配状态的属性有可能会出现NullPointerException

问题2:

■ 若容器中匹配到一个类型的多个bean怎么办?

例:类Food中,有一个Dessert属性,我们希望利用自动装配来完成此属性的赋值

@Component
public class Food {

	@Autowired
	private Dessert dessert;    
    
	...
}

Dessert是一个接口,有三个实现类,分别为Cake、Cookies和IceCream

@Component
public class Cake implements Dessert {..}
@Component
public class Cookies implements Dessert {..}
@Component
public class IceCream implements Dessert {..}

Spring会按Dessert类型 (byType) 查找容器,但是查找到三个bean:cake、cookies、iceCream 。这时,出现了歧义性问题:应该选择哪个bean注入呢?

其实,若查找到了多个bean,Spring会再按变量名字 (dessert)进行查找,当然,当前容器中是没有 dessert 的。这时就会抛出异常:NoUniqueBeanDefinitionException。

对此,我们有两种解决方法:

方法一:使用@Primary设置首选bean
@Component
@Primary    //若有多个bean符合,则"优先"选择这个bean
public class iceCream implements Dessert {..}

如果你使用的是Java配置显式地声明IceCream,那么@Bean方法应该如下所示:

@Bean
@Primary
public Dessert iceCream(){
    return new IceCream() 
}

如果你使用的是XML显示地声明IceCream,那么标签应该如下所示:

<bean id="icecream" class="com.desserteater.IceCream" primary="true"/>

不管采用什么方式来标示首选bean,效果都是一样的,都是告诉Spring在遇到歧义性的时候要选择首选的bean。当然,要注意:只能指定一个Primary首选bean,若指定了多个首选bean,则又会出现歧义性问题

方法二:使用@Qualifier限定符
@Component
public class Food {

	@Autowired
    @Qualifier("cold")    //限定:注入一个"冷的"甜品
	private Dessert dessert;    
    
	...
}

@Qualifier是可以与@Component、@Bean等一起结合使用的

@Component
@Qualifier("soft")  //"软的"
public class Cake implements Dessert {..}

@Component
@Qualifier("crispy")  //"脆的"
public class Cookies implements Dessert {..}

@Component
@Qualifier("cold")  //"冷的"
public class IceCream implements Dessert {..}
@Bean
@Qualifier("soft")
public Dessert cake(){
    return new Cake() 
}

@Bean
@Qualifier("crispy")
public Dessert cookie(){
    return new Cookies() 
}

@Bean
@Qualifier("cold")
public Dessert iceCream(){
    return new IceCream() 
}

参考书籍:《Spring实战 第4版》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值