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

news2024/10/7 20:34:26

🥳🥳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 {

    @Override
    public 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 {

    @Override
    public 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 {

    @Override
    public 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 {

    @Override
    public 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 {

    @Override
    public 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 {

    @Override
    public 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 {

    @Override
    public 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 {
    @Override
    public 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{
    @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 {
        //ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring-context.xml");
        ClassPathXmlApplicationContext springcontext = (ClassPathXmlApplicationContext) req.getServletContext().getAttribute("springContext");

        FinanceAction financeAction = (FinanceAction) springcontext.getBean("financeAction");
        financeAction.list();
    }


}

运行即可

​ 

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

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

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

相关文章

TCP服务器—实现数据通信

目录 前言 1.接口介绍 2.编写服务器 3.编写客户端 4.编译链接 5.测试 6.总结 前言 今天我们要介绍的是使用TCP协议实现数据通信&#xff0c;相比于之前写的UDP服务器实现数据信&#xff0c;在主体逻辑上并没有差别。客户端向服务器发送信息&#xff0c;服务器接受信息并回…

如何进行无线网络渗透测试?

今天我们将继续深入探讨Kali Linux的应用&#xff0c;这次我们将重点介绍如何使用Kali Linux进行无线网络渗透测试。无线网络渗透测试是评估无线网络安全性的重要步骤&#xff0c;而Kali Linux作为一款专业的渗透测试发行版&#xff0c;提供了丰富的工具来帮助你进行这项任务。…

支持https访问

文章目录 1. 打开自己的云服务器的 80 和 443 端口2. 安装 nginx3. 安装 snapd4. 安装 certbot5. 生成证书6. 拷贝生成的证书到项目工作目录7. 修改 main.go 程序如下8. 编译程序9. 启动程序10. 使用 https 和端口 8081 访问页面成功11. 下面修改程序&#xff0c;支持 https 和…

【RocketMQ】NameServer总结

NameServer是一个注册中心&#xff0c;提供服务注册和服务发现的功能。NameServer可以集群部署&#xff0c;集群中每个节点都是对等的关系&#xff08;没有像ZooKeeper那样在集群中选举出一个Master节点&#xff09;&#xff0c;节点之间互不通信。 服务注册 Broker启动的时候会…

grafana-zabbix基础操作篇------导入数据源

文章目录 一、grafana的安装1.1、下载地址1.2、下载后导入所安装机器1.3、yum安装解决依赖1.4、启动grafana1.5、查看端口是否启用&#xff08;端口默认3000&#xff09;1.6、浏览器访问 二、添加zabbix数据源2.1、导入数据源 **下一篇 我们讲讲构建仪表板的操作** 今天&#x…

SpringMVC拦截器的介绍,拦截器的基本实现,拦截器链配置

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaweb 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 拦截器 一、拦截器概念二、拦截器与过滤器的区别三、拦截器…

【ChatGLM】ChatGLM-6B模型Win+4GB显卡本地部署笔记

ChatGLM-6B是清华大学知识工程和数据挖掘小组发布的一个类似ChatGPT的开源对话机器人&#xff0c;由于该模型是经过约1T标识符的中英文训练&#xff0c;且大部分都是中文&#xff0c;因此十分适合国内使用。 预期环境 本机电脑备注&#xff1a; Win10专业版 32G内存256固态系统…

【BASH】回顾与知识点梳理(三十一)

【BASH】回顾与知识点梳理 三十一 三十一. 进程的管理31.1 给进程发送讯号kill -signal PIDlinux系统后台常驻进程killall -signal 指令名称 31.2 关于进程的执行顺序Priority 与 Nice 值nice &#xff1a;新执行的指令即给予新的 nice 值renice &#xff1a;已存在进程的 nice…

绿盾客户端文件加密不显示锁的图标,加密功能正常

环境: 绿盾客户端7.0 Win10 专业版 问题描述: 绿盾客户端文件加密不显示锁的图标,加密功能正常 解决方案: 1.查看控制台是否设置隐藏图标 (未解决) 控制台-规则中心-安全选项-“加密文件显示加密图标”和“不显示Explorer 鼠标右键菜单”是否打钩 如果没打钩,则不…

(学习笔记-进程管理)怎么避免死锁?

死锁的概念 在多线程编程中&#xff0c;我们为了防止多线程竞争共享资源而导致数据错乱&#xff0c;都会在操作共享资源之前加上互斥锁&#xff0c;只有成功获得到锁的线程&#xff0c;才能操作共享资源&#xff0c;获取不到锁的线程就只能等待&#xff0c;直到锁被释放。 那…

(分治) 剑指 Offer 16. 数值的整数次方 ——【Leetcode每日一题】

❓剑指 Offer 16. 数值的整数次方 难度&#xff1a;中等 实现 pow(x, n) &#xff0c;即计算 x 的 n 次幂函数&#xff08;即&#xff0c; x n x^n xn&#xff09;。不得使用库函数&#xff0c;同时不需要考虑大数问题。 示例 1&#xff1a; 输入&#xff1a;x 2.00000, n …

Linux系统安装Google Chrome

1.进入谷歌浏览器官网 Google Chrome - Download the Fast, Secure Browser from GoogleGet more done with the new Google Chrome. A more simple, secure, and faster web browser than ever, with Google’s smarts built-in. Download now.http://www.google.cn/intl/en_…

数学建模之“TOPSIS数学模型”原理和代码详解

一、简介 TOPSIS&#xff08;Technique for Order Preference by Similarity to Ideal Solution&#xff09;是一种多准则决策分析方法&#xff0c;用于解决多个候选方案之间的排序和选择问题。它基于一种数学模型&#xff0c;通过比较每个候选方案与理想解和负理想解之间的相…

图卷积网络:GNN 简介【01/4】

图片来源&#xff1a;作者 一、说明 图形神经网络 &#xff08;GNN&#xff09; 代表了深度学习领域最迷人、发展最迅速的架构之一。作为旨在处理结构化为图形的数据的深度学习模型&#xff0c;GNN 带来了非凡的多功能性和强大的学习能力。 在各种类型的GNN中&#xff0c;图卷…

使用Java服务器实现UDP消息的发送和接收(多线程)

目录 简介&#xff1a;1. 导入必要的库2. 创建服务器端代码3. 创建客户端代码4. 实现多线程处理5. 测试运行示例代码&#xff1a;函数说明服务器端代码说明&#xff1a;客户端代码说明&#xff1a; 总结&#xff1a; 简介&#xff1a; 在本篇博客中&#xff0c;我们将介绍如何…

Spring的三种异常处理方式

1.SpringMVC 异常的处理流程 异常分为编译时异常和运行时异常&#xff0c;编译时异常我们 try-cache 进行捕获&#xff0c;捕获后自行处理&#xff0c;而运行时异常是不 可预期的&#xff0c;就需要规范编码来避免&#xff0c;在SpringMVC 中&#xff0c;不管是编译异常还是运行…

激活函数总结(十):激活函数补充(Identity、LogSigmoid、Bent Identity)

激活函数总结&#xff08;十&#xff09;&#xff1a;激活函数补充 1 引言2 激活函数2.1 Identity激活函数2.2 LogSigmoid激活函数2.3 Bent Identity激活函数 3. 总结 1 引言 在前面的文章中已经介绍了介绍了一系列激活函数 (Sigmoid、Tanh、ReLU、Leaky ReLU、PReLU、Swish、…

【校招VIP】测试方案之等价类

考点介绍&#xff1a; 在校招中&#xff0c;等价类也是重要的考查点。等价类划分是一种典型的黑盒测试设计方法&#xff0c;使用该方法主要对测试子项进行测试规格分析&#xff0c;得到用例&#xff0c;而不用对系统内部处理进行深入了解&#xff0c;它也是目前测试设计过程中使…

Python Opencv实践 - 图像金字塔

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png", cv.IMREAD_COLOR) print(img.shape)#图像上采样 #cv.pyrUp(src, dstNone, dstsizeNone, borderTypeNone) #参考资料&#xff1a;https://blo…