spring ico容器 spring注入方式 spring与tomcat整合

news2024/12/27 17:04:21

一、简介

1、什么是spring?

Spring是一个开源的轻量级Java应用开发框架,它提供了一种简单、高效、灵活的方式来构建企业级应用程序。Spring框架的核心特点是依赖注入Dependency Injection)和面向切面编程Aspect-Oriented Programming),它通过一组模块化的组件提供全面的支持,使开发人员能够快速搭建可扩展、可维护的应用。

2、目的

学习Spring的目的可以总结为以下几点:

  1. 简化开发:Spring提供了一系列的工具和抽象,简化了企业级应用开发过程。它通过依赖注入来解决对象间的依赖关系,使得代码更加灵活、可测试和可维护。
  2. 高效开发:Spring框架提供了诸多模块,如Spring MVC、Spring Boot等,可以快速构建Web应用和微服务。它提供了一种约定优于配置的开发方式,提高了开发效率。
  3. 提高可扩展性:Spring框架基于接口和模块化设计,能够方便地集成其他开源框架和库。它的松耦合特性使得应用程序更易于扩展和维护。
  4. 丰富的功能:Spring拥有丰富的功能和特性,包括事务管理、安全性、缓存、消息队列、调度等。它为开发人员提供了一系列解决方案,使得应用程序开发更加便捷。

3、功能及使用范围

Spring的功能范围非常广泛,包括但不限于以下方面:

  1. 依赖注入和控制反转:通过依赖注入,Spring容器能够将对象之间的依赖关系管理起来,使得对象的创建和使用解耦,提高代码的灵活性和可测试性。
  2. 面向切面编程:Spring提供了面向切面编程(AOP)的支持,可以将与核心业务逻辑无关的功能(如事务管理、日志记录等)进行横切,提高了代码的重用性和可维护性。
  3. Web开发支持:Spring提供了Spring MVC模块,用于开发Web应用程序。它能够处理HTTP请求和响应,进行URL路由、数据绑定、表单验证、视图解析等操作,简化了Web开发过程。
  4. 数据访问支持:Spring框架提供了对各种数据访问技术的支持,包括JDBC、ORM(如Hibernate、MyBatis)、JPA等。它通过抽象出一套统一的数据访问接口,使得数据库访问更加方便和可替换。
  5. 安全性支持:Spring提供了一套强大的安全性框架,可以进行认证和授权管理。它支持各种身份验证方式,如基于表单的认证、基于角色的访问控制等,保护应用程序的安全性。

总之,Spring框架是Java开发领域最流行的框架之一,它提供了丰富的功能和特性,帮助开发人员构建可靠、高效的企业级应用程序。

一句话概括,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。

二、spring IOC

1、ioc的理解

IoC(Inversion of Control,控制反转)是Spring框架的核心概念之一,也是实现依赖注入的基础。它通过解耦对象之间的依赖关系,使得对象的创建和管理由框架来负责,而不是由开发人员手动管理。

在传统的程序设计中,对象之间的依赖关系通常由开发人员在代码中进行硬编码,对象直接通过关键字(如new)来创建和管理。这种方式存在一些问题,如对象之间的耦合度高、可测试性差、扩展性差等。

而IoC则是一种思想上的转变,它将对象的创建和管理权利交给了框架。具体来说,IoC的核心思想是:通过配置或注解,告诉框架需要创建哪些对象,以及对象之间的依赖关系。然后,框架在应用程序运行时根据配置信息动态地创建和组装对象。

Spring通过IoC容器来实现控制反转。IoC容器是一个用于管理对象的容器,它负责创建、组装、初始化和销毁对象。开发人员只需要配置对象的创建和依赖关系,然后通过容器来获取需要的对象即可。

