1.Spring IoC简介
IoC:控制反转(Inversion of Control),在传统开发模式下,都是由开发人员自行创建对象,并管理对象,当使用了Spring框架后,这些事情都交给框架来完成,可以理解“将开发人员对对象的管理权交给了框架”,所以,就出现了“管理权”的移交,则称之为“控制反转”。
DI:依赖注入(Dependency Injection),具体表现为通过框架为对象的属性赋值。
IoC与DI:Spring框架通过DI实现了IoC,DI是实现手段,而IoC是希望实现的目标。
关于Spring IoC,就是要掌握:如何通过Spring框架确实某个类的对象的属性值。
2. 通过SET方式注入属性的值
假设存在User
类,其中有String password
属性,希望Spring在创建User
类的对象时,还能为password
属性注入值(赋值),则先准备好User
类,例如:
package cn.tedu.spring;
public class User {
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
System.out.println("User.setPassword()");
this.password = password;
}
}
然后,在Spring的配置文件中进行配置:
<bean id="user" class="cn.tedu.spring.User">
<!-- property节点:用于配置属性的值 -->
<!-- name属性:需要配置值的属性名称,实际是set方法对应的名称 -->
<!-- value属性:需要配置值的属性的值 -->
<property name="password" value="000111"/>
</bean>
最后,运行时,当获取对象后就可以直接输出属性值,可以看到,该属性已经存在所配置的值。
注意:在<property>
属性中,name
属性其实是SET方法对应的名称,例如以上配置为name="password"
,则Spring框架会基于这个配置值,将首字母大写,并在左侧拼上set
,得到setPassword
,以此为方法名称,结合value
属性值,调用了setPassword("000111")
,从而使得password
属性被赋值。所以,本质是要求name
属性的值与类的SET方法是对应的。但是,规范的SET方法名称与Spring组织出SET方法的方式是完全相同的,所以,也可以简单的理解为name
属性指的就是属性名称。
2.1注入List集合类型的值
如果需要注入List
集合类型的值,例如存在:
// David, Lucy, Tom, Lily, Alex
private List<String> names;
则需要配置为:
<bean id="sampleBean" class="cn.tedu.spring.SampleBean">
<property name="names">
<list>
<value>David</value>
<value>Lucy</value>
<value>Tom</value>
<value>Lily</value>
<value>Alex</value>
</list>
</property>
</bean>
2.2注入数组类型的值
如果需要注入的是数组类型的,例如存在:
// 9, 5, 2, 7
private int[] numbers;
则配置为:
<property name="numbers">
<array>
<value>9</value>
<value>5</value>
<value>2</value>
<value>7</value>
</array>
</property>
2.3注入Set集合类型的值
如果需要注入的是Set
集合类型的数据,假如存在:
// Beijing, Shanghai, Guangzhou, Shenzhen
private Set<String> cities;
则需要配置为:
<property name="cities">
<set>
<value>Beijing</value>
<value>Shanghai</value>
<value>Guangzhou</value>
<value>Shenzhen</value>
</set>
</property>
2.4注入Map类型的值
如果需要注入的是Map
类型的数据,假如存在:
// {username:root, password:1234, from:Beijing}
private Map<String, String> session;
则需要配置为:
<property name="session">
<map>
<entry key="username" value="root"/>
<entry key="password" value="1234"/>
<entry key="from" value="Beijing"/>
</map>
</property>
2.5注入Properties类型的值
如果需要注入的是java.util.Properties
类型的数据,假如存在:
// name:Jack, age:25, gender:Male
private Properties profile;
则配置为:
<property name="profile">
<props>
<prop key="name">Jack</prop>
<prop key="age">25</prop>
<prop key="gender">Male</prop>
</props>
</property>
当然,Properties
类型的数据也可以从.properties
类型的文件中读取。可以先在src/main/resources下创建jdbc.properties文件,并在其中进行属性与值的配置:
url=jdbc:mysql://localhost:3306/database_name
driver=com.mysql.jdbc.Driver
username=root
password=root
initialSize=2
maxActive=10
在Spring的配置文件中,需要使用<util:properties>
节点来读取这个文件,这个节点与<bean>
节点是同一个级别的节点,不要将这个节点写在<bean>
的子级。
在配置时:
<!-- util:properties节点:用于读取.properties文件中的配置信息 -->
<!-- location属性:需要读取的文件的位置 -->
<!-- classpath:指的就是resources文件夹 -->
<util:properties id="jdbc" location="classpath:jdbc.properties"></util:properties>
如果这些数据需要被读取到SampleBean
的Properties jdbc
属性中,先在SampleBean
中添加:
// 数据来自于jdbc.properties文件
private Properties jdbc;
并且,在Spring的配置文件中,在配置SampleBean
的<bean>
节点子级添加:
<property name="jdbc" ref="jdbc"/>
小结:如果某个类中的某个属性需要被注入值,首先,需要为这个属性添加匹配的SET方法,在Spring的配置文件中,在该类对应的<bean>
节点的子级,添加<property>
节点,用于为属性注入值,如果有多个属性都需要注入值,则同一个<bean>
节点的子级应该有多个<property>
节点,在每个<property>
节点中,都通过name
属性指定需要注入值的属性名称,假设需要注入值的属性叫password
,则应该配置为name="password"
,如果该属性的值是可以直接写出来的(例如数值、字符串、布尔值),则在<property>
节点中添加value
属性来配置值,如果该属性的值是另一个Bean对象,则在<property>
节点添加ref
属性来引用另一个<bean>
节点或等同节点的id
值,如果该属性的值是集合类型的,则需要在<property>
节点的子级添加<list>
/ <set>
/ <array>
/ <map>
/ <props>
进行配置,具体配置方式参考以上笔记中的示例代码。
3. 通过构造方法注入属性的值(用得少)
如果某个类没有无参数的构造方法,并且,希望通过构造方法为某些属性注入值,例如:
package cn.tedu.spring;
// 使用构造方法注入属性的值
// 使用构造方法注入时,并不要求每个属性都有SET/GET方法
public class Person {
// Zoe
private String username;
// 26
private int age;
public Person(String username, int age) {
super();
this.username = username;
this.age = age;
}
@Override
public String toString() {
return "Person [username=" + username + ", age=" + age + "]";
}
}
在Spring的配置文件中,需要配置为:
<bean id="person" class="cn.tedu.spring.Person">
<!-- constructor-arg节点:配置构造方法的参数 -->
<!-- index属性:参数的位置,即第几个参数 -->
<constructor-arg index="0" value="Zoe"/>
<constructor-arg index="1" value="26"/>
</bean>
所以 ,如果构造方法中有多个参数,在<bean>
节点的子级就需要添加多个<constructor-arg>
节点进行配置,在<constructor-arg>
节点中,index
属性表示参数的位置,是从0
开始顺序编号,也就是:第1个参数的index
值是0
,第2个参数的index
值是1
,以此类推,如果对应的参数值是数值、字符串、布尔值,就通过value
属性进行配置,如果对应的参数值是另一个Bean对象,就需要通过ref
属性引用到另一个<bean>
节点的id
值,如果对应的参数值是某种集合类型的,则需要在<constructor-arg>
的子级添加集合节点进行配置。