`

Spring(14)——基于注解的配置(二)

阅读更多

14.4 @Qualifier

14.4.1 简介

@Qualifier通常是配合@Autowired的一起使用的。我们知道使用@Autowired进行注入时默认是按照类型进行注入的。打个比方当我们使用@Autowired的定义beanA需要自动注入一个类型为BeanB的bean时,如果在bean容器中存在多个类型为BeanB的bean,那么Spring就会抛出异常。这个时候我们就可以使用@Qualifier来指定需要进行注入的到底是哪个BeanB类型的bean,具体bean是通过@Qualifier注解的value属性来进行指定的。以下示例表示我们通过@Qualifier指定我们需要注入的是beanName为world的那个World,这个时候需要两者都满足的bean才能被注入,即要求被注入的bean既是World类型的,又必须对应的beanName为“world”。

public class Hello {
	
	@Qualifier("world")
	@Autowired
	private World world;

}

对于通过构造方法或普通方法注入的形式,我们可以将@Qualifier标注在对应的方法参数上,以确定到底需要注入哪个对象。如下我们在构造方法参数world上使用@Qualifier标注了我们需要进行注入的是beanName为world1的那个World类型的bean。

public class Hello {
	
	private World world;
	private BeanA beanA;
	
	@Autowired
	public Hello(@Qualifier("world1") World world, BeanA beanA) {
		this.world = world;
		this.beanA = beanA;
	}
	
}

@Qualifier注解的value属性值默认对应的是对应bean定义的beanName,而实际上@Qualifier寻找的是对应的qualifier,只是在没有指定对应的qualifier时默认会取beanName。对应的qualifier可以在进行bean定义时通过qualifier元素进行定义。如下示例我们在定义bean定义时指定了对应的qualifier为abc,那么之后我们在通过@Qualifier指定需要注入该bean时就只能使用@Qualifier(“abc”),而不能使用@Qualifier(“world1”)。

<bean id="world1" class="com.app.World">
	<qualifier value="abc"/>
</bean>

qualifier元素除了可以通过value属性指定当前元素对应的qualifier之外,还需要指定一个type属性,该属性的默认值是org.springframework.beans.factory.annotation.Qualifier。只有这两者的结合才能对应一个qualifier。如在上述示例中当我们在字段上使用@Qualifier(“abc”)进行标注时,实际上Spring将会去寻找value为“abc”,type为org.springframework.beans.factory.annotation.Qualifier的qualifier对应的对应类型的bean进行注入,如果不存在对应类型的qualifier,则取beanName为“abc”的那个bean进行注入。此外还支持给一个bean定义多个qualifier,即定义多个qualifier元素。

在使用qualifier元素定义一个bean的qualifier时允许有重复的qualifier存在,即不要求每个元素的qualifier在当前bean容器内是唯一的。

14.4.2 自定义@Qualifier

@Qualifier还可以标注在其它注解上,这样就形成了一个自定义的Qualifier。在使用@Autowired的时候我们也可以使用自定义的Qualifier来标识我们需要进行注入的具体是哪一个bean。我们先来自定义一个Qualifier,叫MyQualifier。

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
@Qualifier
public @interface MyQualifier {
	
	public String value() default "";
	
}

然后就可以在我们的代码中使用@MyQualifier进行标识需要注入的bean了。

public class Hello {
	
	@MyQualifier("world1")
	@Autowired
	private World world;

}

根据前面的介绍我们知道这里使用@MyQualifier(“world1”)进行标注后,Spring将寻找type为com.app.MyQualifier,value为world1的Qualifier对应com.app.World类型的bean进行注入。当没有找到时就会取beanName为world1的World类型的bean进行注入。所以我们的World类型的bean可以如下定义:

<bean id="world" class="com.app.World" p:id="10">
	<qualifier type="com.app.MyQualifier" value="world1"/>
</bean>

也可以不指定qualifier,然后指定其beanName为world1,这个时候也可以有其它类型的Qualifier定义,但是切不可有MyQualifier类型的Qualifier定义。如下这种定义是可以的。

<bean id="world1" class="com.app.World" p:id="10">
	<qualifier value="abc"/>
</bean>

我们也可以在使用@MyQualifier进行注入时不定义对应的参数,如:

public class Hello {
	
	@MyQualifier
	@Autowired
	private World world;

}

那么对应的在定义需要注入的bean时,也不能指定对应的参数,但是需要定义qualifier元素,并指定对应的type。

<bean id="world0" class="com.app.World" p:id="10">
	<qualifier type="com.app.MyQualifier"/>
</bean>

在自定义Qualifier的时候也可以给我们自定义的Qualifier加上其它额外的属性,如在下面示例中我们给MyQualifier多加了一个order属性的定义。

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
@Qualifier
public @interface MyQualifier {
	
	public String value() default "";
	
	public int order() default 0;
	
}

那么在使用MyQualifier进行标注的时候我们就可以使用新增加的属性进行定义了。

public class Hello {
	
	@MyQualifier(order=1, value="world1")
	@Autowired
	private World world;

}

对应的我们在定义bean时也需要通过qualifier定义对应的属性,这个时候对应的属性是通过qualifier的子元素attribute进行定义的。

<bean class="com.app.World" p:id="10">
	<qualifier type="com.app.MyQualifier" value="world1">
		<attribute key="order" value="1"/>
	</qualifier>
</bean>

对于使用注解进行扫描bean的情况其实我们还可以直接在对应的bean上使用@Qualifier进行标注来指定当前bean对应的qualifier。关于使用注解扫描bean并添加到bean容器中的内容将在后续文章中进行讲解。这里我们先来看一个对应的示例。

@Component
@Qualifier("abc")
public class World {

}

14.5 @Resource

@Resource是JSR250标准中的一个注解,Spring也对其提供了支持,我们可以使用@Resource标注在我们需要进行自动注入的field或set方法上,也可以是普通的非set方法上,但是对应方法只允许接收一个参数。其不能像@Autowired那样定义在构造方法上,也不允许通过一个方法同时注入多个bean对象。

public class Hello {
	
	@Resource
	private World world;
	private BeanA beanA;
	
	/**
	 * 通过普通方法进行注入,对应方法只允许拥有一个参数
	 * @param beanA
	 */
	@Resource
	public void otherMethod(BeanA beanA) {
		this.beanA = beanA;
	}

}

使用@Resource时默认是通过按照beanName来进行注入的。@Resource拥有一个name属性,我们可以通过它来指定我们需要注入的bean的beanName。当没有指定时默认将使用field的名称,或set方法去掉set前缀后的名称。当对应beanName的bean在bean容器中不存在时,Spring将尝试按照需要注入的类型寻找对应的bean给@Resource标注的field或方法进行注入,但此时如果对应类型的bean拥有多个时也一样会报异常。

public class Hello {
	
	/**
	 * 优先注入beanName为world1的bean,不存在时才注入一个类型为World的bean。
	 */
	@Resource(name="world1")
	private World world;

}

对于其它如数组、集合类型的注入,以及ApplicationContext等的注入@Resource也是一样支持的。

public class Hello {
	
	@Resource
	private World[] worldArray;
	@Resource
	private List<World> worldList;
	@Resource
	private Set<World> worldSet;
	@Resource
	private Map<String, World> worldMap;
	
	@Resource
	private ApplicationContext applicationContext;

}

因为元素类型的问题,我们不能直接通过@Autowired加@Qualifier的形式注入一个集合等类型的bean,但是这种情况我们可以通过@Resource来解决。如我们拥有如下这样一个ArrayList类型的bean定义。

<bean id="strList" class="java.util.ArrayList">
	<constructor-arg>
		<list>
			<value>abc</value>
			<value>bcd</value>
			<value>cde</value>
		</list>
	</constructor-arg>
</bean>

如果现在我们需要在我们的程序中自动注入这么一个bean,那么通过@Autowired加@Qualifier的形式是不行的,但是我们只能通过@Resource进行注入。

public class Hello {
	
	@Resource(name="strList")
	private List<String> strList;

}

其实,类似的支持自动注入的注解还有JSR330标准的@Inject注解,这个将在后续单独讲解。

14.6 @PostConstruct和@PreDestroy

@PostConstruct和@PreDestroy注解在之前讲解bean的生命周期回调方法的时候有讲解过。其实把它们放在这里来讲可能并不是很合适,因为这两个注解不需要我们在Spring的配置文件中配置启用Spring对注解的支持就可以使用,即不需要配置<context:annotation-config/>就可以用的注解。但既然本文是讲解Spring对使用注解进行配置的支持,那就还是顺便讲讲。使用@PostConstruct进行标注的方法会被当做是初始化方法,其会在对应bean实例化之后由Spring进行调用。使用@PreDestroy进行标注的方法会被当做是释放资源的方法,其会在bean容器销毁前由Spring进行调用。使用@PostConstruct和@PreDestroy进行标注的方法都是不能带参数。更多信息请参考之前介绍bean生命周期回调的那篇文章。

public class Hello {
	
	@PostConstruct
	public void doInit() {
		System.out.println("init****************");
	}
	
	@PreDestroy
	public void doDestroy() {
		System.out.println("destroy***************");
	}

}

(注:本文是基于Spring4.1.0所写)

 

 

本文转自:https://elim.iteye.com/blog/2388585

分享到:
评论

相关推荐

    跟我学spring3(8-13)

    【第十二章】零配置 之 12.4 基于Java类定义Bean配置元数据 ——跟我学spring3 【第十二章】零配置 之 12.5 综合示例-积分商城 ——跟我学spring3 【第十三章】 测试 之 13.1 概述 13.2 单元测试 ——跟我学spring3 ...

    JavaEE开发的颠覆者SpringBoot实战[完整版].part3

    10.3 云部署——基于Docker 的部署 419 10.3.1 Dockerfile 419 10.3.2 安装Docker 421 10.3.3 项目目录及文件 421 10.3.4 编译镜像 423 10.3.5 运行 424 10.4 Spring Boot 的测试 424 10.4.1 新建Spring Boot 项目 ...

    spring杂谈 作者zhang KaiTao

    1.18 不重复配置——利用Spring通用化配置 1.19 @Value注入Properties 错误的使用案例 1.20 @Value注入Properties 使用错误的案例 1.21 扩展SpringMVC以支持更精准的数据绑定 1.22 扩展SpringMVC以支持更精准的数据...

    JavaEE开发的颠覆者SpringBoot实战[完整版].part2

    10.3 云部署——基于Docker 的部署 419 10.3.1 Dockerfile 419 10.3.2 安装Docker 421 10.3.3 项目目录及文件 421 10.3.4 编译镜像 423 10.3.5 运行 424 10.4 Spring Boot 的测试 424 10.4.1 新建Spring Boot 项目 ...

    JavaEE开发的颠覆者SpringBoot实战[完整版].part1

    10.3 云部署——基于Docker 的部署 419 10.3.1 Dockerfile 419 10.3.2 安装Docker 421 10.3.3 项目目录及文件 421 10.3.4 编译镜像 423 10.3.5 运行 424 10.4 Spring Boot 的测试 424 10.4.1 新建Spring Boot 项目 ...

    Spring.3.x企业应用开发实战(完整版).part2

    4.10.2 使用注解配置信息启动Spring容器 4.10.3 自动装配Bean 4.10.4 Bean作用范围及生命过程方法 4.11 基于Java类的配置 4.11.1 使用Java类提供Bean定义信息 4.11.2 使用基于Java类的配置信息启动Spring容器 4.12 ...

    超详细的Spring框架讲解,就这一篇!足矣

    Spring框架概述1、什么是Spring2、Spring框架的优点3、Spring框架体系结构Spring框架——控制反转(IOC)1、IOC介绍2、基于配置的IOC2.1、导入jar包2.2、配置文件2.3、测试3、基于注解的IOC3.0、导包3.1、开启注解...

    Spring3.x企业应用开发实战(完整版) part1

    4.10.2 使用注解配置信息启动Spring容器 4.10.3 自动装配Bean 4.10.4 Bean作用范围及生命过程方法 4.11 基于Java类的配置 4.11.1 使用Java类提供Bean定义信息 4.11.2 使用基于Java类的配置信息启动Spring容器 4.12 ...

    跟我学spring3(8-13).pdf

    11.2 实现通用层 11.3 实现积分商城层 12.1 概述 12.2 注解实现Bean依赖注入 12.3 注解实现Bean定义 12.4 基于Java类定义Bean配置元数据 12.5 综合示例-积分商城 13.1 概述 13.2 单元测试 集成测试 ——跟我学spring3

    Spring Security 中文教程.pdf

    7.4. 使用其他过滤器 —— 基于框架 8. 核心安全过滤器 8.1. FilterSecurityInterceptor 8.2. ExceptionTranslationFilter 8.2.1. AuthenticationEntryPoint 8.2.2. AccessDeniedHandler 8.3. ...

    SpringSecurity 3.0.1.RELEASE.CHM

    7.4. 使用其他过滤器 —— 基于框架 8. 核心安全过滤器 8.1. FilterSecurityInterceptor 8.2. ExceptionTranslationFilter 8.2.1. AuthenticationEntryPoint 8.2.2. AccessDeniedHandler 8.3. ...

    Spring Security-3.0.1中文官方文档(翻译版)

    7.4. 使用其他过滤器—— 基于框架 8. 核心安全过滤器 8.1. FilterSecurityInterceptor 8.2. ExceptionTranslationFilter 8.2.1. AuthenticationEntryPoint 8.2.2. AccessDeniedHandler 8.3. ...

    MyStudentManagerSSM-1.0.zip

    MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。 2、开发环境搭建以及创建Maven Web项目 参看之前的博文...

    基于JavaEE的快速开发框架

    模块化开发,使用注解简化配置,增强代码可读性与维护性。 组件图 组件图 单元测试组件图 模块说明 core——基础模块。 dao——持久化模块。 ctrl——控制层模块。 ctrl-http——HTTP(S)模块。 ctrl-socket——...

    基于JavaWEB+SSM+mysql框架构建的在线商城系统源码+数据库+项目说明(课程设计).zip

    * 实现了一个 **通用mapper**,免写 SQL,可进行单表和多表关联查询,自动插入一对多/多对一对象(注解配置关联对象,结合 MyBatis Generator ) * 实现了一个 **BaseService 类** ,集成了多条件的查询和增改删...

    Struts2 in action中文版

    9.3.2 基于Spring管理JPA编写代码 212 9.4 小结 216 第10章 探索验证框架 217 10.1 熟悉数据验证框架 217 10.1.1 验证框架的架构 218 10.1.2 Struts 2工作流中的验证框架 219 10.2 将动作关联到验证框架 222 10.2.1...

    支持多数据库的ORM框架ef-orm.zip

    EF的设计的一个主要目的是提高开发效率,减少编码工作,让开发者“零配置”“少编码”的操作数据库大部分功能。 例如:数据库查询条件的传入问题是所有ORM框架都不能回避的一个问题,所以我经常在想——既然我们...

    JAVA上百实例源码以及开源项目源代码

    14个目标文件 内容索引:JAVA源码,系统相关,日历,日期选择  Java语言开发的简洁实用的日期选择控件,源码文件功能说明:  [DateChooser.java] Java 日期选择控件(主体类) [public]  [TablePanel.java] 日历表格...

    JAVA上百实例源码以及开源项目

    14个目标文件 内容索引:JAVA源码,系统相关,日历,日期选择  Java语言开发的简洁实用的日期选择控件,源码文件功能说明:  [DateChooser.java] Java 日期选择控件(主体类) [public]  [TablePanel.java] 日历表格...

Global site tag (gtag.js) - Google Analytics