Spring框架【IOC详解】

news2025/1/23 9:27:21

目录

一、前言

1.1.Spring简介

1.2.使用Spring的优点

1.3.Spring组成

二、Spring之IOC详解

2.1.IOC理论推导

2.1.1.IOC分析实现

2.1.2.IOC本质

2.2.Maven项目导入Jar包

2.3.依赖注入

2.3.1.Set注入(重点)

2.3.2.构造注入

无参构造创建对象

有参构造创建对象

2.4.自动装配

byName(按名称自动装配)

byType (按类型自动装配)

2.5.spring与web容器的整合


 

一、前言

1.1.Spring简介

Spring翻译过来就是春天的意思,它的出现也是给广大程序员带来了春天🍃。

Spring框架最初由Rod Johnson创建,他于2002年写了一本名为《Expert One-on-One J2EE Design and Development》的书,书中详细介绍了一些与J2EE技术有关的设计模式和最佳实

践。该书的成功激发了Rod Johnson继续探索J2EE开发的方法,最终他开发了Spring框架。

2004年,Spring框架发布了第一个正式版本1.0,这个版本包括IoC容器、AOP、数据访问等核心特性。

Spring官网icon-default.png?t=N6B9http:// http://spring.io/Spring官方下载地址icon-default.png?t=N6B9https://repo.spring.io/libs-release-local/org/springframework/spring/

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.0.RELEASE</version>
</dependency>

1.2.使用Spring的优点

Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。
   Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。
   然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。
   目的:解决企业应用开发的复杂性
   功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
   范围:任何Java应用
   简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。

1.3.Spring组成

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 DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
  • Spring ORM:Spring 框架插入了若干个 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之IOC详解

2.1.IOC理论推导

我们先新建一个Maven项目来进行我们的IOC理论推导

2.1.1.IOC分析实现

给客户添加一个文件上传的接口,实现文件上传的功能

1.建立一个UserService接口

public interface UserService {

 public void update();

}

2.实现接口完成功能

public class UserServiceImpl implements UserService {

    public void update() {
        System.out.println("V1.0:程序员实现功能完写的实现类");
    }
    
}

3.客户要求更改需求

public class UserServiceImpl2 implements UserService {

    public void update() {
            System.out.println("V2.0:解决客户投诉问题,更改需求");
    }

}

4.编写Userservlet

public class UserAction {
    private UserService userService= new UserServiceImpl2();
    public String Update(){
        userService.update();
        return "list";
    }
}

在公司很多时候客户在上午提的需求,你做完了下午就不要了,那你只能修改UserServlet的接口实现把2变为1,一个类修改起来容易,10..50..100..这种方式就根本不适用, 甚至反人类 , 每次变动 , 都需要修改大量代码 . 这种设计的耦合性太高了, 牵一发而动全身 。

如果使用Spring, 以前所有东西都是由程序去进行控制创建 , 而现在是由我们自行控制创建对象 , 把主动权交给了调用者 。 程序不用去管怎么创建,怎么实现,它只负责提供一个接口 。

2.1.2.IOC本质

控制反转IOC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IOC的一种方法,也有人认为DI只是IOC的另一种说法。没有IOC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了

耦合对象:

 解耦对象:

理想系统:

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

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

 

采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。

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

2.2.Maven项目导入Jar包

spring 需要导入commons-logging进行日志记录 , 我们利用maven ,他会自动下载对应的依赖项 

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-webmvc</artifactId>
   <version>5.1.10.RELEASE</version>
</dependency>

2.3.依赖注入

2.3.1.Set注入(重点)

userAction.java

public class UserAction {
    private UserService userService;
    private String name;
    private String[] books;
    private List<String> hobbys;
    private Map<String,String> card;
    private Set<String> games;

    public Map<String, String> getCard() {
        return card;
    }

    public void setCard(Map<String, String> card) {
        this.card = card;
    }

    public Set<String> getGames() {
        return games;
    }

    public void setGames(Set<String> games) {
        this.games = games;
    }

