紧接着上篇内容,本篇文章将主要介绍XML Schema的简化配置和使用SpEL表达式语言来优化我们的配置文件。

一、基于XML Schema的简化配置方式

从Spring2.0以来,Spring支持使用XML Schema来简化配置。在以前的bean元素配置下,所有的属性注入都需要一个property元素,集合属性就需要更多的这样的元素,一旦项目庞大,整个配置文件将无法维护。XML Schema提供的命名空间,可以帮助我们的配置文件缩减容量。主要有三种命名空间:

  • p:命名空间简化属性配置
  • c:命名空间简化构造配置
  • util:命名空间简化集合配置

1、使用p:命名空间简化配置

首先看一个我们常见的bean的配置:

<bean id="person" class="MyPackage.Person">
<property name="name" value="single"/>
<property name="age" value="22"/>
</bean>

这是一个再普通不过的bean的配置,它等效于:

<bean id="person" class="MyPackage.Person" p:name="single" p:age="22" />

但是这么做的前提是,在Spring配置文件的XML头部导入p的命名空间:

xmlns:p="http://www.springframework.org/schema/p"

无论你是使用IDE自动导入的,还是使用工具,或者自己手动导入的,想要使用p Schema,就必须该命名空间。p是property的缩写,除了可以注入普通的值类型之外,还可以注入引用类型,例如:

<bean id="person" class="MyPackage.Person" p:name-ref="stuName" p:age="22" />

2、使用c:命名空间简化配置

我们使用p命名空间简化了设置注入操作,c命名空间则是constructor的缩写,它用于简化构造注入的操作。例如:

<bean id="person" class="MyPackage.Person" c:name="single" c:age="22" />

Spring最后会调用构造注入,将name和age作为参数出入bean类的构造器中,构造实例返回。除此之外,还可以这么写:

<bean id="person" class="MyPackage.Person" c:_0="single" c:_1="22" />

下划线加上数字表示,这是构造器中的第几个参数,到时候会被Spring按序传入构造器中。

3、使用util命名空间简化配置

util给我们提供了以下几个元素:

  • constant:对于在配置文件中获取指定类的静态Field的值的一个简化配置
  • property-path:对于在配置文件中获取调用getter方法的一个简化配置
  • list:简化list作为bean的配置
  • map:简化map作为bean的配置
  • set:简化set作为bean的配置
  • properties:加载一份properties属性文件

^1、constant

首先看一段我们之前用于获取一个类的静态属性的配置:

<bean id="person" class="MyPackage.Person">
<property name="name" value="single"/>
<property name="age">
<bean class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
<property name="targetClass" value="MyPackage.BeanStaticClass"/>
<property name="targetField" value="age"/>
</bean>
</property>
</bean>

这是一段我们之前用于在配置文件中获取类静态属性的代码,总体上来说还是挺繁琐的,下面我们使用util下的constant来简化这段配置。

<bean id="person" class="MyPackage.Person">
<property name="name" value="single"/>
<property name="age">
<util:constant static-field="MyPackage.BeanStaticClass.age"/>
</property>
</bean>

static-field属性的值指定了需要访问那个类下的那个静态属性。如果需要将该值单独定义在容器中,可以为其增加id属性以便其他bean实例获取。

^2、property-path

对于在配置文件中直接调用其他bean的getter方法,我们一般如是配置:

<bean id="student" class="MyPackage.Student">
<property name="age" value="22"/>
</bean> <bean id="person" class="MyPackage.Person">
<property name="name" value="single"/>
<property name="age">
<bean class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<property name="targetBeanName" value="student"/>
<property name="propertyPath" value="age"/>
</bean>
</property>
</bean>

一般我们需要这么写来配置,下面我们通过util的property-path来简化配置:

<bean id="student" class="MyPackage.Student">
<property name="age" value="22"/>
</bean> <bean id="person" class="MyPackage.Person">
<property name="name" value="single"/>
<property name="age">
<util:property-path path="student.age"/>
</property>
</bean>

property-path的值指定了需要调用那个bean实例的那个getter方法。如果需要单独将该值配置在容器中,可以为其指定id。

^3、list

通过util,Spring允许我们单独定义一个list bean在容器中。一个list bean给我们提供如下几个属性:

  • id:容器中的唯一标识
  • list-class:指定实现该list的实现类,默认为ArrayList
  • scope:指定该list的作用域

下面我们定义一个list bean:

