Spring的高级装配注解,你知道几个?--《Spring实战》系列 04

领略完第一章的“Spring之旅”,我们看到Spring的三把宝刀,锋芒直击长空;体会完第二章的“装配Bean”,我们知道了Spring内功深厚,三招便杀敌于无形。今天我们正式开启第三章“高级装配”,一起来瞧一瞧Spring还有哪些高级装备。

这一章和第二章的区别在于,这一次我们可以更深入第二把宝刀“依赖注入”的内涵,去感受它内在的魅力。任何新技术的产生都是为了解决实际的问题,每一个新的问题出现也能够促进新的技术发展,Spring作为如此强大的框架自然也是如此。这一章读完之后,我脑海里只留下几个重要的注解,就是这几个注解解决了在实际开发中遇到的种种问题,我们一起来看。

注解一:@Profile

为谁而生: 跨环境部署。

在开发软件时,将应用程序从一个环境迁移到另一个环境是一个很大的挑战,因为这中间会发生很多变化,存在着很多不确定性,比如数据库配置,加密算法以及外部系统的集成。问题的关键就在于,不同的环境中某个bean会有所不同,而一旦bean变得不一样,那么bug就会不请自来,这是大家都不愿意看到的。

就在这时,Spring在3.1版本中,引入了bean profile的功能。在使用profile功能之前,必须先将所有不同的bean定义整理到一个或多个profile之中,并且在将应用部署到每个环境时,保证对应的profile处于active激活的状态。

同样,启动profile的功能也有两种方式,一是在Java配置类中,二是在XML配置文件中。第一种在Java配置类中,直接在类名前加上@Profile(“prod”)注解,并在后面注上是哪个环境即可。第二种在XML文件中使用的标签。

注解二:@Conditional

为谁而生:条件化的bean。

有时在开发中,我们并不希望一个bean在任何时候都可以被创建和调用,只希望它在特定情况下才被使用。这个时候就可以使用@Conditional注解了,一旦一个类加上这个注解,那么程序在运行到这一行时,如果给定的条件计算结果是true,那么就会创建这个bean,否则的话,这个bean就会被忽略。这样bean的创建和使用岂不是非常之灵活多变。

注解三:@Primary @Qulifier

为谁而生:自动装配的歧义性

什么叫自动装配的歧义性?在自动装配的过程中,如果仅有一个bean匹配所需结果时,自动装配才是有效的。如果不仅有一个bean能够匹配结果的话,这种歧义性会阻碍Spring自动装配属性,构造器参数或方法参数。比如说下面这个例子:

@Autowired
public void setDessert (Dessert dessert){
this.dessert = dessert;
}
// Dessert是一个接口,并且有三个实现类,分别是cake,cookies和IceCream
@Component
public class Cake implements Dessert(…);
@Component
public class Cookies implements Dessert(…);
@Component
public class IceCream implements Dessert(…);

从代码可见,这三个类都使用了@Component注解,在组件扫描的时候,都能够发现它们并将其创建为Spring应用上下文里面的bean。但是,当Spring试图自动装配setDessert()中的Dessert的参数时,它并没有唯一的一个可选值,到底是选Cake, Cookies还是IceCream里的,Spring绝对是一脸懵的,没办法它只能给你抛出异常NoUniqueBeanDefinitionException.

就在此时,我们的@Primary注解就可以挺身而出,把这种歧义性的自动装配问题解决掉,那就是在你想选择的那个类上面加上这个注解,到时候Spring就会优先自动装配这个带@Primary的bean。问题解决,无论是在Java类中还是在XML文件中,都可以实现,XML中使用的是 primary=true 的标签。

除了使用@Primary注解外,还可以使用@Qualifier注解来实现自定义限定符,也就是自己给bean起个名字,这样下次在组件扫描的时候,直接加上@Qualifier(“自己起的名字”)就可以解决上面说的歧义问题了。

注解四: @Scope

为谁而生:bean的多作用域

首先什么是bean的多作用域。bean其实在默认情况下是单例singleton的形式,也就是不管给定的一个bean被注入到其它bean多少次,每次所注入的都是同一个实例。这种方式在大多时候都是理想的情况,但有些特殊情况,你所使用的类是易变的(mutable),它们会保持一些状态,因此重用是不安全的。这个时候,bean的多作用域就发挥作用了。

它们包括:
单例(singleton): 在整个应用中,只创建bean的一个实例
原型(prototype):每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例
会话(session): 在web应用中,为每个会话创建一个bean实例
请求(Request): 在web应用中,为每个请求创建一个bean实例

但是该如何在实际开发中自由的切换作用域呢?注解@Scope。 只需要在类的前面加上@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)就可以了。或者是在xml中使用标签 scope=“prototype”, 实现bean作用域的自由切换。

一个大招:运行时值注入

除了这五个高级装配注解以外,这一章还介绍了运行时值注入的两种方式。这一技术产生的原因是什么呢?在编程中,有时候硬编码是可以的,有时候我们也希望避免硬编码值,希望它是动态的,在运行时再确定,为了实现这一功能,就有了以下两种运行时值注入的方式:

属性占位符(Property placeholder)
Spring表达式语言(SpEL)

关于这两种运行时值注入方式细节特别多,我们下回再详细聊~

Spring的故事还没完,我们明天见~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值