    public String[] getBooks() {
        return books;
    }

    public void setBooks(String[] books) {
        this.books = books;
    }

    public List<String> getHobbys() {
        return hobbys;
    }

    public void setHobbys(List<String> hobbys) {
        this.hobbys = hobbys;
    }

    public String getName() {
        return name;
    }

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

    public UserService getUserService() {
        return userService;
    }

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public String Update(){
        userService.update();
        System.out.println("名字:"+name);
        System.out.println("书籍:");
        for (String book:books){
            System.out.print("<<"+book+">>\t\n");
        }
        System.out.println("爱好:"+hobbys);
        System.out.println("card:"+card);
        System.out.println("games:"+games);
        return "list";
    }


}
GoodsAction.java
public class GoodsAction {
    private UserService userService;

    public UserService getUserService() {
        return userService;
    }

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public String Update(){
        userService.update();
        return "list";
    }
}

Test测试类

public class UserTest {
    public static void main(String[] args) {
        //加载spring核心配置文件(建模)获取spring的上下文对象
        //上下文对象中可以获取任何Javabean对象
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("/Spring-Context.xml");

        //用户
        UserAction useraction = (UserAction) context.getBean("userAction");
        useraction.Update();
        System.out.println("  ===============================");
        //商品
        GoodsAction goodsAction= (GoodsAction) context.getBean("goodsAction");
        goodsAction.Update();

    }

1.Bean注入

这里的值是一个引用,ref

 <bean class="com.csdn.xw.web.UserAction" id="userAction">
        <property name="userService" ref="serviceImpl2"></property>
        <property name="name" value="小明"></property>
 </bean>

  <bean class="com.csdn.xw.service.impl.UserServiceImpl2" id="serviceImpl2"></bean>

2.数组注入

<property name="books" >
            <array>
                <value>西游记</value>
                <value>红楼梦</value>
                <value>水浒传</value>
                <value>三国演义</value>
            </array>
</property>

3.List注入

 <property name="hobbys">
            <list>
                <value>唱</value>
                <value>跳</value>
                <value>RAP</value>
            </list>
 </property>

4.Map注入

 <property name="card">
            <map>
                <entry key="JAVA" value="100"></entry>
                <entry key="Python" value="100"></entry>
            </map>
 </property>

5.Set注入

 <property name="games">
            <set>
                <value>电脑</value>
                <value>鼠标</value>
            </set>
 </property>

测试结果:

2.3.2.构造注入

无参构造创建对象

userAction.java

public class UserAction {
    public UserAction() {
        System.out.println("user创建了");
 
    }
}

spring-context.xml

<bean class="com.csdn.xw.web.UserAction" id="UserAction"></bean>

测试结果:

 

有参构造创建对象

userAction.java

  
public class UserAction {
    private String name;
    private String[] books;
    private List<String> hobbys;
    private Map<String,String> card;
    private Set<String> games;

    //有参构造器
    public UserAction(String name, String[] books, List<String> hobbys, Map<String, String>                     card, Set<String> games) {
        this.name = name;
        this.books = books;
        this.hobbys = hobbys;
        this.card = card;
        this.games = games;
    }

    /测试有无注入
     public void pros(){
        System.out.println("名字:"+name);
        System.out.println("书籍:");
        for (String book:books){
            System.out.print("<<"+book+">>\t\n");
        }
        System.out.println("爱好:"+hobbys);
        System.out.println("card:"+card);
        System.out.println("games:"+games);
    }
}

spring-context.xml

