如何完成spring的最小化XML配置
一、自动装配
1、四种类型的自动装配
类型 | 解释 | xml 配置 |
---|---|---|
byname | 根据 bean 的 name 或者 id | <bean id=”bean” class=”…” autowire=”byname”/> |
bytype | 根据 bean 类型自动装配 | <bean id=”bean” class=”…” autowire=”bytype”/> |
contructor | 根据 bean 的构造器入参具有相同类型 | 同上 |
autodetect | 首先使用 contructor,失败再尝试 bytype | 同上 |
bytype 在出现多个匹配项时不会自动选择一个然是报错,为避免报错,有两种办法:1.使用<bean>元素的 primary 属性,设置为首选 bean,但所有 bean 的默认 primary 都是 true,因此我们需要将所有非首选 bean 设置为false;2.将 bean 的autowire-candidate熟悉设置为false,取消 这个 bean 的候选资格,这个 bean 便不会自动注入了。
contructor 自动装配和 bytype 有一样的局限性,当发现多个 bean 匹配某个构造器入参时,spring 不会尝试选择其中一个;此外,如果一个类有多个构造器都满足自动装配的条件,spring 也不会猜测哪个更合适使用。
2、默认自动装配
如果需要为 spring 应用上下文中的每个 bean(或者其中的大多数)配置相同的 autowire 属性,可以在根元素<beans>上增加一个 default-autowire 属性,默认该属性设置为 none。该属性只应用于指定配置文件中的所有 bean,并不是 spring 上下文中的所有 bean。
3、混合使用自动装配和显式装配
当我们对某个 bean 使用了自动装配策略,并不代表我们不能对该 bean 的某些属性进行显示装配,任然可以为任意一个属性配置<property>元素,显式装配将会覆盖自动装配。但是当使用 constructor 自动装配策略时,我们必须让 spring 自动装配构造器所有入参,不能使用<constructor-arg>元素进行混合。
二、注解装配
从 spring2.5 开始,可以使用注解自动装配 bean 的属性,使用注解允许更细粒度的自动装配,可选择性的标注某一个属性来对其应用自动装配。spring 容器默认禁用注解装配,需要在 spring 配置中启用,最简单的启用方式是使用 spring 的 context 命令空间配置中的<context:annotation-config>,如下所示:
<beans ...> <context:annotation-config/> <!-- bean declarations go here --> </beans>
spring3 支持几种不同的用于自动装配的注解:
- spring 自带的@autowired 注解
- jsr-330 的@inject 注解
- jsr-250 的@resource 注解
1、使用@autowired
@autowired 用于对被注解对象启动 bytype 的自动装配,可用于以下对象:
- 类属性,即使私有属性也能注入
- set 方法
- 构造器
- 任意需要装配 bean 的方法
在使用@autowired 时有两种情况会出错:没有匹配的 bean 和存在多个匹配的 bean,但是都有对应的解决方法。
当没有匹配 bean 时,自动装配会抛出 nosuchbeandefinitionexception,如果不想抛出可使用 required 属性,设置为 false 来配置可选的自动装配,即装配失败就不进行装配,不会报错。
@autowired(required=false)
当使用构造器配置时,只有一个构造器可以将 required 属性设置为 true,其他都只能设置为 false。此外,当使用注解标注多个构造器时,spring 会从所有满足装配条件的构造器中选择入参最多的那个。
当存在多个 bean 满足装配条件时,spring 也会抛出 nosuchbeandefinitionexception 错误,为了选择指定的 bean,我们可以使用@qualifier 注解进行筛选:
@autowired @qualifier("name1")//筛选名为name1的bean private testclass testclass;
除了通过 bean 的 id 来缩小选择范围,我们还可以通过直接在 bean 上使用 qualifier 来缩小范围,限制 bean 的类型,xml 如下:
<bean class="com.test.xxx"> <qualifier value="stringed"/> </bean>
注解如下:
@qualifier("stringed") public class xxx{}
还可以创建自定义限定器(qualifier)
创建自定义限定器只需要使用@qualifier 注解作为它的源注解即可,如下创建了一个 stringed 限定器:
@target({elementtype.field,elementtype.parameter,elementtype.type}) @retention(retentionpolicy.runtime) @qualifier public @interface stringed{}
然后使用它注解一个 bean:
@stringed public class guitar{}
然后就可以进行限定了:
@autowired @stringed private guitar guitar;
2、使用@inject 自动注入
为统一各种依赖注入框架的编程模型,jcp(java community process)发布的 java 依赖注入规范,被称为 jsr-330,从 spring3 开始,spring 已经开始兼容该依赖注入模型。
和@autowired 一样,@inject 可以用来自动装配属性、方法和构造器。但是@inject 没有 required 属性,因此依赖关系必须存在,如不存在将抛出异常。
jsr-330 还提供另一种注入技巧,注入一个 provider。provider 接口可以实现 bean 引用的延迟注入以及注入 bean 的多个实例等功能。
例如我们有一个 knifejuggler 类需要注入一个或多个 knife 实例,假设 knife bean 的作用域声明为 prototype,下面的 knifejuggler 的构造器将获得多个 knife bean:
private set<knife> knifes; @inject public knifejuggler(provider<knife> knifeprovider){ knives = new hashset<knife>(); for(int i=0;i<5;i++){ knives.add(knifeprovider.get()); } }
相对于@autowired 所对应的@qualifier,@inject 对应的是@named 注解。事实上 jsr-330 中也有@qualifier 注解,不过不建议直接使用,建议通过该注解来创建自定义的限定注解,和 spring 的@qualifier 创建过程类似。
3、注解中使用表达式
spring3 中引入的@value属性可用来装配 string 类型的值和基本类型的值。借助 spel 表达式,@value 不光可以装配硬编码值还可以在运行期动态计算表达式并装配,例如下面的:
@value("#{systemproperties.name}") private string name;
三、自动检测 bean
在 spring 中使用上面说到的<context:annotation-config>,可以做到自动装配,但还是要在 xml 中申明 bean。spring 还有另一个元素<context:component-scan>,元素除了完成自动装配的功能,还允许 spring 自动检测 bean 和定义 bean ,用法如下:
<beans ...> <context:component-scan base-package="com.springtest"> </context:component-scan> </beans>
开启后支持如下注解:
注解 | 解释 |
---|---|
@component | 通用的构造型注解,标识类为 spring 组件 |
@controller | 标识该类定义为 spring mvc controller |
@repository | 标识该类定义为数据仓库 |
@service | 标识该类定义为服务 |
使用上述注解是 bean 的 id 默认为无限定类名。使用@component("name")指定 id。
1、过滤组建扫描
通过为\context:component-scan配置<context:include-filter>和<context:exclude-filter>子元素,我们可以随意调整扫描行为。下面的配置自动注册所有的 testinterface 实现类:
<context:component-scan base-package="com.fxb.springtest"> <context:include-filter type="assignable" expression="com.fxb.springtest.testinterface"/> </context:component-scan>
其中的 type 和 expression 属性一起协作来定义组件扫描策略。type 有以下值可选择:
过滤器类型 | 描述 |
---|---|
annotation | 过滤器扫描使用指定注解所标注的类。通过 expression 属性指定要扫描的注解 |
assignable | 过滤器扫描派生于 expression 属性所指定类型的那些类 |
aspectj | 过滤器扫描于 expression 属性所指定的 aspectj 表达式所匹配的那些类 |
custom | 使用自定义的 org.springframework.core.type.typefilter 实现类,该类由 expression 属性指定 |
regex | 过滤器扫描类的名称与 expression 属性所指定的正则表达式所匹配的类 |
exclude-filter 使用和 include-filter 类似,只是效果相反。
四、使用 spring 基于 java 的配置
在 spring3.0 中几乎可以不使用 xml 而使用纯粹的 java 代码来配置 spring 应用。
首先还是需要极少量的 xml 来启用 java 配置,就是上面说到的<context:component-scan>,该标签还会自动加载使用@configuration注解所标识的类
@configuration 注解相当于 xml 配置中的\元素,这个注解将会告知 spring:这个类包含一个或多个 spring bean 的定义,这些定义是使用@bean 注解所标注的方法
申明一个简单的 bean 代码如下:
@configuration public class testconfig{ @bean public animal duck(){ return new ducker(); } }
@bean 告知 spring 这个方法将返回一个对象,该对象应该被注册为 spring 应用上下文中的一个 bean,方法名作为该 bean 的 id 。想要使用另一个 bean 的引用也很简单,如下:
@bean public food duckfood(){ return new duckfood(); } @bean //通过方法名引用一个bean,并不会创建一个新的实例 public animal duck(){ return new ducker(duckfood()); }
五、小结
终于写完了 spring 的最小化配置,对 spring 的各种注解也有了一些了解,再不是之前看到注解一脸莫名其妙了,虽然现在 springboot 已经帮我们做了零 xml 配置,但觉得还是有必要了解下 xml 配置实现,这样对 java 的配置实现理解也会更加深刻。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: python输入中文的实例方法
推荐阅读
-
02Spring基于xml的IOC配置--实例化Bean的三种方式
-
Spring实战之XML与JavaConfig的混合配置详解
-
Spring在web.xml中的配置详细介绍
-
Spring boot如何快速的配置多个Redis数据源
-
01Spring基于xml的IOC配置--入门
-
spring-mvc.xml 和 application-context.xml的配置与深入理解
-
Spring整合Struts 2与Hibernate(基于XML配置的S2SH整合)
-
spring和springMVC配置文件中的扫描包如何配置
-
web.xml中如何设置配置文件的加载路径实例详解
-
Spring MVC 的 XML 配置方式