<util:list id="list" list-class="java.util.ArrayList">
<value>nanjing</value>
<value>nantong</value>
<value>yancheng</value>
</util:list>

^4、map和set

有关map和set的util使用,基本和list的使用情况类似,此处只给出创建bean的配置代码,其他的不再赘述。

//map
<util:map id="map" map-class="java.util.HashMap">
<entry key="中国银行" value="241241212" />
<entry key="建设银行" value="543534545"/>
</util:map>
//set
<util:set id="set" set-class="java.util.HashSet">
<value>single</value>
<value>cyy</value>
</util:set>

至此,有关XML Schema的基本内容已如上述所述,Spring中还有一些其他相关的Schema文件,它们各自有各自的作用,有用于简化AOP配置的,有用于简化事务配置的等等,我们将在后续文章中进行学习。

二、使用Spring的EL表达式语言

Spring的配置文件有一个非常明显的缺陷,大量的静态注入,动态性不强。而SpEL类似于jsp的EL,采用表达式的方式为属性注入值,当程序动态运行时,这些表达式的值才确定。SpEL可以单独使用,也可以在Spring配置文件中使用,我们此处主要介绍在配置文件中的SpEL的使用。

1、创建数组

有时我们的实例中有类型为数组的属性,那么我们就可以通过SpEL定义数组作为参数注入依赖给该属性。

<bean id="person" class="MyPackage.Person">
<property name="array" value="#{new int[]{12,2,5,7,8,6,8}}" />
</bean>

在Spring配置中使用SpEL中,基本的使用格式如下:

#{expression}

2、创建list集合

我们也可以使用SpEL定义list集合,例如:

<bean id="person" class="MyPackage.Person">
<property name="list" value="#{{'single','cyy','xijingping'}}"/>
</bean>

list集合的定义使用 "{....}",大括号中的每个元素都对应于list中的一个元素。

我们可以通过以下语法格式访问list中的元素:

listName[index]

访问容器中map集合中的元素:

mapName[key]

例如:

<bean id="person" class="MyPackage.Person">
<property name="name" value="#{list[0]}"/>
</bean>

这段配置会向person实例中的name属性注入容器中已经定义好的名为list的第一个元素的值。

3、调用方法

在SpEL中调用任意方法将会比我们之前介绍的那种纯配置形式简单很多,例如:

<bean id="person" class="MyPackage.Person">
<property name="name" value="#{'hello'.concat(' world!')}"/>
</bean>

我们这里调用了jdk中的方法为person实例的name属性注入依赖值,当然也可以是我们自己定义的方法,可以是任意的方法。

4、类运算符

SpEL提供了一种运算符:T()。该运算符告诉Spring将括号中的内容作为一类类型而不是作为字符串进行解析。例如:

<bean id="person" class="MyPackage.Person">
<property name="name" value="#{java.lang.Math.random()}"/>
</bean>

这样书写,Java会给我们报错,说java.lang.Math.random()并不是一个字符串,但是如果给他加上单引号,那么该函数就会以纯字符串作为参数注入给name属性,并不会被识别为正常函数。

正确书写格式如下:

<bean id="person" class="MyPackage.Person">
<property name="name" value="#{T(java.lang.Math).random()}"/>
</bean>

5、集合选择

使用SpEL集合选择的基本格式如下:

collection.?[condition_expr]

只有符合条件condition_expr的集合元素才会被选择出来,例如:

<bean id="person" class="MyPackage.Person">
<property name="list" value="#{list.?[length()>7]}"/>
</bean>

Spring会遍历整个list,每个元素都会调用他的length方法判断是否大于7,如果不是将舍弃该元素,否则该元素才会被帅选出来。

6、集合投影

集合投影可以让集合中的每个元素都去执行同一个方法,每个元素调用同一个方法,不同元素的该方法的返回值将构成最终的新集合。例如:

<bean id="person" class="MyPackage.Person">
<property name="list" value="#{list.![length()]}"/>
</bean>

最终新集合中的元素是原集合中每个元素的长度。

SpEL的用法远非如此,这里只是列举了常用的几种用法。

两篇文章加强了对bean配置的理解,有总结不到之处,望指出!

