【Spring】OCP,DIP原则,IoC思想和依赖注入DI重点知识汇总

简介: 【Spring】OCP,DIP原则,IoC思想和依赖注入DI重点知识汇总

1. Spring启示录:

1.1 OCP原则:

  • 什么是OCP?
  • OCP是软件七大开发原则的最基本原则: 开闭原则
  • 对什么开? 对扩展开放
  • 对什么闭? 对修改关闭
  • OCP原则是最核心的最基本的, 其他的六个原则都是为这个原则服务的
  • OCP开闭原则的核心是什么?
  • 只要你在扩展功能的时候, 没有修改以前写好的代码, 那么你就是符合OCP原则的
  • 反之, 如果在扩展系统功能的时候, 修改了之前的代码, 那么这个设计就是失败的, 违背了OCP原则.
  • 当进行系统功能扩展的时候, 如果动了之前稳定的程序, 修改了之前的程序, 之前所有的程序都需要程序进行测试, 这是非常麻烦的.

1.2 依赖倒置原则(DIP原则):

  • 什么是依赖倒置原则?
  • 面向接口编程, 面向抽象编程, 不要面向具体编程
  • 依赖倒置原则的目的?
  • 降低程序的耦合度, 提高扩展力
  • 什么叫符合依赖倒置?
  • 上(业务层的代码) 不依赖 下(持久层的代码), 就是符合依赖倒置
  • 什么叫不违背依赖倒置?
  • 上 依赖 下, 就是违背
  • 只要 下 代码一改动, 上 就受到牵连
// 业务层
public class UserServiceImpl implements UserService {
    // 修改之前: 违背了依赖倒置原则
  private UserDao userDao = new UserDaoImplForMySQL();
    // 修改之后: 不违背了,但是如果不new的话, userDao=null
    private UserDao userDao; // 直接写个接口
    @Override
    public void deleteUser(){
        // null调用方法就会空指针异常
        userDao.deleteById();
    }
}

1.3 控制反转IoC思想:

  • 当前的程序设计, 显然违背了OCP又违背了DIP, 怎么办?
  • 可以采用"控制反转"这种编程思想来解决问题
  • 什么是控制反转?
  • 控制反转: IoC (Inversion of Control)
  • 反转是什么呢?
  • 反转的是俩件事
  • 第一件事: 我不在程序中采用硬编码的方式来new对象了 (new对象的权利交出去了)
  • 第二件事: 我不在程序中采用硬编码的方式来维护对象的关系了 (对象之间的维护全交出去了), 例如下面代码:
// 业务层
public class UserServiceImpl implements UserService {
     // 到底是UserDaoImplForMySQL还是UserDaoImplForOracle
     //   和UserServiceImpl产生关系, 我不管了
    private UserDao userDao = new UserDaoImplForMySQL();   
    private UserDao userDao = new UserDaoImplForOracle();
    @Override
    public void deleteUser(){   
        userDao.deleteById();
    }
}
  • 控制反转: 是一种编程思想, 或者叫做一种新型的设计模式, 由于出现的比较新, 没有被纳入到GoF23中设计模式的范围内.
  • 控制反转的作用: 让程序符合OCP原则又符合DIP原则

1.4 依赖注入DI:

  • Spring框架实现了控制反转IoC这种思想
  • Spring框架可以帮你new对象
  • Spring框架可以帮你维护对象和对象之间的关系
  • Spring是一种实现了IoC思想的容器
  • 控制反转的实现方式有很多, 其中比较重要的叫做: 依赖注入(Dependency Injection, 简称DI)
  • 控制反转是思想, 依赖注入是这种思想的具体实现
  • 依赖注入DI, 又包括常见的俩种方式:
  • 第一种, set注入 (执行set方法给属性赋值)
  • 第二种, 构造方法注入 (执行构造方法给属性赋值)
public class UserServiceImpl implements UserService{
    private UserDao userDao;
    // set注入
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    // 构造方法注入
    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }
    @Override
    public void deleteUser() {
        userDao.deleteById();
    }
}
  • 依赖注入中, "依赖"是什么意思? "注入"是什么意思?
  • 依赖: 对象和对象之间的关联关系(A对象中有B, B对象中有C)
  • 注入: 是一种手段, 通过这种手段, 可以让A对象和B对象产生关系
  • 依赖注入: 对象A和对象B之间的关系, 靠注入的手段来维护, 而注入包括: set注入和构造注入
  • Spring通过依赖注入的方式来完成Bean管理
  • Bean管理说的是:
  • Bean对象的创建
  • Bean对象中属性的赋值(或者叫做Bean对象之间关系的维护)

