Spring系列篇--关于IOC【控制反转】的详解

🥳🥳Welcome Huihui's Code World ! !🥳🥳

接下来看看由辉辉所写的关于Spring的相关操作吧

目录

🥳🥳Welcome Huihui's Code World ! !🥳🥳

 一.什么是Spring

二.Spring的特点

三.什么是IOC

场景模拟:

控制反转:

使用步骤

1 创建Maven的war项目然后配置web的相关依赖以及项目结构的配置

2在pom.xml文件中配置Spring的依赖

3 在resources下创建并配置spring-context.xml

4 在业务层中创建WorkBiz接口及其实现类

5 在项目中创建MVC的包结构,并创建Web层,并获取Spring的容器对象

6 测试

7 总结

四.IOC的实现方式

五.IOC依赖注入的三种方式

1.Setter方法注入(Setter Injection):

2.构造函数注入(Constructor Injection):

3.接口注入(Interface Injection):

byName:

byType:

六.spring与web容器的整合 

1.监听器的初始化方法 只执行一次

2.spring的上下文要存放在Tomcat上下文中


 一.什么是Spring

  ▲Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的
  ▲ Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情
  🔺简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架

二.Spring的特点

  1. 轻量级和非侵入性:Spring框架采用轻量级的设计理念,不侵入应用程序的业务逻辑,使得应用程序可以更加灵活和可维护

  2. 控制反转(IoC)和依赖注入(DI):IoC是Spring框架的核心概念,它通过DI将对象的创建和依赖关系的管理从应用程序代码中解耦出来。这样可以降低代码的耦合性,提高代码的可测试性和可维护性

  3. 面向切面编程(AOP):Spring框架通过AOP提供了一种在应用程序中优雅地处理横切关注点的方式。通过AOP,可以将一些与主要业务逻辑无关的功能,如日志记录、事务管理等,从应用程序代码中分离出来,使得代码更加简洁和可维护

  4. 数据访问和集成:Spring框架提供了一系列的数据访问和集成模块,如JDBC、ORM(Object-Relational Mapping)、事务管理等。这些模块可以帮助开发人员更加方便地与数据库进行交互,处理事务以及与第三方系统进行集成

  5. Web开发支持:Spring框架提供了一系列的Web开发支持模块,如Spring MVC、Spring WebFlux等。这些模块可以帮助开发人员构建灵活、可扩展和高性能的Web应用程序

那么在这篇博客中,我们就来详细的解剖一下IOC【控制反转】,首先让我们看一看IOC到底是个什么吧!!!

三.什么是IOC

▲IOC(Inversion of Control,控制反转)是软件开发中的一种设计原则和编程思想。它指的是将对象的创建和依赖关系的管理转移给外部容器(通常是框架或容器),从而实现了对象间的解耦

⭕在传统的开发模式中,对象之间的依赖关系是由对象自己负责管理的。例如,如果一个对象需要依赖其他对象,它会通过直接实例化其他对象或使用静态方法获取依赖对象。这样的实现方式使得对象之间高度耦合,难以进行更改和测试,因而会使得项目难以维护

▲而在IOC的思想下,对象的创建和依赖关系的管理被转移给一个外部容器。容器负责实例化对象,并在对象之间建立依赖关系。对象只需要声明自己所需要的依赖,容器会自动注入这些依赖。这样可以大大降低代码的耦合性,使得代码更加模块化、可扩展和可测试

了解了IOC是什么之后,可能我们对于IOC的便捷之处还没有一个更加直观的了解,那么接下来我将用代码(不过都是一个简单的模拟)来展示,这样也可以更加直观的感觉出IOC的便捷!!

场景模拟:

 在一个公司的管理系统中,管理层都需要管理公司的事物以及员工,但是每个管理层管理员工所关注的点是不同的,因为每个管理者的工作是不同的因此需要做出一个十分好用的管理系统还是需要考虑很多方面的,有一天你所在的公司接到了一个项    目:xx公司的管理系统
恰好你就被派任到此项目了,此时你就需要完成一个公司的人员管理系统
接下来就是甲方给你提需求了!

