目录
  1. 1. IOC理论推导
  2. 2. HelloSpring
    1. 2.1. 上面的过程就叫控制反转 :
  3. 3. IOC创建对象的原理(方式)
Spring:IOC本质分析探究

官方文档: https://docs.spring.io/spring/docs/5.2.7.RELEASE/spring-framework-reference/core.html#spring-core

控制反转IOC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IOC的一种方法,也有人认为DI只是IOC的另一种说法。没有IOC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
在这里插入图片描述
  IOC是Spring框架的核心内容,使用多种方式完美的实现了IOC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。

  Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从IOC容器中取出需要的对象。
在这里插入图片描述
  采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。

  控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。


IOC理论推导

搭建项目

  新建Maven项目,pom.xml到导入spring-webmvc依赖(也可称为包,导该依赖的好处就是:idea会默认帮我们导入spring的几个主要包),删除src目录,项目根目录下新建Module,并且选择maven项目(这样就可以在一个项目中,新建多个项目了(Module))

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>

在这里插入图片描述
原来:

  1. UserDao 接口
1
2
3
4
5
6
7
8
9
package com.ling.dao;

/**
* @author 编程之外
* dao接口
*/
public interface UserDao {
void getUser();
}
  1. UserDaoImpl 实现类
1
2
3
4
5
6
7
8
9
10
11
package com.ling.dao;

/**
* @author 编程之外
* dao实现类
*/
public class UserDaoImpl implements UserDao {
public void getUser(){
System.out.println("默认获取用户的数据");
}
}
  1. UserService 业务接口
1
2
3
4
5
6
7
8
9
package com.ling.service;

/**
* @author 编程之外
* service接口
*/
public interface UserService {
void getUser();
}
  1. UserServiceImpl 业务实现类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.ling.service;

import com.ling.dao.UserDao;
import com.ling.dao.UserDaoImpl;

/**
* @author 编程之外
* service 实现类
* service层调到层实现类
*/
public class UserServiceImpl implements UserService {

private UserDao userDao = new UserDaoImpl();

public void getUser() {
userDao.getUser();
}
}

在这里插入图片描述
在之前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求,去修改原代码!如果程序代码量非常大,修改一次的成本代价就十分昂贵!

现在我们使用一个Set接口实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.ling.service;

import com.ling.dao.UserDao;
import com.ling.dao.UserDaoImpl;

/**
* @author 编程之外
* service 实现类
* service层调到层实现类
*/
public class UserServiceImpl implements UserService {

private UserDao userDao;

//利用set进行动态实现值的注入
public void setUserDao(UserDao userDao){
this.userDao=userDao;
}


public void getUser() {
userDao.getUser();
}
}
  • 之前,程序是主动创建对象!控制权在程序员手上
  • 使用了set注入后,程序不再具有主动性,而是变成了被动的接收对象! ==控制反转==

这种思想从本质上解决了问题,我们不用再去管理对象的创建 。系统的耦合性大大降低~,可以更专注的在业务的实现上! 这是IOC的原型!


HelloSpring

1、编写一个HelloSpring实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.ling.pojo;

/**
* @author 编程之外
*/
public class HelloSpring {
private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public void show(){
System.out.println("Hello"+ name );
}

@Override
public String toString() {
return "HelloSpring{" +
"name='" + name + '\'' +
'}';
}
}

2、在resources目录下编写spring配置文件 , 这里命名为beans.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">

<!--使用Spring来创建对象,在spring这些都称为Bean

原来:
类型 变量名 = new 类型();
Hello hello = new Hello();

现在:
bean = 对象 ==》new Hello();
id = 变量名
class = new 的对象;
property 相对于给对象中的name属性设置一个值 -》Spring
-->
<bean id="hello" class="com.ling.pojo.HelloSpring">
<property name="name" value="Spring"/>
</bean>

</beans>

3、进行测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import com.ling.pojo.HelloSpring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
* @author 编程之外
*/
public class TestSpring {
public static void main(String[] args) {

// 获取spring的上下文对象!解析beans.xml文件 , 生成管理相应的Bean对象
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

//我们的对象现在都在spring中的管理了,要使用,直接通过id(这里的hello)去里面取出来就可以了
//getBean : 参数即为spring配置文件中bean的id .
HelloSpring hello = (HelloSpring) context.getBean("hello");

System.out.println(hello.toString());
hello.show();

}
}

结论:

  • HelloSpring 对象是由Spring创建的
  • HelloSpring 对象的属性是由Spring容器设置的

上面的过程就叫控制反转 :

控制 : 谁来控制对象的创建 , 传统应用程序的对象是由程序本身控制创建的 , 使用Spring后 , 对象是由Spring来创建的 .

反转 : 程序本身不创建对象 , 而变成被动的接收对象 .


IOC创建对象的原理(方式)

  1. 使用无参构造新建对象,默认!

  2. 使用有参构造创建对象。

    1. 通过参数 下标赋值
1
2
3
4
<!--通过下标赋值:下标为 0 即有参构造中的第一个参数-->
<bean id="user" class="com.ling.pojo.User">
<constructor-arg index="0" value="编程之外"/>
</bean>
  1. 通过参数类型赋值
    1
    2
    3
    4
    <!--通过参数类型赋值,但如果有两个参数都是String类型,则报错,所以不建议使用该方式-->
    <bean id="user" class="com.ling.pojo.User">
    <constructor-arg type="java.lang.String" value="编程之外"/>
    </bean>
  2. 通过参数名赋值
    1
    2
    3
    4
    <!--通过参数名称赋值,如这里的 name参数 -->
    <bean id="user" class="com.ling.pojo.User">
    <constructor-arg name="name" value="编程之外"/>
    </bean>

总结:在配置文件加载的时候,容器中管理的对象就已经初始化了!


文章作者: 遇见0和1
文章链接: http://vogos.cn/2020/07/02/Spring%EF%BC%9AIOC%E6%9C%AC%E8%B4%A8%E5%88%86%E6%9E%90%E6%8E%A2%E7%A9%B6/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 遇见0和1の个人客栈
打赏
  • 微信赞赏
  • 我的公众号

评论