2. Spring概述:

  • Spring是一个轻量级的控制反转IoC和面向切面AOP的容器框架
  • Spring最初的出现是为了解决EJB臃肿的设计, 以及难以测试等问题
  • Spring为简化而生, 让程序员只需关注核心业务的实现, 尽可能的不再关注非业务逻辑代码(事务控制,安全日志等)
  • Spring把创建好的对象存储到一个什么样的数据结构中呢?
  • Map

  • 在配置文件中配置的类必须是自定义的吗? 可以使用JDK中的类, 例如: java.util.Date?
1. // xml
2. <bean id="dateBean" class="java.util.Date"/> // 不是

3. 第一个spring程序:

  • Spring是怎么实例化对象的?
  • 默认情况下, spring通过反射机制, 调用类的无参构造方法来实例化对象, 实现原理如下:
  • class clazz = Class.forName("com.powernode.bean.User");
  • Object obj = clazz.newInstance();
  • ApplicationContext接口的超级父接口是: BeanFactory (翻译为Bean工厂, 就是能够生产Bean对象的一个工厂对象)
  • BeanFactory是IoC容器的顶级接口
  • Spring的IoC容器底层实际上使用了工厂模式
  • Spring底层的IoC是怎么实现的?
  • XML解析 + 工厂模式 + 反射机制
  • ApplicationContext是BeanFactory的子类, 为什么使用ApplicationContext?
  • 因为它方法更多, 功能更丰富
// xml
    <!-- 配置bean, 这样spring才可以帮助我们管理这个对象   -->
    <!-- bean标签的俩个重要属性:
                id: 是这个bean的身份证号, 不能重复, 是唯一标识
                class: 必须填写类的全路径, 全限定类名(带包名的类名)
    -->
    <bean id="userBean" class="com.powernode.bean.User"/>
// @Test
public void testFirstSpringCode() {
    // 第一步: 获取Spring容器
    // ApplicationContext 翻译为: 应用上下文, 其实就是Spring容器
    // ApplicationContext 是一个接口
    // ApplicationContext 接口下有很多实现类, 其中一个就是ClassPathXmlApplicationContext
    // ClassPathXmlApplicationContext 专门从类路径当中加载spring配置文件的一个spring上下文对象
    // 这行代码只要执行, 就相当于启动了spring容器, 解析spring.xml文件, 并且实例化所有的bean对象, 放到bean容器当中
    ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
  // 下面的代码也没问题:
    BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring.xml");
    // 第二步: 根据bean的id从spring容器中获取这个对象
    // 如果id不存在, 不会返回null, 会报错
    Object userBean = ctx.getBean("userBean");
    // 不想强制类型转换, 可以使用下面的代码: (通过第二个参数, 指定返回的bean的类型)
    User userBean1 = ctx.getBean("userBean", User.class);
    System.out.println(userBean);
}
  • 注意不是在调用getBean()方法的时候创建对象, 执行以下代码的时候, 就会实例化对象, 调用无参构造
// @Test
public void testBeginInitbean(){
    // 注意不是在调用getBean()方法的时候创建对象, 执行以下代码的时候, 就会实例化对象
    new ClassPathXmlApplicationContext("spring.xml");
}


相关文章
|
9天前
|
XML 缓存 Java
搞透 IOC、Spring IOC ,看这篇就够了!
本文详细解析了Spring框架的核心内容——IOC(控制反转)及其依赖注入(DI)的实现原理,帮助读者理解如何通过IOC实现组件解耦,提高程序的灵活性和可维护性。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
|
1月前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
【10月更文挑战第1天】Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
117 9
|
1月前
|
存储 Java 程序员
SpringIOC和DI的代码实现,Spring如何存取对象?@Controller、@Service、@Repository、@Component、@Configuration、@Bean DI详解
本文详细讲解了Spring框架中IOC容器如何存储和取出Bean对象,包括五大类注解(@Controller、@Service、@Repository、@Component、@Configuration)和方法注解@Bean的用法,以及DI(依赖注入)的三种注入方式:属性注入、构造方法注入和Setter注入,并分析了它们的优缺点。
22 0
SpringIOC和DI的代码实现,Spring如何存取对象?@Controller、@Service、@Repository、@Component、@Configuration、@Bean DI详解
|
1月前
|
存储 开发框架 Java
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
文章详细介绍了Spring、IOC、DI的概念和关系,解释了控制反转(IOC)和依赖注入(DI)的原理,并提供了IOC的代码示例,阐述了Spring框架作为IOC容器的应用。
25 0
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
|
2月前
|
缓存 Java Spring
手写Spring Ioc 循环依赖底层源码剖析
在Spring框架中,IoC(控制反转)是一个核心特性,它通过依赖注入(DI)实现了对象间的解耦。然而,在实际开发中,循环依赖是一个常见的问题。
38 4
|
21天前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
49 0
|
29天前
|
XML Java 数据格式
Spring的IOC和AOP
Spring的IOC和AOP
43 0
|
2月前
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
|
27天前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
139 2
|
3月前
|
缓存 Java Maven
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决