    <bean class="com.csdn.xw.web.UserAction" id="userAction">
        <property name="userService" ref="serviceImpl2"></property>
        <constructor-arg name="name" value="张三"></constructor-arg>
        <constructor-arg name="books">
            <array>
                <value>大话数据结构</value>
                <value>大话设计模式</value>
            </array>
        </constructor-arg>
        <constructor-arg name="hobbys">
            <list>
                <value>沐浴</value>
                <value>足疗</value>
                <value>按摩</value>
            </list>
        </constructor-arg>
        <constructor-arg name="card">
            <map>
                <entry key="csdn" value="nb"></entry>
            </map>
        </constructor-arg>
        <constructor-arg name="games">
            <set>
                <value>Java方文山</value>
            </set>
        </constructor-arg>
    </bean>

测试结果:

 

2.4.自动装配

byName(按名称自动装配)

由于在手动配置xml过程中,常常发生字母缺漏和大小写等错误,而无法对其进行检查,使得开发效率降低。采用自动装配将避免这些错误,并且使配置简单化。

测试:

1、修改bean配置,增加一个属性 autowire=“byName”

 <bean class="com.csdn.xw.web.GoodsAction" id="goodsActiona" autowire="byName">
        <property name="userService" ref="serviceImpl1"></property>
 </bean>
<beans xmlns="http://www.springframework.org/schema/beans"
       default-autowire="byName"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

2、再次测试,结果依旧成功输出!

3、我们将 GoodsAction的bean id修改为 goodsACtion

4、再次测试, 执行时报空指针java.lang.NullPointerException。因为按byName规则找不对应set方法,真正的setgoodsAction就没执行,对象就没有初始化,所以调用时就会报空指针错误。

小结:

当一个bean节点带有 autowire byName的属性时

或是beans节点带有 default-autowire="byName"。

  1. 将查找其类中所有的set方法名,例如setCat,获得将set去掉并且首字母小写的字符串,即cat。

  2. 去spring容器中寻找是否有此字符串名称id的对象。

  3. 如果有,就取出注入;如果没有,就报空指针异常。

byType (按类型自动装配)

使用autowire byType首先需要保证:同一类型的对象,在spring容器中唯一。如果不唯一,会报不唯一的异常。

NoUniqueBeanDefinitionException

测试:

1、将user的bean配置修改一下 : autowire=“byType”

2、测试,正常输出

3、在注册一个goodsAction的bean对象!

<bean class="com.csdn.xw.web.GoodsAction" id="goodsAction" autowire="byType">
</bean>

<bean class="com.csdn.xw.web.UserAction" id="userAction" autowire="byType">
        <property name="userService" ref="serviceImpl2"></property>
</bean>

<bean class="com.csdn.xw.service.impl.UserServiceImpl2" id="serviceImpl2"></bean>
<bean class="com.csdn.xw.service.impl.UserServiceImpl1" id="serviceImpl1"></bean>

4、测试,报错:NoUniqueBeanDefinitionException

5、在这个配置中,我们定义了两个UserService的实现类 UserServiceImpl1和 UserServiceImpl2,并且将UserAction的autowire属性设置为byType,表示使用byType进行自动装配。

现在,如果我们运行这个程序,将会抛出一个异常,提示存在多个匹配的 bean,无法确定要注入哪个 bean。这是因为 UserAction类依赖于UserService接口,而容器中存在两个与 UserService接口匹配的 bean,即 UserServiceImpl1和 UserServiceImpl2,导致无法确定要注入哪个 bean。

这就是按照类型自动装配!

2.5.spring与web容器的整合

每一次的请求都需要进行建模,十分消耗新能,希望建模一次,然后每次的请求都可以拿到spring的上下文。使用监听器将spring上下文放入tomcat上下文中。

SpringLoadlistener.java

@WebListener
public class SpringLoadlistener implements ServletContextListener {
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("初始化将Spring的上下文放入tomcat");
        //将Spring的上下文放入tomcat
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("/Spring-Context.xml");
        //获取tomcat上下文
        ServletContext servletContext = sce.getServletContext();
        servletContext.setAttribute("springcontext",context);
    }
}

UserServlet.java

@WebServlet("/userlist")
public class UserServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //处理请求的时候获取spring上下文
        ClassPathXmlApplicationContext springcontext = (ClassPathXmlApplicationContext) req.getServletContext().getAttribute("springcontext");
        UserAction useraction = (UserAction) springcontext.getBean("userAction");
        System.out.println(useraction);
        useraction.Update();
    }
}

