入门
Spring有两个功能,控制反转,和注入属性
控制反转
IoC把对象生成放在了XML里定义,所以当我们需要换一个实现子类将会变成很简单(一般这样的对象都是实现于某种接口的),只要修改XML就可以了。
IoC的缺点是,生成一个对象的步骤变复杂了,对于不习惯这种方式的人,会觉得有些别扭和不直观。对象生成因为是使用反射编程,在效率上有些损耗。但相对于IoC提高的维护性和灵活性来说,这点损耗是微不足道的,除非某对象的生成对效率要求特别高。
多种方式注入属性
基本上可以分为
属性注入
- 注入基本类型
- 注入对象类型
- 注入数组类型
构造方法注入
- 按照类型注入
- 按照位置注入
工厂方法注入
- 静态工厂注入
- 实例工厂注入
这些会在后面一一提到。
配置spring环境
我们在idea下使用maven来配置spring环境
首先,新建一个maven项目,然后再pom.xml中加入Spring的包依赖
1
2
3
4
5
6
|
<!--Spring基础jar包--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.2.4.RELEASE</version> </dependency> |
等待maven刷新完成。
然后再file-> Projectr Structure
中选择Faces,将里面的Spring减掉。
然后再项目上右键,选择Add Framework Support
选中Spring,然后勾选创建空的配置文件,之后完成。
这样基本的环境配置完成。
系统自动生成的spring-config.xml会在java目录下,maven项目需要将其移动到resources目录下。
多重方式实现注入
我们可以通过在xml中注入属性,然后通过spring来得到对象,这样在对象属于Spring,降低了耦合性,因为我们可以在xml中配置属性的属性。
如果我们不用的话,我们原来是需要使用new然后调用构造函数来得到一个对象。
###属性注入
最简单的我们建立一个没有属性的类,只有一个输出的语句的成员函数。
在xml配置文件中写入
1
|
<bean
id="pet" class="pojo.Cat"></bean> |
id是我们在配置文件中的唯一标识,注意如果不写id的话,会默认将类名首字母小写,然后当作id,也就是cat。
class也就是我们写的类的全类名
这里我们先建立一个Pet宠物类建立一个虚函数,shout(),然后继承建立一个Cat。
代码如下:
1
2
3
|
public
abstract
class
Pet { public
abstract
void
shout(); } |
然后是cat类,继承Pet重写shout
1
2
3
4
5
6
|
public
class
Cat extends
Pet{ @Override public
void
shout() { System.out.print("这是cat"); } } |
这样我们就可以在测试类中,测试是否能得到这个cat。
建立测试类
在测试函数中,我们需要加载spring的配置文件,然后再配置文件中得到对象,然后调用对象的shout方法。
1
2
3
|
ApplicationContext
context= new
ClassPathXmlApplicationContext("spring-config.xml"); Pet
pet= (Pet) context.getBean("pet"); pet.shout(); |
可以在上面的代码看到我们通过classPathXMlApplicationContext得到了一应用上下文,然后根据这个对象getBean方法,传入参数就能得到这个对象,注意类型的强制转换
测试代码的基本都是这样。
但是这个类没有属性,我们新建一个Master类,给他一个age,和name属性,然后在配置文件中,加上
1
2
3
4
|
<bean
id="master" class ="pojo.Master"> <property
name="name" value="张三"></property> <property
name="age" value=" 21 "/> </bean> |
加入了property节点,其中的name就是set方法中的属性名,首字母小写,如果没有这个set方法的话,会飘红报错。value就是对应的值。
这是基本类型。
如果对象的类型是引用类型的话,比如我们给这个master加上一个pet属性。
类型是Pet,然后我们在他的属性下面加一个属性节点
如下:
1
|
<property
name="pet" ref="pet"/> |
这里的ref属性其中填的就是pet,前面已经声明过的pet。
如果属性类型是基本类型的数组类型,就加上array标签,或者list等也可如下:
1
2
3
4
5
6
|
<property
name="strs"> <array> <value>123</value> <value>321</value> </array> </property> |
如果是一个对象数组,将value换成bean或者ref即可,如果是bean的话,说明是新建的对象,如果ref代表是引用的对象。
1
2
3
4
5
6
|
<property
name="strs"> <array> <bean
id="pet2" class="pojo.Cat"></bean> <bean
id="pet3" class="pojo.Cat"></bean> <bean
id="pet4" class="pojo.Cat"></bean> </array> |
构造方法注入
如果我们使用的是属性注入,spring会调用的是无参的构造方法。如果我们写了带有参数的构造方法,那么需要手动写一个无参的构造方法,相应的,我们也可以调用有参的构造方法来进行初始化,调用构造函数分为两种,一种是按类型注入,另一种是按照位置注入。
按照类型注入
1
2
3
4
5
6
7
8
9
10
|
<bean
id="master" class="pojo.Master"> <!--注入基本数据类型--> <constructor-arg
type="java.lang.Integer" value="20"/> <!--
对于包含特殊字符的属性值,可以在value子节点使用CDATA --> <constructor-arg
type="java.lang.String"> <value><![CDATA[<sansan>]]></value> </constructor-arg> <!--ref用于注入对象类型--> <constructor-arg
type="pojo.Pet" ref="petBean"/> </bean> |
这里外层的bean不变。
里面的使用的是constructor-arg,type写入的是类型。另外如果是数组的话,参照上面的处理。
另外一种就是按照位置插入,从0开始,按照参数的顺序插入。
例如:
1
2
3
4
5
|
<beanid="master3"class="pojo.Master"> <constructor-argindex="0"value="wangwg"/> <constructor-argindex="1"value="12"/> <constructor-argindex="2"ref="pet"/> </bean> |
如果有数组的话一样的处理。
工厂方法注入
如果使用工厂方法注入的话,我们需要一个工厂类,然后我们通过spring建立工厂,然后调用工厂方法产生实例,类型分为两种,一种是静态工厂注入,另一种是实例工厂注入,需要实力话出来,如果不好理解的话,可以理解为一个商店,我们需要什么的时候我们就买什么,通过类的多态来进行处理。
这里我们新建一个petShop然后建立一个普通的方法,传入一个String类型,如果是Cat,我们就返回new Cat(),这也就是实例工厂注入。
实例工厂注入需要实例化类,所以需要对工厂类在配置文件里进行配置,然后将需要生产出来的bean配置好即可。
如下:
1
2
3
4
|
<bean
id="petShop" class="pojo.PetShop"/> <bean
id="cat" factory-bean="petShop" factory-method="getPet"> <constructor-arg
value="cat" index="0"></constructor-arg> </bean> |
这里我们看到,这个cat实例是使用的两个属性,一个是我们调用的工厂对象,也就是上面生成的工厂的id,另一个就是生产方法调用的方法。
如果是静态的工厂,我们需要将生产方法声明为静态的然后直接生产例如:
1
|
<bean
id="cat2" class="pojo.PetShop" factory-method="getPet"></bean> |
这里的类型就是工厂类型,然后调用工厂方法,这里我重载了getPet这个方法的无参形式。
这样,工厂注入完成。