使用Spring的IoC容器,开发人员可以达到以下几个目的:

  1. 解耦对象之间的依赖关系:通过IoC容器,开发人员只需要关注对象的功能实现,而不需要关心对象是如何创建和组装的。对象之间的依赖关系由容器负责管理,降低了对象之间的耦合度。
  2. 提高代码的可测试性:由于对象的创建和组装由容器来完成,开发人员可以很容易地对对象进行替换或模拟,从而实现单元测试和集成测试。
  3. 增强代码的可扩展性:当需要添加新的功能或模块时,只需要配置新的对象和依赖关系,而不需要修改现有的代码。通过配置方式,可以方便地在不影响现有代码的情况下进行扩展。
  4. 提高代码的灵活性:IoC容器使得对象的创建完全可配置化,可以在运行时根据需要创建不同的实例。同时,框架提供了生命周期管理和依赖解析等功能,使得对象的管理更加便捷。

总而言之,IoC是Spring框架的核心特性之一,它通过控制反转的思想,将对象的创建和依赖关系的管理交给了框架,减少了对象之间的耦合度,提高了代码的可测试性和可扩展性。

2、分析实现

首先创建好我们的maven项目

 设置我们的pom.xml

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

新建

我们用原来的方式写一下

  1. 编写一个接口
    public interface UserService {
        public void updUser();
    }

  2. 再编写一个实现类
    public class UserServiceImpl1 implements UserService {
        public void updUser() {
            System.out.println("修改SQL用户数据");
    }

    我们原来的方式是这样写的

  3. 现在我们添加一个实现类

    public class UserServiceImpl2 implements UserService {
        public void updUser() {
            System.out.println("修改SQL用户数据");
            //修改用户姓名
            System.out.println("修改用户姓名");
        }
    }
  4. 当我们测试调方法的时候只需要改动后面的实现类

  5. 手动实例化的弊端:
    1、一旦依赖的接口实现需要大批量改动,迭代,维护成本高
     2、当接口的实现类不统一,维护成本更高

我们怎么解决这个问题呢?

3、编写bean

首先我们要在maven项目里面的resources文件里面建立一个基于spring的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">

</beans>

 我们在web文件里面建立两个Class类

public class UserAction {
    private UserService us;

    public UserService getUs() {
        return us;
    }

    public void setUs(UserService us) {
        this.us = us;
    }

    public String updUser() {
        us.updUser();
        return "list";
    }

}
public class GoodsAction {
    private UserService us;

    public UserService getUs() {
        return us;
    }

    public void setUs(UserService us) {
        this.us = us;
    }

    public String updUser() {
        us.updUser();
        return "list";
    }

}

编写一个测试类

public class demo1 {
    public static void main(String[] args) {
//        加载spring核心配置文件(建模),获取spring的上下文对象,上下文对象中可以获取任何JavaBean对象
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
        UserAction userAction = (UserAction) context.getBean("userAction");
        userAction.updUser();
        GoodsAction goodsAction = (GoodsAction) context.getBean("goodsAction");
        goodsAction.updUser();
    }
}

在我们的新建的这个spring-context.xml文件里面添加<bean>

<?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">

    <!--凡是在spring核心配置文件spring-context.xml中配置,那么该类JavaBean就交给了spring容器管理-->
    <bean class="com.tgq.ioc.web.UserAction" id="userAction">
        <property name="us" ref="userService1"/>
    </bean>

    <bean class="com.tgq.ioc.web.GoodsAction" id="goodsAction">
        <property name="us" ref="userService2"/>
    </bean>
    <bean class="com.tgq.ioc.service.impl.UserServiceImpl1" id="userService1"/>
    <bean class="com.tgq.ioc.service.impl.UserServiceImpl2" id="userService2"/>
</beans>


 

三、spring IOC的注入方式

spring的ioc有哪些注入方式呢?

  1. set方法属性注入
  2. 构造注入
  3. 接口注入/自动装配

1、set方法属性注入

在我们前面的GoodsAction新添几个属性和get、set方法,一个输出打印的方法toPrint()

public class GoodsAction {
    private UserService us;
    private String name;
    private int age;

    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> getPeoples() {
        return peoples;
    }

    public void setPeoples(List<String> peoples) {
        this.peoples = peoples;
    }

    private List<String> peoples;

    public UserService getUs() {
        return us;
    }

    public void setUs(UserService us) {
        this.us = us;
    }

    public String updUser() {
        us.updUser();
        return "list";
    }
    public void toPrint() {
        System.out.println(this.name);
        System.out.println(this.age);
        System.out.println(this.peoples);
    }

}

在print-context.xml里面设置值,使用set方法属性注入用property

    <bean class="com.tgq.ioc.web.GoodsAction" id="goodsAction">
        <property name="us" ref="userService2">
        </property>
        <property name="name" value="旺财"/>
        <property name="age" value="20"/>
        <property name="peoples">
            <list>
                <value>留守儿童</value>
                <value>情侣</value>
                <value>留守老人</value>
            </list>
        </property>
    </bean>

在测试类里面调用

goodsAction.toPrint();

 

2、构造注入

在我们的User Action里面添加属性及有参无参的构造方法,一个输出打印的方法toPrint()

public class UserAction {
    private UserService us;
    private String name;
    private int age;
    private List<String> hobby;

    public UserAction() {
    }

    public UserAction(String name, int age, List<String> hobby) {
        this.name = name;
        this.age = age;
        this.hobby = hobby;
    }

    public UserService getUs() {
        return us;
    }

    public void setUs(UserService us) {
        this.us = us;
    }

    public String updUser() {
        us.updUser();
        return "list";
    }
    public void toPrint() {
        System.out.println(this.name);
        System.out.println(this.age);
        System.out.println(this.hobby);
    }
}

在print-context.xml里面设置值,使用构造输入需要用constructor-arg标签

    <bean class="com.tgq.ioc.web.UserAction" id="userAction">
        <property name="us" ref="userService1"/>
        <constructor-arg name="name" value="l"/>
        <constructor-arg name="age" value="18"/>
        <constructor-arg name="hobby">
            <list>
                <value>唱</value>
                <value>跳</value>
                <value>rap</value>
            </list>
        </constructor-arg>
    </bean>

继续在测试类里面调用toPrint方法

 

 

3、自动装配

自动装配中byName和byType的区别:

byName:在配置好的文件中变量名不更改就不会报错。按照属性的名称进行自动装配。

  1. 当一个bean的属性名称与其他bean的id匹配时,Spring容器会自动将该bean注入到对应的属性中。
  2. 如果找不到匹配的bean,则会抛出异常。
  3. 在XML配置中,可以使用autowire="byName"@Autowired注解实现byName自动装配。

byType:会在整个spring中寻找JavaBean,按照属性的类型进行自动装配。

  1. 当一个bean的属性的类型与其他bean的class匹配时,Spring容器会自动将该bean注入到对应的属性中。
  2. 如果有多个匹配的bean,则会抛出异常,需要进行更具体的限定或使用@Qualifier注解来解决。
  3. 在XML配置中,可以使用autowire="byType"@Autowired注解实现byType自动装配。

四、spring与tomcat的整合/spring与web容器的整合

我们的xml文件

<?xml version="1.0" encoding="UTF-8"?>
<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">

    <!--凡是在spring核心配置文件spring-context.xml中配置,那么该类JavaBean就交给了spring容器管理-->
    <bean class="com.tgq.ioc.web.UserAction" id="userAction">
        <property name="us" ref="userService1"/>
    </bean>

    <bean class="com.tgq.ioc.web.GoodsAction" id="goodsAction">
        <property name="us" ref="userService2"/>
    </bean>
    <bean class="com.tgq.ioc.service.impl.UserServiceImpl1" id="userService1"/>
    <bean class="com.tgq.ioc.service.impl.UserServiceImpl2" id="userService2"/>
</beans>

编写一个过滤器

@WebListener
public class sprintListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("初始化");
        //spring的上下文
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
//tomcat上下文
        ServletContext servletContext = sce.getServletContext();

        servletContext.setAttribute("sprintContext", context);

    }
}