测试结果:

 到这里我的分享就结束了,欢迎到评论区探讨交流!!

如果觉得有用的话还请点个赞吧 ♥  ♥

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/883337.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32F4X-GPIO输入功能使用

STM32F4 GPIO输入模式配置 上一节讲GPIO的时候说到了将GPIO设置成输出模式&#xff0c;并通过将GPIO的电平拉高拉低控制LED灯的例程。GPIO除了用作输出功能之外&#xff0c;还可以用作输入功能。最常用的就是检测按键的输入电平。 硬件设计 本章的硬件是基于正点原子的探索者…

UI设计师个人工作总结范文精选

UI设计师个人工作总结范文(一) 在忙忙碌碌中&#xff0c;2019年又将过去了&#xff0c;在这一年当中&#xff0c;设计部无论是在运作模式、设计产值、还是人员结构&#xff0c;各方面的变化都比较大。 设计部的运作模式是从7月底开始进行调整的&#xff0c;以独立承包制的运营方…

Linux / Ubuntu磁盘扩容

测试时遇到了shell脚本执行错误的问题&#xff0c;找到脚本编写的楼哥&#xff0c;才发现自己给虚拟机的磁盘已经满了&#xff0c;没想到啊&#xff0c;业务的解压操作&#xff0c;这么费磁盘&#xff0c;那就需要进行磁盘的扩展&#xff0c;记录一下 1、首先停掉虚拟机&#…

只需四步,让Vscode连接远程服务器中的docker容器进行开发

0. 前提条件 本地windows或其他环境中安装了Vscode&#xff0c;Vscode中安装了Remote-SSH拓展&#xff08;用于利用SSH连接docker容器&#xff09;远程服务器中安装了docker&#xff0c;并且拉取了自己需要的镜像&#xff08;image&#xff09;有root权限&#xff0c;能使用su…

【环境配置】Windows10终端和VSCode下能够直接打开Anaconda-Prompt

很多小伙伴在 Windows 下做深度学习开发的时候&#xff0c;遇到终端没有在 Linux 那么方便&#xff0c;那么我们现在就可以来设置一下&#xff1b;这样我们也可以在文件夹内部右键打开终端&#xff0c;也可以在 VS Code 里面新建一个虚拟环境的控制台&#xff1b;这里主要是针对…

HCIP-OpenStack组件介绍

OpenStack排错思路&#xff1a; OpenStack查询日志&#xff0c;所有日志都在/var/log/模块名称下面。 OpenStack修改配置&#xff0c;所有配置文件都在/etc/模块名称下面。 openstack把这些组件服务都集成到httpd服务中了&#xff0c;目的是为了提升性能。登入不了openstack在…

Spark MLlib机器学习库(一)决策树和随机森林案例详解

Spark MLlib机器学习库(一)决策树和随机森林案例详解 1 决策树预测森林植被 1.1 Covtype数据集 数据集的下载地址&#xff1a; https://www.kaggle.com/datasets/uciml/forest-cover-type-dataset 该数据集记录了美国科罗拉多州不同地块的森林植被类型&#xff0c;每个样本…

Git 如何使用TortoiseGit 操作本地仓库

初始化仓库 方法一: 新建一个文件夹,进入文件夹内部操作 1、右键--> 在这里创建Git 版本库 注意: 不要直接在桌面上操作,否则桌面就是一个仓库 方法二: 1、右键-->Git GUI here 方法三: 命令行模式 1、 git init 创建完毕仓库,我们发现,此时我们创建的文件夹下…

安防视频监控有哪些存储方式?哪种存储方式最优?

视频监控系统涉及到大量的视频数据&#xff0c;需要对这些数据进行存储&#xff0c;以备日后查看或备份。视频监控的存储需求需要根据场所的实际情况进行选择&#xff0c;以保证监控数据的有效存储和日后的调阅、回溯。 当前视频监控的存储方式&#xff0c;通常有以下几种&…