需求1: 现在人事管理的模块和财务管理的模块都需要查询到用户的信息那么我只需要写一个dao方法和一个biz,然后在人事和财务的web层中调用用户的biz层
package com.wh.biz.impl;import com.wh.biz.WorkerBiz;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-15 16:35*/public class WokerBizImpl implements WorkerBiz {@Overridepublic void list() {System.out.println("查询员工(用户)信息");}}
package com.wh.web;import com.wh.biz.WorkerBiz;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-15 16:38*/
public class FinanceAction {//财务
private WorkerBiz workerBiz = new WokerBizImpl();public void list() {//调用业务逻辑层查询的方法workerBiz.list();}}
package com.wh.web;import com.wh.biz.WorkerBiz;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-15 16:38*/
public class HRAction {//人事private WorkerBiz workerBiz = new WokerBizImpl();public void list() {//调用业务逻辑层查询的方法workerBiz.list();}
}

结果

但是客户那边商量之后,突然间又换了一个需求

需求2:同时在人事模块,财务模块拿到所有的用户数据,并且要求人事模块中的用户数据是通过年龄排序的对应策略:修改biz中list方法,添加年龄排序功能
package com.wh.biz.impl;import com.wh.biz.WorkerBiz;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-15 16:35*/public class WokerBizImpl1 implements WorkerBiz {@Overridepublic void list() {System.out.println("查询员工(用户),按照年龄来排序...");}}
package com.wh.web;import com.wh.biz.WorkerBiz;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-15 16:38*/
public class HRAction {//人事private WorkerBiz workerBiz = new WokerBizImpl1();public void list() {//调用业务逻辑层查询的方法workerBiz.list();}
}
package com.wh.web;import com.wh.biz.WorkerBiz;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-15 16:38*/
public class FinanceAction {//财务
private WorkerBiz workerBiz = new WokerBizImpl();public void list() {//调用业务逻辑层查询的方法workerBiz.list();}}

结果

客户那边思来想去,认为财务模块中的数据也需要另作要求

需求3:同时在人事模块,财务模块拿到所有的用户数据,并且要求人事模块中的用户数据是通过年龄排序的,财务模块中的用户数据是通过薪资排序的对应策略,修改biz中list方法,添加排薪资排序功能
package com.wh.biz.impl;import com.wh.biz.WorkerBiz;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-15 16:35*/public class WokerBizImpl1 implements WorkerBiz {@Overridepublic void list() {System.out.println("查询员工(用户),按照年龄来排序...");}}
package com.wh.biz.impl;import com.wh.biz.WorkerBiz;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-15 16:35*/public class WokerBizImpl2 implements WorkerBiz {@Overridepublic void list() {System.out.println("查询员工(用户),按照薪资排序...");}}
package com.wh.web;import com.wh.biz.WorkerBiz;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-15 16:38*/
public class HRAction {//人事private WorkerBiz workerBiz = new WokerBizImpl1();public void list() {//调用业务逻辑层查询的方法workerBiz.list();}
}
package com.wh.web;import com.wh.biz.WorkerBiz;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-15 16:38*/
public class FinanceAction {//财务
private WorkerBiz workerBiz = new WokerBizImpl2();public void list() {//调用业务逻辑层查询的方法workerBiz.list();}}

结果

 

相信聪明的你也应该发现问题了吧,当客户需求不断变更的时候我们就需要不断的修改代码,我这里只用了两个Action来展示,大家可能觉得不过如此,不就只需要增加几个不同功能的impl类,然后将所实例化的那行代码中的impl类进行改动嘛。但是我们要想,员工/用户的信息在一般情况下,在很多的地方都需要用到,那要是有200个web中都用到了用户的信息,那不是要修改200次? 要是200个中有一百个是按照年龄排序的,另外一百个是按照薪资排序的,那不是还得一个个看仔细了之后修改? 可见,这样的方式非常的费时间,不易维护(提出新需求,没方法快速修改)

前面我们已经说到了在IOC的思想下,对象的创建和依赖关系的管理被转移给一个外部容器

那我们就来看一下ioc到底是怎么进行这一波骚操作的吧

控制反转:

使用步骤

1 创建Maven的war项目然后配置web的相关依赖以及项目结构的配置

不会使用IDEA创建Maven项目的看这个

不会使用Eclipse创建Maven的项目的看这个


2在pom.xml文件中配置Spring的依赖

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.javaxl</groupId><artifactId>T224_spring</artifactId><packaging>war</packaging><version>0.0.1-SNAPSHOT</version><name>T224_spring Maven Webapp</name><url>http://maven.apache.org</url><properties><spring.version>5.0.1.RELEASE</spring.version><javax.servlet.version>4.0.0</javax.servlet.version><junit.version>4.12</junit.version></properties><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency><!-- 2、导入spring依赖 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>${spring.version}</version></dependency><!-- 5.1、junit --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${junit.version}</version><scope>test</scope></dependency><!-- 5.2、servlet --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>${javax.servlet.version}</version><scope>provided</scope></dependency></dependencies><build><finalName>T224_spring</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.7.0</version><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin></plugins></build>
</project>


3 在resources下创建并配置spring-context.xml

<?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 http://www.springframework.org/schema/beans/spring-beans.xsd"><bean class="com.wh.biz.impl.WokerBizImpl1" id="wokerBizImpl1"></bean><bean class="com.wh.biz.impl.WokerBizImpl2" id="wokerBizImpl2"></bean><bean class="com.wh.web.HRAction" id="hrAction"><property name="workerBiz" ref="wokerBizImpl1"></property></bean><bean class="com.wh.web.FinanceAction" id="financeAction"><property name="workerBiz" ref="wokerBizImpl2"></property></bean></beans>


4 在业务层中创建WorkBiz接口及其实现类

package com.wh.biz.impl;import com.wh.biz.WorkerBiz;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-15 16:35*/public class WokerBizImpl implements WorkerBiz {@Overridepublic void list() {System.out.println("查询员工(用户)信息");}}
package com.wh.biz.impl;import com.wh.biz.WorkerBiz;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-15 16:35*/public class WokerBizImpl1 implements WorkerBiz {@Overridepublic void list() {System.out.println("查询员工(用户),按照年龄来排序...");}}
package com.wh.biz.impl;import com.wh.biz.WorkerBiz;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-15 16:35*/public class WokerBizImpl2 implements WorkerBiz {@Overridepublic void list() {System.out.println("查询员工(用户),按照薪资排序...");}}

5 在项目中创建MVC的包结构,并创建Web层,并获取Spring的容器对象

package com.wh.web;import com.wh.biz.WorkerBiz;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-15 16:38*/
public class HRAction {/人事//    private WorkerBiz workerBiz = new WokerBizImpl1();private WorkerBiz workerBiz;//实例化业务逻辑层public void list() {workerBiz.list();}//调用业务逻辑层查询的方法public WorkerBiz getWorkerBiz() {//workerBiz的get方法return workerBiz;}public void setWorkerBiz(WorkerBiz workerBiz) {//workerBiz的get方法this.workerBiz = workerBiz;}
}
package com.wh.web;import com.wh.biz.WorkerBiz;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-15 16:38*/
public class FinanceAction {//财务
//    private WorkerBiz workerBiz = new WokerBizImpl1();
private WorkerBiz workerBiz;//实例化业务逻辑层public void list() {//调用业务逻辑层查询的方法workerBiz.list();}public WorkerBiz getWorkerBiz() {//workerBiz的get方法return workerBiz;}public void setWorkerBiz(WorkerBiz workerBiz) {//workerBiz的get方法this.workerBiz = workerBiz;}}

6 测试

package com.wh.ioc;import com.wh.web.HRAction;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-16 18:46*/
public class IOCTest {@SuppressWarnings("resource")public static void main(String[] args) {//建模ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring-context.xml");HRAction hrAction = (HRAction) context.getBean("hrAction");hrAction.list();}}

package com.wh.ioc;import com.wh.web.FinanceAction;
import com.wh.web.HRAction;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-16 18:46*/
public class IOCTest {@SuppressWarnings("resource")public static void main(String[] args) {//建模ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring-context.xml");HRAction hrAction = (HRAction) context.getBean("hrAction");hrAction.list();FinanceAction financeAction = (FinanceAction) context.getBean("financeAction");financeAction.list();}}

7 总结

需要什么功能,或是说需要修改,只需要在spring-context中进行配置/修改便可(web层中进行相应的封装便可)

原来的代码进行修改或增加功能,都需要手动的进行查找,先将修改功能的模块写好,在去寻找需要修改功能的Action,一个一个的手动修改,可以说是十分的繁琐。但是我们使用IOC的方式,就只需要修改配置文件,这样一对比,是不是就能够非常直观的感受到使用IOC的好处了!!

四.IOC的实现方式

  1. 依赖注入(Dependency Injection,DI):通过DI,容器在创建对象时,自动将依赖对象注入到对象中。依赖注入可以通过构造函数、属性注入或接口注入等方式进行。

  2. 依赖查找(Dependency Lookup):通过依赖查找,对象使用容器提供的查找机制,主动获取所需的依赖对象

可以看到ioc的实现方式主要有两种,那么我们今天就来探究一下其中的依赖注入!

五.IOC依赖注入的三种方式

1.Setter方法注入(Setter Injection):

通过在目标对象中定义对应的setter方法,从而实现对依赖对象的注入。依赖对象通过调用setter方法设置给目标对象

顾名思义就是需要提供set方法,那如果我没有提供set方法呢?我们可以试一下将action中的set方法给注释掉

可以看到报出了一个错误,意思是在其中没有set方法 

package com.wh.web;import com.wh.biz.WorkerBiz;import java.util.List;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-15 16:38*/
public class FinanceAction {
//    private WorkerBiz workerBiz = new WokerBizImpl1();
private WorkerBiz workerBiz;//实例化业务逻辑层public void list() {//调用业务逻辑层查询的方法System.out.println(name);System.out.println(age);System.out.println(hobby);workerBiz.list();}public WorkerBiz getWorkerBiz() {//workerBiz的get方法return workerBiz;}public void setWorkerBiz(WorkerBiz workerBiz) {//workerBiz的set方法this.workerBiz = workerBiz;}private String name;private int age;private List<String> hobby;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public List<String> getHobby() {return hobby;}public void setHobby(List<String> hobby) {this.hobby = hobby;}
}
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd"><bean class="com.wh.biz.impl.WokerBizImpl1" id="wokerBizImpl1"></bean><bean class="com.wh.biz.impl.WokerBizImpl2" id="wokerBizImpl2"></bean><bean class="com.wh.web.HRAction" id="hrAction"><property name="workerBiz" ref="wokerBizImpl1"></property></bean><!--set注入--><bean class="com.wh.web.FinanceAction" id="financeAction"><property name="workerBiz" ref="wokerBizImpl2"></property><property name="name" value="wh"></property><property name="age" value="18"></property><property name="hobby" ><list><value>唱</value><value>跳</value><value>RAP</value></list></property></bean></beans>

结果

2.构造函数注入(Constructor Injection):

通过在目标对象的构造函数中定义参数,从而实现对依赖对象的注入。依赖对象在创建目标对象时通过构造函数传递进来

package com.wh.web;import com.wh.biz.WorkerBiz;import java.util.List;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-15 16:38*/
public class FinanceAction {
//    private WorkerBiz workerBiz = new WokerBizImpl1();
private WorkerBiz workerBiz;//实例化业务逻辑层public void list() {//调用业务逻辑层查询的方法System.out.println(name);System.out.println(age);System.out.println(hobby);workerBiz.list();}private String name;private int age;private List<String> hobby;public FinanceAction() {//空参构造}public FinanceAction(String name, int age, List<String> hobby) {//有参构造this.name = name;this.age = age;this.hobby = hobby;}
}
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd"><bean class="com.wh.biz.impl.WokerBizImpl1" id="wokerBizImpl1"></bean><bean class="com.wh.biz.impl.WokerBizImpl2" id="wokerBizImpl2"></bean><bean class="com.wh.web.HRAction" id="hrAction"><property name="workerBiz" ref="wokerBizImpl1"></property></bean><!--构造函数注入--><bean class="com.wh.web.FinanceAction" id="financeAction"><property name="workerBiz" ref="wokerBizImpl2"></property><constructor-arg name="name" value="wh"></constructor-arg><constructor-arg name="age" value="18"></constructor-arg><constructor-arg name="hobby"><list><value>唱</value><value>跳</value><value>RAP</value></list></constructor-arg></bean></beans>

 结果

3.接口注入(Interface Injection):

通过在目标对象中定义一个接口,并在接口中定义一个设置依赖对象的方法,从而实现对依赖对象的注入。目标对象实现该接口并实现依赖对象的设置方法

注意:

autowire="xx" (其中填的是byName/byType)


byName:

是通过spring管理的bean对象的ID进行查找,如果找不到,则注入失败,反之成功
 

<?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 http://www.springframework.org/schema/beans/spring-beans.xsd"><bean class="com.wh.biz.impl.WokerBizImpl1" id="wokerBizImpl1"></bean><bean class="com.wh.biz.impl.WokerBizImpl2" id="wokerBizImpl2"></bean><bean class="com.wh.web.HRAction" id="hrAction"><property name="workerBiz" ref="wokerBizImpl1"></property></bean><!--自动装配-byname--><bean class="com.wh.web.FinanceAction" id="financeAction" autowire="byName"><property name="workerBiz" ref="wokerBizImpl2"></property></bean></beans>
package com.wh.web;import com.wh.biz.WorkerBiz;import java.util.List;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-15 16:38*/
public class FinanceAction {
//    private WorkerBiz workerBiz = new WokerBizImpl1();
private WorkerBiz workerBiz;//实例化业务逻辑层public void list() {//调用业务逻辑层查询的方法workerBiz.list();}public WorkerBiz getWorkerBiz() {//workerBiz的get方法return workerBiz;}public void setWorkerBiz(WorkerBiz workerBiz) {//workerBiz的get方法this.workerBiz = workerBiz;}}

结果

byType:

是通过spring管理的bean对象的接口实现类进行查找,如果没有或者2个以上,则注入失败,反之成功

但是在使用byType时,同一类型的对象,在spring容器中必须唯一。如果不唯一,会报不唯一的异常

<?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 http://www.springframework.org/schema/beans/spring-beans.xsd"><!--自动装配-byname--><bean class="com.wh.web.FinanceAction" id="financeAction" autowire="byType"></bean><bean class="com.wh.biz.impl.WokerBizImpl1" id="wokerBizImpl1"></bean>
</beans>
package com.wh.web;import com.wh.biz.WorkerBiz;import java.util.List;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-15 16:38*/
public class FinanceAction {
//    private WorkerBiz workerBiz = new WokerBizImpl1();
private WorkerBiz workerBiz;//实例化业务逻辑层public void list() {//调用业务逻辑层查询的方法workerBiz.list();}public WorkerBiz getWorkerBiz() {//workerBiz的get方法return workerBiz;}public void setWorkerBiz(WorkerBiz workerBiz) {//workerBiz的get方法this.workerBiz = workerBiz;}}

结果

六.spring与web容器的整合 

  Q:为什么需要进行这一步操作?
  A:  建模的过程是十分耗时的     
   
  解决问题的思路:
         1.建模必不可少
         2.保证建模只执行一次
         3.建模后期望在每一个servlet都能够拿到spring的上下文对象


   Q:怎么处理?

    A:

1.监听器的初始化方法 只执行一次

package com.wh.listener;import org.springframework.context.support.ClassPathXmlApplicationContext;import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;/*** @author 王辉* @site www.shihuihuila.com* @create 2023-08-16 18:37*/
@WebListener
public class Listener implements ServletContextListener {@Overridepublic void contextInitialized(ServletContextEvent sce) {System.out.println("初始化执行");ServletContext servletContext = sce.getServletContext();String springConfigLocation = servletContext.getInitParameter("springConfigLocation");System.out.println(springConfigLocation+"...");//拿到spring上下文ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring-context.xml");//将spring的上下文保存在Tomcat上下文中servletContext.setAttribute("springContext", context);}}

2.spring的上下文要存放在Tomcat上下文中

package com.wh.ioc;import com.wh.web.FinanceAction;
import org.springframework.context.support.ClassPathXmlApplicationContext;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** spring与web容器的整合原理* 	why:建模的过程是十分耗时的* 解决问题:* 1.建模必不可少* 2.建模只保障只执行一次* 3.建模后期望在每一个servlet都能够拿到spring的上下文对象ClassPathXmlApplicationContext* how:* 1.监听器的初始化方法 只执行一次* 2.spring的上下文要存放在Tomcat上下文中*  @author 王辉* @site www.shihuihuila.com*  @create 2023-08-16 19:37**/
@WebServlet("/springDemo")
public class DemoServlet extends HttpServlet{@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req,resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring-context.xml");ClassPathXmlApplicationContext springcontext = (ClassPathXmlApplicationContext) req.getServletContext().getAttribute("springContext");FinanceAction financeAction = (FinanceAction) springcontext.getBean("financeAction");financeAction.list();}}

运行即可

​ 

好啦,今天的分享就到这了,希望能够帮到你呢!😊😊  

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

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

相关文章

【O2O领域】Axure外卖订餐骑手端APP原型图,外卖众包配送原型设计图

作品概况 页面数量&#xff1a;共 110 页 兼容软件&#xff1a;Axure RP 9/10&#xff0c;不支持低版本 应用领域&#xff1a;外卖配送、生鲜配送 作品申明&#xff1a;页面内容仅用于功能演示&#xff0c;无实际功能 作品特色 本品为外卖订餐骑手端APP原型设计图&#x…

Datawhale Django 后端开发入门 Task05 DefaultRouter、自定义函数

一、DefaultRouter是Django REST framework中提供的一个路由器类&#xff0c;用于自动生成URL路由。路由器是将URL与视图函数或视图集关联起来的一种机制。Django REST framework的路由器通过简单的配置可以自动生成标准的URL路由&#xff0c;从而减少了手动编写URL路由的工作量…

Redis Lua脚本执行原理和语法示例

Redis Lua脚本语法示例 文章目录 Redis Lua脚本语法示例0. 前言参考资料 1. Redis 执行Lua脚本原理1.1. 对Redis源码中嵌入Lua解释器的简要解析&#xff1a;1.2. Redis Lua 脚本缓存机制 2. Redis Lua脚本示例1.1. 场景示例1. 请求限流2. 原子性地从一个list移动元素到另一个li…

基于郊狼算法优化的BP神经网络(预测应用) - 附代码

基于郊狼算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码 文章目录 基于郊狼算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码1.数据介绍2.郊狼优化BP神经网络2.1 BP神经网络参数设置2.2 郊狼算法应用 4.测试结果&#xff1a;5.Matlab代码 摘要…

【深入解析:数据结构栈的魅力与应用】

本章重点 栈的概念及结构 栈的实现方式 数组实现栈接口 栈面试题目 概念选择题 一、栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端 称为栈顶&#xff0c;另一端称为栈底。栈中的数…

指针(一)【C语言进阶版】

大家好&#xff0c;我是深鱼~ 【前言】&#xff1a; 指针的主题&#xff0c;在初阶指针章节已经接触过了&#xff0c;我们知道了指针的概念&#xff1a; 1.指针就是个变量&#xff0c;用来存放地址&#xff0c;地址的唯一标识一块内存空间&#xff08;指针变量&#xff09;&a…

【云原生|Docker系列第3篇】Docker镜像的入门实践

欢迎来到Docker入门系列的第三篇博客&#xff01;在前两篇博客中&#xff0c;我们已经了解了什么是Docker以及如何安装和配置它。本篇博客将重点介绍Docker镜像的概念&#xff0c;以及它们之间的关系。我们还将学习如何拉取、创建、管理和分享Docker镜像&#xff0c;这是使用Do…

jenkins同一jar包部署到多台服务器

文章目录 安装插件配置ssh服务构建完成后执行 没有部署过可以跟这个下面的步骤先部署一遍&#xff0c;我这篇主要讲jenkins同一jar包部署到多台服务器 【Jenkins】部署Springboot项目https://blog.csdn.net/qq_39017153/article/details/131901613 安装插件 Publish Over SSH 这…

stm32g070的PD0/PD2 PA8和PB15

目前在用STM32G070做项目&#xff0c;其中PD2TIMER3去模拟PWM&#xff0c;PD0用作按键检测&#xff0c;测试发现PD0低电平检测没有问题&#xff0c;高电平检测不到&#xff0c;电路图如下图所示&#xff1a; 用万用表测试电平&#xff0c;高电平1.0V左右&#xff0c;首先怀疑硬…

rust踩雷笔记(4)——刷点Vec相关的题(持续更新)

俗话说&#xff0c;孰能生巧&#xff0c;今天是第六天接触Rust&#xff0c;感觉基础语法和特性没什么问题了&#xff08;当然如果你整天都学这个可能2天半就够了&#xff09;&#xff0c;但是想达到熟练使用&#xff0c;还需要刷点题。算法我相信能来看rust博客的人都是大牛&am…

【项目实践】基于LSTM的一维数据扩展与预测

基于LSTM的一维数据拟合扩展 一、引(fei)言(hua) 我在做Sri Lanka生态系统服务价值计算时&#xff0c;中间遇到了一点小问题。从世界粮农组织(FAO)上获得Sri Lanka主要农作物产量和价格数据时&#xff0c;其中的主要作物Sorghum仅有2001-2006年的数据&#xff0c;而Millet只有…

算法通关村第4关【黄金】| 表达式问题

1. 计算器问题 思路&#xff1a;此题不考虑括号和负数情况&#xff0c;单纯使用栈即可解决。注意的是数字可能是多位数需要保留完整的num&#xff0c; 保留数字的前缀符号&#xff0c;当碰到加号&#xff0c;存进去&#xff1b;当碰到减号&#xff0c;存相反数进去&#xff1b;…

Apinto 网关进阶教程,插件开发入门指南

Apinto 是基于Go语言&#xff0c;由 Eolink 自主研发的一款高性能、可扩展、易维护的云原生 API 网关。Apinto 能够帮助用户简单、快速、低成本、低风险地实现&#xff1a;系统微服务化、系统集成、向合作伙伴、开发者开放功能和数据。 通过 Apinto&#xff0c;企业能够专注于…

【LeetCode-中等题】15. 三数之和

题目 题解一&#xff1a;双指针法 图解参考链接&#xff1a;画解算法&#xff1a;15. 三数之和 详解参考代码随想录讲的非常好 梦破碎的地方&#xff01;| LeetCode&#xff1a;15.三数之和 代码&#xff1a; class Solution {public List<List<Integer>> thre…

Codeforces Round 893 (Div. 2) A ~ C

比赛链接 A. Buttons 博弈、最优策略一定是先去按都能按的按钮&#xff0c;按完之后再按自己的。 #include<bits/stdc.h> #define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); #define endl \nusing namespace std;typedef pair<int, int> PII; typede…

jstack(Stack Trace for Java)Java堆栈跟踪工具

jstack&#xff08;Stack Trace for Java&#xff09;Java堆栈跟踪工具 jstack&#xff08;Stack Trace for Java&#xff09;命令用于生成虚拟机当前时刻的线程快照&#xff08;一般称为threaddump或者javacore文件&#xff09;。 线程快照就是当前虚拟机内每一条线程正在执…

动手学深度学习-pytorch版本(二):线性神经网络

参考引用 动手学深度学习 1. 线性神经网络 神经网络的整个训练过程&#xff0c;包括: 定义简单的神经网络架构、数据处理、指定损失函数和如何训练模型。经典统计学习技术中的线性回归和 softmax 回归可以视为线性神经网络 1.1 线性回归 回归 (regression) 是能为一个或多个…

Linux系统的目录结构

file system hierarchy standard文件系统层级标准&#xff0c;定义了在类Unix系统中的目录结构和目录内容。 即让用户了解到已安装软件通常放置于哪个目录下。 Linux目录结构的特点 使用树形目录结构来组织和管理文件。 整个系统只有一个根目录&#xff08;树根&#xff09;&a…

记录几个Hudi Flink使用问题及解决方法

前言 如题&#xff0c;记录几个Hudi Flink使用问题&#xff0c;学习和使用Hudi Flink有一段时间&#xff0c;虽然目前用的还不够深入&#xff0c;但是目前也遇到了几个问题&#xff0c;现在将遇到的这几个问题以及解决方式记录一下 版本 Flink 1.15.4Hudi 0.13.0 流写 流写…

Flink之时间语义

Flink之时间语义 简介 Flink中时间语义可以说是最重要的一个概念了,这里就说一下关于时间语义的机制,我们下看一下下面的表格,简单了解一下 时间定义processing time处理时间,也就是现实世界的时间,或者说代码执行时,服务器的时间event time事件时间,就是事件数据中所带的时…