上一章 详解SSJ(Spring3.x mvc + Spring3.x Core + JPA2.x)轻量级集成开发—第2章 剖析IOC容器进阶
下一章 详解SSJ(Spring3.x mvc + Spring3.x Core + JPA2.x)轻量级集成开发—第4章 剖析Annotations特性
目录
一、原始类型(字面值)注入;
二、引用类型(复合类型)注入;
三、集合类型注入;
前言
在上一章中,笔者详细的讲解了关于IOC容器的方方面面。对于刚接触Spring的朋友而言,笔者建议你一定要仔细的阅读笔者前几章讲解的内容,因为只有当你熟知这些最基本也是最核心的内容后,你才会更容易接受后续章节的内容。看过笔者博文的朋友都给笔者提过一些非常重要的意见,笔者在此由衷的感谢你们 ,是你们的支持才让笔者的博文更加精彩。大家应该都知道笔者的博文一般不太喜欢讲解一些不重要且罗里吧嗦几乎很难用到的东西,这是笔者的风格。但如果你觉得你希望看到非常全面的内容,那么笔者推荐你参考Spring的官方使用手册。
一、原始类型(字面值)注入
依赖装配有2种常规的方式,一种是投值注入,另外一种也就是构造注入。虽然在前面章节中笔者已经详细的讲解过了2种注入方式的用法,但是本章还需继续对依赖装配的参数类型做进一步讲解。
我们都知道在JVM内部,原始数据类型有4类8种:
1、整数类型:byte、short、int、long;
2、浮点类型:float、double;
3、字符类型:char;
4、布尔类型:boolean;
当然JVM内部还存在一种原始类型returnAddress,很遗憾的是Java程序员并不能够使用该类型,该类型被用来实现Java程序设计语言中的finally子句。
来看看在IOC配置文件的<bean/>标签中,我们使用<property/>标签来实现原始类型的投值注入:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> <bean name="product" class="org.johngao.bean.ProductBean"> <property name="productName" value="洗面奶" /> <property name="productPrice" value="16.8" /> <property name=productStock value="200" /> <property name="productDiscount" value="false" /> </bean> </beans>
对应的Bean代码如下:
public class ProductBean { private String productName; private double productPrice; private int productStock; private boolean productDiscount; /* 此处省略set和get方法 */ }
定义在IOC配置文件中的“value”属性值其实都是为字符串,只不过当IOC进行依赖装配的时候,会强制性做类型检查然后对应转换为所定义在Bean中属性的类型,这便是原始类型参数的注入。当然使用构造注入的方式和投值注入式一样的,所以笔者在此就不再重复演示使用构造注入的方式来注入原始数据类型,或许你可以自己尝试。
二、引用类型(复合类型)注入
其实所谓引用类型,我们可以理解为对象类型。也就是说在JVM的数据类型中,除了原始数据类型外,其余的都是引用类型。相信大家都应该知道引用类型一般由3种类型组成:
1、类类型;
2、数组类型;
3、接口类型;
其中类类型的值是对类实例的引用,接口类型则是对其派生类的实例引用,数组类型则是对数组对象的引用。在JVM中存在一种特殊的引用值null,该引用值表示引用类型的变量没有引用任何对象。
在JVM中原始类型并没有作为引用类型来实现,这样做的目的是出于效率方面的考虑。因为引用类型的变量所持有的是引用值,并不是真正的原始数据,这种间接的层次增加了资源的开销,而原始类型则没有这种开销。
可能会有很多朋友会问引用类型和原始类型有什么区别呢?原始类型的变量持有的是其原始值,然而引用类型的变量则持有引用值。原始值是指真正的原始数据,引用值指的则是对某个对象的引用,并不是目标对象本身。
JVM中的数据类型示例图:
提示:
大家来猜猜看JVM中是否存在指针?或许大部分人说有,大部分人说没有。当然笔者在这里并不是想挑起事端,笔者的浅见仅仅只是认为JVM中其实并不存在真正意义上的指针,只是说对象的引用就类似于指针的操作,仅此而已。
接下来咱们仍然使用投值注入的方式来注入引用类型参数,只不过这里咱们需要使用到“ref”属性进行引用:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean name="productBean" class="org.johngao.bean.ProductBean">
<property name="buyBean" ref="buyBean"/>
</bean>
<bean name="buyBean" class="prg.johngao.bean.BuyBean"/>
</beans>
当IOC容器对参数进行依赖装配之前,首先会实例化定义在IOC配置文件中的Bean实例,不管这个Bean实例是否是单例,实例化操作绝对优先于依赖装配,这一点希望大家切记。笔者发现很多刚学习Spring的朋友往往最容易犯的一个错误就是在IOC容器实例化Bean实例的时候赋值或者引用还未依赖装配的参数,往往这种错误发生的时候,新手相当郁闷,甚至会自顾自的说,怎么搞的,我明明依赖装配了啊,也引用了依赖装配啊,怎么还是不行呢,所以细心是关键。
新手常见错误如下:
@Resource private String productName; private String productName2 = productName;
仔细观察上述代码,IOC容器在初始化Bean实例的时候,其实还并未对productName属性进行依赖装。但这个时候productName2属性已经在引用productName的值了,想想看productName的缺省构造赋值是什么?没错就是“null”,所以希望大家注意下。
三、集合类型注入
在很多情况下,我们依赖装配注入的参数可能会使用到集合类型。从严格意义上来说集合类型也是属于引用类型的一种,那么接下来我们就来看看如何注入集合类型参数,这里值得庆幸的是Spring对集合类型的参数注入提供了良好的支持。
先来看看使用投值注入的方式如何注入一个List类型的集合类型:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> <bean name="products" class="org.johngao.bean.Products"> <property name="productBeans"> <list> <bean class="org.johngao.bean.ProductBean"> <property name="productName" value="洗面奶" /> <property name="productPrice" value="16.8" /> <property name="productStock" value="200" /> <property name="productDiscount" value="false" /> </bean> <bean class="org.johngao.bean.ProductBean"> <property name="productName" value="洗发水" /> <property name="productPrice" value="36.8" /> <property name="productStock" value="30" /> <property name="productDiscount" value="true" /> </bean> </list> </property> </bean> </beans>
上述配置文件中笔者演示了如何使用投值注入的方式注入一个List集合类型,如果你想使用Set或者Map集合的方式注入你的集合参数,Spring也是支持的。
来看看使用构造注入的方式如何注入一个Set类型的集合类型:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> <bean name="products" class="org.johngao.bean.Products"> <constructor-arg> <set> <bean class="org.johngao.bean.ProductBean"> <property name="productName" value="洗发水" /> <property name="productPrice" value="36.8" /> <property name="productStock" value="30" /> <property name="productDiscount" value="true" /> </bean> <bean class="org.johngao.bean.ProductBean"> <property name="productName" value="洗面奶" /> <property name="productPrice" value="16.8" /> <property name="productStock" value="100" /> <property name="productDiscount" value="true" /> </bean> </set> </constructor-arg> </bean> </beans>
通过上述配置文件我们可以发现,如果注入集合参数时,我们可以指定<list/>、<map>、<set/>等标签来进行标注,至此本章的内容到此结束了,由于时间仓库,本文可能存在诸多不尽人意的地方,希望各位体谅。