spring 学习总结(二) IOC的初步应用
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
IOC的实现原理
Ioc是通过读取配置文件中。然后利用反射机制,在需要的时候获取对象。
在spring中的实现方式如下:
1.使用XML配置、或者注解将对象进行存放。
2.spring容器通过读取配置文件或者元数据创建对象,并将对象存入IoC容器。
3.在使用时,从IoC容器中取出对象。
在网上偷了张图,大致可以描述清楚:

首先我们需要搭建好spring的运行环境,现在大多是通过maven进行依赖注入,随手在网上找一份即可(以下配置文件转自张果,侵删):
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zxl</groupId>
<artifactId>MyProject</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>MyProject</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>4.3.0.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
<version>4.10</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.4</version>
</dependency>
</dependencies>
</project>
1.无参构造
在实体类文件夹entity中创建一个Worke类
public class Worker{
private int userId;
private String name;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId= userId;
}
public String getName(){
return name;
}
public void setName(String name) {
this.name = name;
}
}
在spring.xml文件中配置bean标签,bean中id表示对象名,class表示模板类:
<?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.xsd">
<!-- 配置Worker对象-->
<bean id="worker1" class="com.zxl.entity.Worker"></bean>
</beans>
调用API获取对象,通过id获取对象:
public class Test {
public static void main(String[] args) {
//1.加载spring.xml配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
//2.通过id值获取对象
Worker worker1 = (Worker) applicationContext.getBean("worker1");
System.out.println(worker1);
}
}
此处创建对象并非用new创建,而是通过读取配置文件,利用反射机制创建
以上程序打印出的信息大致如下
Worker {userId=0,name=null}
此处调用了Worke类的无参构造方法,只会创建对象,不会赋值。需要赋值可以进行配置。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 配置worker对象 -->
<bean id="worker1" class="com.zxl.entity.Worker">
<property name="userId" value="32"></property>
<property name="name" value="随月踏清风"></property>
</bean>
</beans>
此时打印的结果为:
Worker {userId=32 name=随月踏清风}
无参构造赋值是通过调用setter方法,因此getter方法可以不要,但是setter方法不能省略。
2.有参构造
有无参构造,就有有参构造。有参构造,顾名思义就是在类中加入有参构造方法。代码如下:
public class Worker{
private int userId;
private String name;
public Worker(int userId,String name){
this.userId = userId;
this.name = name;
}
}
spring.xml的配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 通过有参构造函数创建对象 -->
<bean id="worker1" class="com.zxl.entity.Worker">
<constructor-arg name="userId" value="32"></constructor-arg>
<constructor-arg name="name" value="随月踏清风"></constructor-arg>
</bean>
</beans>
IOC容器根据constructor-arg标签加载对应的有参构造函数,创建对象并完成属性赋值。如果不想通过name进行参数赋值,可以利用索引index进行对应,如下:
<bean id="worker1" class="com.zxl.entity.Worker">
<constructor-arg index="0" value="32"></constructor-arg>
<constructor-arg index="1" value="随月踏清风"></constructor-arg>
</bean>
以上方法从容器中获取的对象都是单例对象,不管创建多少个,指向的都是同一个,如下面的例子
ApplicationContext ctx=newClassPathXmlApplicationContext("spring.xml");
Worker worker1=ctx.getBean("worker1");
Worker worker2=ctx.getBean("worker1");
System.out.println(worker1==worker2)
显而易见,打印的结果是true。想一个bean对象对应多个,可以使用scope指定作用域。

修改配置文件如下:
<bean id="worker1" class="com.zxl.entity.Worker" scope="prototype">
<constructor-arg index="0" value="32"></constructor-arg>
<constructor-arg index="1" value="随月踏清风"></constructor-arg>
</bean>
若此时再次运行测试代码,运行结果为false。
需要说明的是,指定bean的时候,可以用id和(或)name,两者都可以找到指定的bean,但是也存在一部分差异,此处不做过多说明。
IOC是spring的核心,spring中控制层、业务层、持久层都是通过IOC完成依赖注入的,本文只针对ioc的简单应用进行了整理,更多用法还需要继续学习。