Spring框架学习之高级依赖关系配置(二)的更多相关文章

  1. Spring框架学习之高级依赖关系配置(一)

    上篇文章我们对Spring做了初步的学习,了解了基本的依赖注入思想.学会简单的配置bean.能够使用Spring容器管理我们的bean实例等.但这还只是相对较浅显的内容,本篇将介绍bean的相关更高级 ...

  2. spring-第九篇之高级依赖关系配置

    1.关于配置文件一些使用 组件与组件之间的耦合,采用依赖注入管理:基本类型的成员变量值,应该直接在代码中设置. 2.获取其他bean的属性值 PorpertyPathFactoryBean用来获取目标 ...

  3. Spring框架学习笔记(3)——配置bean

    1.属性注入 (1)根据setter方法属性注入,这里使用的是property标签.需要bean属性提供对应的setter方法,比如笔记(1)里的 HelloWorld使用的就是这种方法. <! ...

  4. Spring框架学习笔记(4)——配置bean more

    1.配置List属性 <!-- 配置List属性 --> <bean id="person4" class="com.broadtext.beans.c ...

  5. Spring框架学习之注解配置与AOP思想

         上篇我们介绍了Spring中有关高级依赖关系配置的内容,也可以调用任意方法的返回值作为属性注入的值,它解决了Spring配置文件的动态性不足的缺点.而本篇,我们将介绍Spring的又一大核心 ...

  6. Spring框架学习一

    Spring框架学习,转自http://blog.csdn.net/lishuangzhe7047/article/details/20740209 Spring框架学习(一) 1.什么是Spring ...

  7. Spring框架学习1

    AnonymouL 兴之所至,心之所安;尽其在我,顺其自然 新随笔 管理   Spring框架学习(一)   阅读目录 一. spring概述 核心容器: Spring 上下文: Spring AOP ...

  8. Spring框架学习之IOC(一)

    Spring框架学习之IOC(一) 先前粗浅地学过Spring框架,但当时忙于考试及后期实习未将其记录,于是趁着最近还有几天的空闲时间,将其稍微整理一下,以备后期查看. Spring相关知识 spri ...

  9. Spring框架学习笔记(5)——Spring Boot创建与使用

    Spring Boot可以更为方便地搭建一个Web系统,之后服务器上部署也较为方便 创建Spring boot项目 1. 使用IDEA创建项目 2. 修改groupid和artifact 3. 一路n ...

随机推荐

  1. WebSocket In ASP.NET Core(二)

    WebSocket In ASP.NET Core(二) Server in ASP.NET-Core DI in ASP.NET-Core Routing in ASP.NET-Core Error ...

  2. TEXT宏

    TEXT宏是windows程序设计中经常遇到的宏,定义在 <winnt.h>中 TCHAR *P = TEXT("this is a const string"); 如 ...

  3. 使用LayUI操作数据表格

    接着 上一篇 继续完善我们的demo,这次我们加一个搜索按钮 搜索 在table标签的上方,加入这样一组html <div class="demoTable"> 搜索商 ...

  4. GitHub Desktop客户端打开文件乱码问题解决方案

    今天在使用GitHub Desktop客户端的时候,发添加本地仓库后文件内容显示为乱码. 1.现象  如下图所示: 2.原因分析 后来分析得知原来是由于编码不统一造成 的. 具体来说,我在window ...

  5. 6656 Watching the Kangaroo

    6656 Watching the KangarooDay by day number of Kangaroos is decreasing just liketiger, whale or lion ...

  6. Life Forms (poj3294 后缀数组求 不小于k个字符串中的最长子串)

    (累了,这题做了很久!) Life Forms Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 8683   Accepted ...

  7. Python selenium 文件自动下载 (自动下载器)

    MyGithub:https://github.com/williamzxl 最新代码已经上传到Github,以下版本为stupid版本. 由于在下载过程中需要下载不同文件,所以可以把所有类型放在Va ...

  8. java spark-streaming接收TCP/Kafka数据

    本文将展示 1.如何使用spark-streaming接入TCP数据并进行过滤: 2.如何使用spark-streaming接入TCP数据并进行wordcount: 内容如下: 1.使用maven,先 ...

  9. JavaScript前端和Java后端的AES加密和解密

    在实际开发项目中,有些数据在前后端的传输过程中需要进行加密,那就需要保证前端和后端的加解密需要统一.这里给大家简单演示AES在JavaScript前端和Java后端是如何实现加密和解密的. 直接上代码 ...

  10. Virgo标签打印

    去年刚换新的公司,熟悉新的业务和代码,在修改公司打印标签的时候,感觉到无比烦躁与头痛.只因为不好维护,所有的标签打印,全部是GDI+绘制,每次修改微调,都只能全部运行才能看到效果.程序过大,编译过慢, ...