当前位置: 首页 > news >正文

【Spring框架】Spring核心思想IoC以及依赖注入DI详解

目录

  • Spring框架
    • 前言 服务端三层开发
      • 表现层
      • 业务层
      • 持久层
    • Spring框架的概述
    • Spring框架的优点
    • Spring核心——IoC
      • 什么是IoC?O.o
      • 什么是耦合度?
    • 创建第一个IoC程序
      • 导入必要依赖
      • 编写接口和实现类
      • 编写Spring核心配置文件
      • 测试类进行测试
    • Spring配置文件
      • Bean对象的创建和销毁的两个属性配置
    • 实例化Bean对象的三种方式
    • DI依赖注入
      • 属性的set方法注入值
      • 属性构造方法方式注入值
      • 数组,集合(List,Set,Map),Properties等的注入
    • 多配置文件的加载方式
      • 主配置文件中直接添加
      • 工厂创建的时候直接加载多个配置文件

Spring框架

前言 服务端三层开发

表现层

表现层负责处理用户界面和用户交互。它接收用户的请求,进行初步处理后转发给业务层,并将业务层返回的数据呈现给用户。常见的表现层技术包括 Web 框架(如 Spring MVC、Struts)、前端框架(如 React、Vue.js)等。

  • Servlet
  • SpringMVC
  • Struts

业务层

业务层是系统的逻辑核心,负责处理业务规则和业务流程。它接收来自表现层的请求,调用持久层进行数据操作,并返回处理结果给表现层。业务层通常包含服务类和服务接口,实现复杂的业务逻辑和事务管理。常见的业务层技术包括 Spring、Hibernate 等。

  • service
  • Spring

持久层

持久层负责数据的存储和检索,主要与数据库进行交互。它提供了数据访问对象(DAO)或仓库(Repository)来封装数据访问逻辑,确保数据的一致性和完整性。持久层通常使用 ORM(对象关系映射)框架(如 Hibernate、MyBatis)来简化数据库操作。

  • JDBC
  • MyBatis
  • JDBC Template

Spring框架的概述

Spring是一个开放源代码的设计层面框架,它解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。Spring是于2003年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。

Spring是于2003 年兴起的一个轻量级的Java开发框架,由Rod Johnson在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。

它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。

Spring的核心是控制反转(IoC控制反转)和面向切面(AOP)。简单来说,Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开源框架。

Spring框架的优点

  1. 方便解耦,简化开发,Spring就是一个大工厂,可以将所有对象创建和依赖关系维护,交给Spring管理。

  2. AOP编程的支持,Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能。(可扩展性)

  3. 声明式事务的支持,只需要通过配置就可以完成对事务的管理,而无需手动编程。

  4. 方便程序的测试,Spring对Junit4支持,可以通过注解方便的测试Spring程序。

  5. 方便集成各种优秀框架,Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts2、Hibernate、MyBatis、Quartz等)的直接支持。

  6. 降低JavaEE API的使用难度,Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低。

Spring核心——IoC

什么是IoC?O.o

IOC——Inverse of Control,控制反转,将对象的创建权力反转给Spring框架!!

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。如下图(来自百度百科)

img

那么涉及到第二个问题:

什么是耦合度?

可以看看这篇文章:聊聊什么是耦合度-CSDN博客,简而言之就是各个对象或者类或者是模块之间的依赖程度,然而我们并不希望我们的程序是一个高耦合度的程序,因为这样各个模块之间紧密相连,会导致可扩展性、可维护性变差。

我们希望我们的程序是低耦合高内聚的程序,也就是模块内部的元素依赖关系紧密,而模块之间并不存在很紧密的依赖关系,高内聚度的模块会使得代码更加清晰、易于理解和维护,同时可以提高代码的复用性。

创建第一个IoC程序

这里还是说一下我用到的工具:

  • IDE:IntelliJ IDEA 2024.2.3
  • Maven:3.9.8

导入必要依赖

<dependencies><!-- Spring核心 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.2.RELEASE</version></dependency><!-- 日志接口 --><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency><!-- 日志核心 --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.12</version></dependency><!-- JUnit测试 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency>
</dependencies>

编写接口和实现类

// 接口类
public interface UserService {public void hello();
}// 实现类
public class UserServiceImpl implements UserService {@Overridepublic void hello() {System.out.println("Hello IOC!!!");}
}

编写Spring核心配置文件

在src目录下创建applicationContext.xml的配置文件,名称是可以任意的,但是一般都会使用默认名称。我们通过这个配置文件来实现我们IoC的核心操作:

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!--IOC管理bean--><!--一个bean相当于一个对象bean的意义是将该类的创建对象的权利授予spring容器,让spring容器来创建对象,--><bean id="userService" class="com.qcby.service.Impl.UserServiceImpl" />
</beans>

