入门
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这个方法的无参形式。
这样,工厂注入完成。