初学spring——Spring内核之IoC/DI(控制反转/依赖注入)

什么是IoC/DI?

它的全称是:Inversion of Control/Dependency InJect,翻译过来就是控制反转/依赖注入。IoC是spring的基础,它实现一种控制反转的功能。说白了就是把对象的控制权交给了Spring而不再由应用程序来创建。DI与IoC的功能相同,因为他们的主语都是Spring,只不过是换了一个说法来表述同一件事情,它实现的是依赖注入,因为它已经被赋予了相关的值,直接使用就OK。

搭建Spring环境

下面先看一下Spring基础包的说明:

包名描述
spring-core-xxx-x.jarSpring框架的核心工具类 ,Spring的其他组件都要使用这个包
spring-beans-xxx-x.jarSpring所有的应用都需要用到的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是不是一样的?只是他们的说法不同罢了!

我的目录结构

目录结构

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白说(๑• . •๑)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值