编写servlet类调用它

@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 {
        //获取到sprint的上下文对象
        ClassPathXmlApplicationContext Context = (ClassPathXmlApplicationContext) req.getServletContext().getAttribute("sprintContext");
        UserService bean = (UserService) Context.getBean("userService1");
        System.out.println(bean);
        bean.updUser();

    }
}

启动服务器就完成了整合
 

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

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

相关文章

华为网络篇 RIP的负载均衡-29

难度2复杂度2 目录 一、实验原理 二、实验拓扑 三、实验步骤 四、实验过程 总结 一、实验原理 RIP是使用跳数&#xff08;经过路由的数量&#xff09;作为metric值的&#xff0c;当网络上存在去往目标的路由有两条以上都是相同metric时&#xff0c;就出现了流量负载均衡。…

星际争霸之小霸王之小蜜蜂(一)

目录 前言 一、安装pygame库 1、pygame库简介 2、在windows系统安装pygame库 二 、搭建游戏框架 1、创建游戏窗口 2、改变窗口颜色 总结 前言 大家应该都看过或者都听说过python神书“大蟒蛇”&#xff0c;上面有一个案例是《外星人入侵》&#xff0c;游戏介绍让我想起了上…

Quivr 基于GPT和开源LLMs构建本地知识库 (更新篇)

