Spring-01-概述及IOC理论推导

Spring-01-概述及IOC理论推导

1. 简介

mark

  • 2002年,Rod Jahnson首次推出了Spring框架雏形interface21框架。

  • 2004年3月24日,Spring框架以interface21框架为基础,经过重新设计,发布了1.0正式版。

  • 很难想象Rod Johnson的学历 , 他是悉尼大学的博士,然而他的专业不是计算机,而是音乐学。

官网 : http://spring.io/

官方下载地址 : https://repo.spring.io/libs-release-local/org/springframework/spring/

GitHub : https://github.com/spring-projects

重要:

Spring 中文文档地址: https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/overview.html#overview-feedback

Spring 英文文档地址https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans

优点:

  • 控制反转IOC
  • 面向切面编程AOP
  • 对事务的支持,对框架的支持
  • Spring是一个轻量级框架,非侵入式

一句话概括:

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)。

1.1 组成

Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式 .

组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:

  • 核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
  • Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
  • Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向切面的编程功能 , 集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理任何支持 AOP的对象。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖组件,就可以将声明性事务管理集成到应用程序中。
  • Spring DAOJDBC DAO抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
  • Spring ORMSpring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
  • Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
  • Spring MVC 框架MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。

Spring 官网描述

  • Spring 框架分为多个模块。应用程序可以选择所需的模块。
  • 核心容器的模块是核心,包括配置模型和依赖项注入机制
  • 除此之外,Spring 框架为不同的应用程序体系结构提供了基础支持,包括消息传递,事务性数据和持久性以及 Web。它还包括基于 Servlet 的 Spring MVC Web 框架,以及并行的 Spring WebFlux 反应式 Web 框架。

2. IOC理论推导

2.1 推导

考虑如下一种情形:

  1. UserDao.inteface
1
2
3
4
5
package com.zhuuu.dao;

public interface UserDao {
public void getUser();
}
  1. UserDaoImpl.java
1
2
3
4
5
6
7
package com.zhuuu.dao;

public class UserDaoImpl implements UserDao{
public void getUser() {
System.out.println("获取用户数据");
}
}
  1. UserService.inteface
1
2
3
4
5
package com.zhuuu.Service;

public interface UserService {
public void getUser();
}
  1. UserServiceImpl.java
1
2
3
4
5
6
7
8
9
public class UserServiceImpl implements UserService {
// 组合的概念
private UserDao userDao = new UserDaoImpl();

public void getUser() {
// 真正其实是调用dao层
userDao.getUser();
}
}

测试一下:

1
2
3
4
5
6
@Test
public void test(){
// 用户实际调用的是业务层,dao 层他们不需要接触!
UserService service = new UserServiceImpl();
service.getUser();
}

那么现在问题来了,如果用户想添加新的功能,那么我们只能从Service层Impl去修改代码

1
2
3
4
5
6
7
8
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoMySqlImpl();

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

假设如果我们还要新增一个功能的话,如

1
2
3
4
5
6
7
package com.zhuuu.dao;

public class UserDaoOracleImpl implements UserDao {
public void getUser() {
System.out.println("Oracle获取数据");
}
}
  • 那么我们发现了一个很严重的问题,程序的耦合性太高了,牵一发而动全身。
  • 假设我们的这种需求非常大 , 这种方式就根本不适用了

那么我们如何解决呢?

2.2 推导结果

  • 我们可以在需要用到它的地方,不去实现它,而是留出一个接口
  • 通过set方法去引用注入
  1. 修改过的UserServiceImpl.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class UserServiceImpl implements UserService {
// private UserDao userDao = new UserDaoImpl();

/**
* 方式二 :利用接口实现类(set方法)
*/
private UserDao userDao;

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

public void getUser() {
// 真正其实是调用dao层
// 用户实际调用的是业务层,dao 层他们不需要接触!
userDao.getUser();
}
}
  1. 现在通过不一样的的方法去测试
1
2
3
4
5
6
7
8
9
@Test
public void test(){
UserServiceImpl service = new UserServiceImpl();
service.setUserDao( new UserDaoMySqlImpl() );
service.getUser();
//那我们现在又想用Oracle去实现呢
service.setUserDao( new UserDaoOracleImpl() );
service.getUser();
}

注意:这里已经发生了根本性的变化

  • 以前所有的东西都是由程序去进行控制创建
  • 而现在是由用户进行控制创建,把主动权交给了调用者,程序不要用管怎么创建对象。
  • 这种思想 , 从本质上解决了问题 , 我们程序员不再去管理对象的创建了 , 更多的去关注业务的实现 . 耦合性大大降低 . 这也就是IOC的原型 !

2.3 IOC本质

控制反转IOC(Inversion Of Control)

  • 一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法
  • 没有IoC的程序中 , 我们使用面向对象编程,对象的创建与对象间的依赖关系完全在硬编码的程序中
  • 控制反转后将对象的创建交给第三方(可以说是获取依赖对象的方式反转了)

mark

mark

以上就是IOC带来的改变。

同时,在Spring中:

  • IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。

  • Spring容器在初始化的时候先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再去从IOC容器中读取需要的对象。

mark

在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。

mark

打赏
  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2019-2022 Zhuuu
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信