前面我们提到,Spring设计核心就是IoC,这里配置文件中就是在由我们的IoC容器创建对象,我们将由IoC容器管理的Java对象称为Spring Bean,我们可以在编译器的对应的类文件中看到一个小咖啡豆的标志

在这里插入图片描述

测试类进行测试

下面我们写一个最简单的测试方法来测试我们写好的UserServiceImpl实现类:

    @Testpublic void run1(){// 使用Spring的工厂ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");// 通过工厂获得类:UserService userService = (UserService) applicationContext.getBean("userService");userService.hello();}

输出结果:

在这里插入图片描述

这里简单穿插一条题外话:Spring的默认设计模式是单例模式——单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点。感兴趣的可以看看这篇文章:一文带你彻底搞懂设计模式之单例模式!!由浅入深,图文并茂,超超超详细的单例模式讲解!!-CSDN博客,介绍的很详细不再过多介绍。

Spring配置文件

  • id属性:Bean起个名字,在约束中采用ID的约束,唯一,取值要求:必须以字母开始,可以使用字母、数字、连字符、下划线、句话、冒号 id:不能出现特殊字符。

  • class属性:Bean对象的全路径。

  • scope属性:scope属性代表Bean的作用范围,其中的属性值如下:

    取值范围说明
    singleton默认值,单例模式
    prototype多例模式
    requestWEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中
    sessionWEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中
    global sessionWEB 项目中,应用在 Portlet 环境,如果没有 Portlet 环境那么globalSession 相当于 session

Bean对象的创建和销毁的两个属性配置

说明:Spring初始化bean或销毁bean时,有时需要作一些处理工作,因此spring可以在创建和拆卸bean的时候调用bean的两个生命周期方法

  • init-method标签:当bean被载入到容器的时候调用init-method属性指定的方法

  • destroy-method标签:当bean从容器中删除的时候调用destroy-method属性指定的方法

实例化Bean对象的三种方式

  1. 默认是无参数的构造方法(默认方式,基本上使用)

    <bean id="userService" class="com.qcby.service.Impl.UserServiceImpl" />
    
  2. 静态工厂实例化方式

    /*** 静态工厂方式*/
    public class StaticFactory {// 静态工厂方式public static UserService createUs(){System.out.println("通过静态工厂的方式创建UserServiceImpl对象...");// 编写很多业务逻辑 权限校验return new UserServiceImpl();}}<bean id="us" class="com.qcby.demo1.StaticFactory" factory-method="createUs" />  
    
  3. 实例工厂实例化方式,因为类中的方法非静态,所以需要先实例化类,再去创建对象,因此得名(说实话这个一开始还真没注意到)

    /*** 动态工厂方式*/
    public class Dfactory {public UserService createUs(){System.out.println("实例化工厂的方式...");return new UserServiceImpl();}}<bean id="dfactory" class="cn.tx.demo1.Dfactory" />
    <bean id="us" factory-bean="dfactory" factory-method="createUs" />
    

DI依赖注入

依赖注入(Dependency Injection)是在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件中!!这么说可能有点难懂,可以理解为:你的类中有很多属性,比如name、age等,我们需要给这些属性赋值,但是我们又不想通过调用构造器或者是调用setter()方法去赋值,这时我们就可以用DI,来给这些属性赋值,或者是创建依赖对象。

**依赖注入是实现控制反转的一种常见方式。**目的是处理依赖于对象的关系

属性的set方法注入值

编写实现类,其中包括要实现的对象或属性,最后通过配置文件调用setter()方法进行注入:

// 实现类
public class OrderServiceImpl implements OrderService {// 编写成员属性,一定需要提供该属性的set方法private OrderDao orderDao;// 一定需要提供该属性的set方法,IOC容器底层就通过属性的set方法方式注入值public void setOrderDao(OrderDao orderDao) {this.orderDao = orderDao;}private String name;private Integer age;public void setName(String name) {this.name = name;}public void setAge(Integer age) {this.age = age;}@Overridepublic void saveOrder() {System.out.println("业务层,保存订单,姓名:" + name + "-年龄:" + age);orderDao.saveOrder();}
}public class OrderDaoImpl implements OrderDao {@Overridepublic void saveOrder() {System.out.println("持久层:保存订单...");}}

编写配置文件:

<!--DI:依赖注入-->
<bean id="orderService" class="com.qcby.service.Impl.OrderServiceImpl"><!-- 将实例化的对象注入到orderDao --><property name="orderDao" ref="orderDao" /><property name="name" value="Ray" /><property name="age" value="23" />
</bean>
<!-- 这里先将OrderDaoImpl实例化,再注入到orderService中 -->
<bean id="orderDao" class="com.qcby.DAO.Impl.OrderDaoImpl"/>

<bean id="orderDao" class="com.qcby.DAO.Impl.OrderDaoImpl"/>这条语句其实就是创建对象,并在<property name="orderDao" ref="orderDao" />这里将对象用orderDao接口接收

编写测试方法:

@Test
public void run2(){// 使用Spring的工厂ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");// 通过工厂获得类:OrderService orderService = (OrderService) applicationContext.getBean("orderService");orderService.saveOrder();
}

在这里插入图片描述

属性构造方法方式注入值

编写类以及对应的带参的构造方法

public class Car {// 名称private String cname;// 金额private Double cmoney;public Car(String cname, Double cmoney) {this.cname = cname;this.cmoney = cmoney;}@Overridepublic String toString() {return "Car{" +"cname='" + cname + '\'' +", cmoney=" + cmoney +'}';}
}

编写配置文件,注入属性值:

<bean id="car" class="com.qcby.Demo.Car"><constructor-arg name="cname" value="Porsche"/><constructor-arg name="cmoney" value="40000000" />
</bean>

测试:

@Test
public void run3(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");Car car = (Car) applicationContext.getBean("car");System.out.println(car.toString());
}

在这里插入图片描述

数组,集合(List,Set,Map),Properties等的注入

编写实现类,实现对应属性:

public class CollectionBean {// 数组private String [] strs;public void setStrs(String[] strs) {this.strs = strs;}private List<String> list;public void setList(List<String> list) {this.list = list;}private Map<String,String> map;public void setMap(Map<String, String> map) {this.map = map;}private Properties properties;public void setProperties(Properties properties) {this.properties = properties;}@Overridepublic String toString() {return "CollectionBean{" +"strs=" + Arrays.toString(strs) +", list=" + list +", map=" + map +", properties=" + properties +'}';}
}

编写配置文件,注入值:

<!--给集合属性注入值-->
<bean id="collectionBean" class="com.qcby.Demo.CollectionBean"><property name="strs"><array><value>美美</value><value>小凤</value></array></property><property name="list"><list><value>熊大</value><value>熊二</value></list></property><property name="map"><map><entry key="aaa" value="老王"/><entry key="bbb" value="小王"/></map></property><property name="properties"><props><prop key="username">root</prop><prop key="password">123456</prop></props></property>
</bean>

编写测试方法:

@Test
public void run4(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");CollectionBean collectionBean = (CollectionBean) applicationContext.getBean("collectionBean");System.out.println(collectionBean.toString());
}

在这里插入图片描述

多配置文件的加载方式

一共两种方式:

主配置文件中直接添加

<import resource="applicationContext2.xml"/>

工厂创建的时候直接加载多个配置文件

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml","applicationContext2.xml");
http://www.lryc.cn/news/468040.html

相关文章:

  • Java项目-基于springboot框架的智慧外贸系统项目实战(附源码+文档)
  • Python程序控制结构 if语句详解
  • 【ppq install】
  • 3DGS相关方法conda环境配置
  • python画图|曲线动态输出
  • 电子商务类型
  • vue elementui el-table实现增加行,行内编辑修改
  • 1. Redis简介与安装
  • Redis的持久化存储和集群管理操作
  • Auto-encoder(自编码器)
  • Vue+sortable+el-table表格排序使用指南
  • 表数据删一半,为什么表文件大小不变?
  • MoCoOp: Mixture of Prompt Learning for Vision Language Models
  • YOLOv8 onnx 部署
  • 在文件里引用目录文件下的静态资源图片不显示
  • vue使用 jsplumb 生成流程图
  • 攻坚金融关键业务系统,OceanBase亮相2024金融科技大会
  • 《纳瓦尔宝典:财富和幸福指南》读书随笔
  • C++ | STL | 侯捷 | 学习笔记
  • C函数基础
  • html和css实现页面
  • Github_以太网开源项目verilog-ethernet代码阅读与移植(八)——移植工程分享
  • 【大模型实战篇】大模型分词算法BPE(Byte-Pair Encoding tokenization)及代码示例
  • 低功耗4G模组LCD应用示例超全教程!不会的小伙伴看这篇就够了!
  • Java while语句练习 C语言的函数递归
  • illustrator免费插件 截图识别文字插件 textOCR
  • 提升数据管理效率:ETLCloud与达梦数据库的完美集成
  • 头歌——人工智能(搜索策略)
  • gorm.io/sharding改造:赋能单表,灵活支持多分表策略(下)
  • 域渗透AD渗透攻击利用 MS14-068漏洞利用过程 以及域渗透中票据是什么 如何利用