文章目录
什么是IoC/DI?
它的全称是:Inversion of Control/Dependency InJect,翻译过来就是控制反转/依赖注入。IoC是spring的基础,它实现一种控制反转的功能。说白了就是把对象的控制权交给了Spring而不再由应用程序来创建。DI与IoC的功能相同,因为他们的主语都是Spring,只不过是换了一个说法来表述同一件事情,它实现的是依赖注入,因为它已经被赋予了相关的值,直接使用就OK。
搭建Spring环境
下面先看一下Spring基础包的说明:
| 包名 | 描述 |
|---|---|
| spring-core-xxx-x.jar | Spring框架的核心工具类 ,Spring的其他组件都要使用这个包 |
| spring-beans-xxx-x.jar | Spring所有的应用都需要用到的Jar,他能访问配置文件、创建和管理bean以及实现IoC和DI操作相关的所有类 |
| spring-context-xxx-x.jar | 提供了IoC的扩展服务还提供许多企业级服务的支持。如:远程访问、缓存、邮件等 |
| spring-expression-xxx-x.jar | 定义了spring表达式语言 |
使用Spring时,需要把这四个基础包导入(后面有一个坑要踩):

实现IoC
IoC理论上是借助于“第三方”实现了具有依赖关系对象之间的解耦。
定义一个UserDao接口:
package com.dz.ioc_di;
public interface UserDao {
/**
* 讲一下哈:你好
*/
public abstract void sayHello();
}
UserDaoImpl去实现它
package com.dz.ioc_di;
public class UserDaoImpl implements UserDao {
@Override
public void sayHello() {
System.out.println("你好!");
}
}
将UserDao装配到容器
(配置文件可以到官网找到:spring配置文件获取)配置文件起名为applicationContext.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">
<!-- 把userDao装配到spring容器中(IoC) -->
<bean id="userDao" class="com.dz.ioc_di.UserDaoImpl"></bean>
</beans>
id=“userDao”:我们将要根据id从容器中取值。
class=“com.dz.ioc_di.UserDaoImpl”:将对象创建出来放到id里面。
测试
public class Test {
public static void main(String[] args) {
//加载配置文件
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//根据容器里面的id去获取到里面的对象
UserDao userDao = ac.getBean("userDao", UserDao.class);
//调用执行接口的方法
userDao.sayHello();
}
}
结果,报出一个错误?找不到日志类?

看了一下官方文档,里面说Logging是Spring唯一一个强制依赖的类,因为有一些人想要去看它的执行日志。所以我们把它导入进去就OK了。

再看结果,成功执行了方法:

实现DI
实现依赖注入的方法就多了,可以使用setter方法注入、可以使用构造器注入、也可以使用注解注入。
setter方法注入
下面在实现IoC的基础上升级一小下,定义一个User实体类:
public class User {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
同样滴,在applicationContext.xml里面进行配置:(注意bean里面的变化)
<?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">
<!-- 把user实体 装配到spring容器中,并注入值 -->
<bean id="user" class="com.dz.ioc_di.User">
<property name="name" value="dz"></property>
<property name="age" value="23"></property>
</bean>
<!-- 把userDao装配到spring容器中(IoC),并注入对象 -->
<bean id="userDao" class="com.dz.ioc_di.UserDaoImpl">
<!-- 根据name的名称=构造方法里面的参数名称,ref是要引用注入的对象 -->
<property name="user" ref="user"></property>
</bean>
</beans>
property 标签:里面配置的是类里面的属性。
name属性:对应的是类里面属性的名称。
value属性:就是给属性赋值了。
ref属性:引用的是当前配置文件里面其他bean的id。
userDaoImpl变为:
package com.dz.ioc_di;
public class UserDaoImpl implements UserDao {
User user; //需要注入对象,相当于user=new User();
@Override
public void sayHello() {
System.out.println("你好!" + user.getName() + "。你是" + user.getAge() + "吗?");
}
//提供setter方法,实现注入
public void setUser(User user) {
this.user = user;
}
}
其他的不进行改变,看结果:

构造器注入
实体类、UserDao接口、测试方法不进行改变,改变UserDaoImpl实现类:
package com.dz.ioc_di;
public class UserDaoImpl implements UserDao {
User user;
//提供了一个构造方法注入user
public UserDaoImpl(User user) {
super();
this.user = user;
}
@Override
public void sayHello() {
System.out.println("你好!" + user.getName() + "。你是" + user.getAge() + "吗?");
}
}
修改配置文件:
<?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">
<!-- 把user实体 装配到spring容器中,并注入值 -->
<bean id="user" class="com.dz.ioc_di.User">
<property name="name" value="dz"></property>
<property name="age" value="23"></property>
</bean>
<!-- 把userDao装配到spring容器中(IoC),并注入对象 -->
<bean id="userDao" class="com.dz.ioc_di.UserDaoImpl">
<!-- 根据name的名称=构造方法里面的参数名称,ref是要引用注入的对象 -->
<constructor-arg name="user" ref="user"></constructor-arg>
</bean>
</beans>
执行结果:

在回过头来看一下测试类里面:
public class Test {
public static void main(String[] args) {
//加载配置文件
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//根据容器里面的id去获取到里面的对象
UserDao userDao = ac.getBean("userDao", UserDao.class);
//调用执行接口的方法
userDao.sayHello();
}
}
加载完Spring容器之后,使用getBean方法根据配置文件里面bean的id去调用,并返回它的接口。到这里就看出,实际上userDao的这个对象与Test类并没有什么关系。它只是通过容器拿到了一个userDao进行使用,并没有在这里面去new 它的实现类,所以他们之间就没有产生依赖的关系。
而在UserDaoImpl里面去注入的一个User对象,也是同样的道理,从容器里面拿到了user对象并且使用它。
这就是IoC的控制反转,对象不交给程序去new了,而是在容器里面拿。至于DI依赖注入也是在容器里面拿出来注入给一个对象。既然都是从容器里面拿出来用,那么IoC和DI是不是一样的?只是他们的说法不同罢了!
我的目录结构

965

被折叠的 条评论
为什么被折叠?



