首先明确IOC只是一种思想,而DI依赖注入是实现这种思想的方法。
假如公司要设计一辆车,首先从别的地方拿来一个轮子,然后再根据这个轮子设计出底盘,然后再根据底盘设计出车身,最后根据车身拼装好整个车。就形成了一个依赖关系:

但是如果公司想要换一个更大的轮胎,因为设计的时候是相互依赖的,所以就要根据这个新的轮胎进行全部重做。
而控制反转就是不再相互依赖,而是都依赖接口:
现在公司想设计一辆车,首先设计车的大概样子,然后下面的人根据这个样子来确定车身的标准,然后车身再设计好底盘的标准,最后根据底盘来确定轮子的标准。形成一种约定的关系:


如果要把轮胎的size设置为自定义的,就不需要再修改上层类。


我们可以把它当成一个工厂,这个工厂可以自动对代码进行初始化,我们只需要在Configuration(可能是XML的代码)中配置一下车的参数,让容器自动根据参数进行初始化,就不需要每次在想要车的时候都要初始化一大段代码。
举个例子:我们想要一个车,就在Configuration中写下想要车的参数,然后把这个单子交给容器工厂,然后这个工厂就会给我们一个想要的车,我们就不用关心这个车是怎么造出来的。
在项目中,我们需要向数据库中查询一个数据,只需要在xml文件中配置sql语句,这样容器工厂就会根据这个配置进行初始化,从数据库取出数据返回。

首先创建一个maven项目,在pom.xml文件中导入必要依赖
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-coreartifactId>
<version>5.0.7.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-beansartifactId>
<version>5.0.7.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.0.7.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aopartifactId>
<version>5.0.7.RELEASEversion>
dependency>
dependencies>
接下来创建两个实体类
Teacher.java
public class Teacher {
private String tName;
public String gettName() {
return tName;
}
//必须提供 setter() 方法,因为 Spring 是根据反射机制通过实体类的 setter() 为对象赋值的
public void settName(String tName) {
this.tName = tName;
}
@Override
public String toString() {
return super.toString();
}
}
Student.java
public class Student {
private String sName;
private int age;
private Teacher teacher;
public Student() {
this.sName = "小王";
this.age = 21;
}
//省略setter、getter方法和toString方法
}
在ressources目录下添加Spring配置文件,把②中创建的两个实体类注入到IOC容器中。
spring_config.xml
<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"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation=" http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="teacher" class="entity.Teacher">
<property name="tName" value="AlanShleby"/>
bean>
<bean id="student" class="entity.Student">
<property name="sName" value="Mike"/>
<property name="age" value="22"/>
<property name="teacher" ref="teacher"/>
bean>
beans>
创建启动类
MyBeanFactoryApplication.java
public class MyBeanFactoryApplication {
public static void main(String[] args) {
Student student1 = new Student();
System.out.println(student1);
//通过 ClassPathXmlApplicationContext来读取配置文件xml
ApplicationContext factory = new ClassPathXmlApplicationContext("spring_config.xml");
//然后就可以看到工厂创建好的实例对象
Student student = (Student) factory.getBean("student");
System.out.println(student);
}
}
输出结果
因为在xml中配置了新值,因此输出不同

首先将上一步添加的依赖以及xml文件注释掉,开始手写
定义Bean实体,对应XML文件中的 标签
Bean.java
public class Bean {
private String beanId;
//注入的文件路径
private String classPath;
//省略setter、getter方法
}
创建Bean工厂,类似于ApplicationContext
BeanFactory.java
public class BeanFactory {
//使用List存放Bean集合
private List<Bean> beanList;
public List<Bean> getBeanList() {
return beanList;
}
public void setBeanList(List<Bean> beanList) {
this.beanList = beanList;
}
/**
* @Description: //TODO 获取Bean实例
* @Author: wyq
* @Date 2022/9/3 22:06
*/
public Object getBean(String beanId) throws Exception {
Object instance;
for (Bean bean : beanList) {
if (beanId.equals(bean.getBeanId())) {
String classPath = bean.getClassPath();
//要求JVM查找并加载指定路径的类
Class classFile = Class.forName(classPath);
//调用 newInstance() 默认的构造方法进行实例化,返回一个实例化好的对象
instance = classFile.newInstance();
return instance;
}
}
return null;
}
}
修改启动类
public class MyBeanFactoryApplication {
public static void main(String[] args) throws Exception {
Student student1 = new Student();
System.out.println(student1);
//声明Bean对象,类似xml功能
Bean bean=new Bean();
bean.setBeanId("student");
bean.setClassPath("entity.Student");
List<Bean> beanList=new ArrayList<Bean>();
beanList.add(bean);
//向工厂传入配置文件,类似于ApplicationContext
BeanFactory factory=new BeanFactory();
factory.setBeanList(beanList);
//查看工厂创建好的实例对象
Student student=(Student) factory.getBean("student");
System.out.println(student);
}
}
输出结果
工厂没有接收到赋值的请求,默认使用空参的构造方法