Redis数据库的可视化工具AnotherRedisDesktopManager使用+抖音直播小玩法实践

一、它是什么 Another Redis DeskTop Manager 是一个开源项目&#xff0c;提供了以可视化的方式管理 Redis 的功能&#xff0c;可供免费下载安装&#xff0c;也可以在此基础上进行二次开发&#xff0c;主要特点有&#xff1a; 支持 Windows 平台和 MacOS 平台 支持查询 Key、…

分布式图数据库 NebulaGraph v3.6.0 正式发布,强化全文索引能力

本次 v3.6.0 版本&#xff0c;主要强化全文索引能力&#xff0c;以及优化部分场景下的 MATCH 性能。 强化 强化增强全文索引功能&#xff0c;具体 pr 参见&#xff1a;#5567、#5575、#5577、#5580、#5584、#5587 优化 支持使用 MATCH 子句检索 VID 或属性索引时使用变量&am…

蓝帽杯2022

计算机取证 1 内存取证获取开机密码 现对一个windows计算机进行取证&#xff0c;请您对以下问题进行分析解答。 从内存镜像中获得taqi7的开机密码是多少&#xff1f;&#xff08;答案参考格式&#xff1a;abcABC123&#xff09; 首先我们直接对 1.dmp 使用 vol查看 py -2 v…

WSL2 Ubuntu子系统安装OpenCV

文章目录 前言一、&#xfeff;基本概念二、操作步骤1.下载源码2.安装依赖3.运行编译4.配置路径 前言 OpenCV用C语言编写&#xff0c;它的主要接口也是C语言&#xff0c;但是依然保留了大量的C语言接口。该库也有大量的Python, Java and MATLAB/OCTAVE (版本2.5)的接口。这些语…

大数据_SLA,SLO,SLI 名词解读

参考 &#xff1a; SLI、SLO和SLA&#xff0c;一文彻底搞懂&#xff01;&#xff01;&#xff01;_木给哇啦丶的博客-CSDN博客 前言 SLO和SLA是大家常见的两个名词&#xff1a;服务等级目标和服务等级协议。 云计算时代&#xff0c;各大云服务提供商都发布有自己服务的 SLA 条…

应用层读取wfp防火墙阻断记录

前言 之前的文档中&#xff0c;描写了如何对WFP防火墙进行操作[链接在此]&#xff0c;这篇文档中&#xff0c;描述如何获取WFP防火墙进行阻断的操作记录。 需要注意的坑点 使用FWPM_NET_EVENT_TYPE获取防火墙日志时&#xff0c;需要注意&#xff0c;只有丢弃和内核丢弃&…

指定CUDA版本失败的解决方案

新电脑安装的WIN11系统&#xff0c;因为CUDA只有11和12目前能装到WIN11上&#xff0c;所以就装了一个CUDA 11.7。但是编译PBRT失败&#xff0c;所以无奈之下又装了CUDA 12。 但是因为我有的代码需要CUDA 11里的函数&#xff0c;这些函数在CUDA12里被彻底删除了&#xff0c;但是…

CentOS7的journalctl日志查看方法

多台服务器间免密登录|免密拷贝 Cenos7 搭建Minio集群部署服务器(一) Cenos7 搭建Minio集群Nginx统一访问入口|反向动态代理(二) Spring Boot 与Minio整合实现文件上传与下载(三) CentOS7的journalctl日志查看方法 MySQL8.xx一主两从复制安装与配置 1、概述 日志管理工…

下单接口调优实战,性能提高10倍

目录 概述 用到的工具和环境 工具 环境 找瓶颈 总结 概述 最近公司的下单接口有些慢&#xff0c;老板担心无法支撑双11&#xff0c;想让我优化一把&#xff0c;但是前提是不允许大改&#xff0c;因为下单接口太复杂了&#xff0c;如果改动太大&#xff0c;怕有风险。另外…