一、前言 自从大模型被炒的越来越火之后&#xff0c;似乎国内涌现出很多希望基于大模型构建本地知识库的需求&#xff0c;大概在5月底的时候&#xff0c;当时Quivr发布了第一个0.0.1版本&#xff0c;第一个版本仅仅只是使用LangChain技术结合OpenAI的GPT模型实现了一个最基本的…

Mariadb高可用MHA (四十二)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、概述 1.1 概念 1.2 组成 1.3 特点 1.4 工作原理 二、构建MHA 2.1 ssh免密登录 2.2 主从复制 2.3 MHA安装 2.3.1所有节点安装perl环境 2.3..2 node 2.3.…

clickhouse-监控配置

一、概述 监控是运维的一大利器&#xff0c;要想运维好clickhouse,首先就要对其进行监控&#xff0c;clickhouse有几种监控数据的方式&#xff0c;一种是系统本身监控&#xff0c;一种是通过exporter来监控&#xff0c;下面分别描述一下 二、系统自带监控 我下面会对监控做一…

github拉取自己的私有仓库(Token方式、本地秘钥方式)

github拉取自己的私有仓库(Token方式、本地秘钥方式) 问题背景 日常开发和学习过程中&#xff0c;经常碰到需要从GitHub或者其他类似网站&#xff0c;拉取私有仓代码的需求。本文将总结常用的两种方式&#xff0c;Token方式和本地秘钥方式&#xff0c;方便后续查阅和优化。 …

C++ 11 新特性 学习笔记

1、字符串原始字面量 R“()”用于取消转义&#xff0c;可用于路径表示 运行成功 这两个RawValue起到描述作用&#xff08;可以不写&#xff09;&#xff0c;并不参与输出 注意&#xff0c;这里输出中文乱码 2、nullptr NULL在C中表示0&#xff0c;在非C中表示万能指针 nullpt…

Ordinals 之后,以太坊铭文协议 Ethscriptions 如何再塑 NFT 资产形态

随着加密市场的发展&#xff0c;NFT 赛道逐渐形成了其独有的市场。但在加密熊市的持续影响下&#xff0c;今年 NFT 赛道的发展充满坎坷与挑战。据 NFTGO 数据显示&#xff0c;截至 8 月 7 日&#xff0c;与去年相比&#xff0c;NFT 市值总计约 56.4 亿美元&#xff0c;过去 1 年…

nginx部署时http接口正常,ws接口404

可以这么配置 map $http_upgrade $connection_upgrade {default upgrade; close; }upstream wsbackend{server ip1:port1;server ip2:port2;keepalive 1000; }server {listen 20038;location /{ proxy_http_version 1.1;proxy_pass http://wsbackend;proxy_redirect off;proxy…

人工智能学习框架—飞桨Paddle人工智能

1.人工智能框架 机器学习的三要素&#xff1a;模型、学习策略、优化算法。 当我们用机器学习来解决一些模式识别任务时&#xff0c;一般的流程包含以下几个步骤&#xff1a; 1.1.浅层学习和深度学习 浅层学习(Shallow Learning)&#xff1a;不涉及特征学习&#xff0c;其特征…

python编程小游戏简单的,利用python编写小游戏

这篇文章主要介绍了python编程小游戏简单的&#xff0c;具有一定借鉴价值&#xff0c;需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获&#xff0c;下面让小编带着大家一起了解一下。 虽然大家老调侃程序员没头发&#xff0c;看起来比实际年龄大。但其实咱们却是非常有…

RabbitMq:Topic exchange(主题交换机)的理解和使用

RabbitMq:Topic exchange(主题交换机)的理解和使用 在RabbitMq中&#xff0c;生产者的消息都是通过交换机来接收&#xff0c;然后再从交换机分发到不同的队列中去&#xff0c;在分发的过程中交换机类型会影响分发的逻辑&#xff0c;下面主要讲解一下主题交换机。 ​ 主题交换…

【制作npm包5】npm包制作完整教程,我的第一个npm包

制作npm包目录 本文是系列文章&#xff0c; 作者一个橙子pro&#xff0c;本系列文章大纲如下。转载或者商业修改必须注明文章出处 一、申请npm账号、个人包和组织包区别 二、了解 package.json 相关配置 三、 了解 tsconfig.json 相关配置 四、 api-extractor 学习 五、npm包…

更多openEuler镜像加入AWS Marketplace!

自2023年7月openEuler 22.03 LTS SP1正式登陆AWS Marketplace后&#xff0c;openEuler社区一直持续于在AWS上提供更多版本。 目前&#xff0c;openEuler22.03 LTS SP1 ,SP2两个版本及 x86 arm64两种架构的四个镜像均可通过AWS对外提供&#xff0c;且在亚太及欧洲15个Region开放…

Flink之Partitioner(分区规则)

Flink之Partitioner(分区规则) 方法注释global()全部发往1个taskbroadcast()广播(前面的文章讲解过,这里不做阐述)forward()上下游并行度一致时一对一发送,和同一个算子连中算子的OneToOne是一回事shuffle()随机分配(只是随机,同Spark的shuffle不同)rebalance()轮询分配,默认机…

排序算法-冒泡排序(C语言实现)

简介&#x1f600; 冒泡排序是一种简单但效率较低的排序算法。它重复地扫描待排序元素列表&#xff0c;比较相邻的两个元素&#xff0c;并将顺序错误的元素交换位置&#xff0c;直到整个列表排序完成。 实现&#x1f9d0; 以下内容为本人原创&#xff0c;经过自己整理得出&am…

Python遍历多个子文件夹并基于文件名特征将文件复制到不同的目标文件夹

本文介绍基于Python语言&#xff0c;遍历一个大文件夹中大量的子文件夹&#xff0c;并将每一个子文件夹中大量的文件&#xff0c;按照每一个文件的文件名称的特点与差异&#xff0c;自动创建多个目标文件夹&#xff0c;并将指定文件复制到不同的目标文件夹中的方法。 首先&…

【云原生】【k8s】Kubernetes+EFK构建日志分析安装部署

目录 EFK安装部署 一、环境准备&#xff08;所有主机&#xff09; 1、主机初始化配置 2、配置主机名并绑定hosts&#xff0c;不同主机名称不同 3、主机配置初始化 4、部署docker环境 二、部署kubernetes集群 1、组件介绍 2、配置阿里云yum源 3、安装kubelet kubeadm …

《零基础7天入门Arduino物联网-05》电路基础知识下

配套视频课程&#xff1a;《零基础学Arduino物联网&#xff0c;入门到进阶》 配套课件资料获取&#xff1a;微联实验室 配套学习套件购买&#xff1a;淘宝搜索店铺【微联实验室】 电阻、电容、电感和二极管 电阻 电阻用于电路中&#xff0c;其主要功能在于控制电流的流动和阻…

开源低代码平台Openblocks

网友 HankMeng 想看低代码工具&#xff0c;正好手上有一个&#xff1b; 什么是 Openblocks &#xff1f; Openblocks 是一个开发人员友好的开源低代码平台&#xff0c;可在几分钟内构建内部应用程序。 传统上&#xff0c;构建内部应用程序需要复杂的前端和后端交互&#xff0c;…