一,Spring入门

news2024/12/28 3:24:49

1 Spring简介

Spring是一个轻量级的JavaEE应用框架,对比EJB(Enterprise Java Beans)技术是官方制定的重量级的JavaEE解决方案。EJB的重的表现:编码必须实现EJB内置的组件、必须部署在支持EJB的服务器中才能运行测试。EJB有很强的侵入性,造成开发的代码庞大而且无法通用。Spring框架非侵入性,在开发、测试、扩展方面都远超EJB,已经是JavaEE开发的事实标准。

Spring构建于众多优秀的设计模式之上,比如:工厂设计模式代理设计模式、模板方法设计模式、策略设计模式…。

设计模式:前人总结的,用于解决特定问题的优秀的方案。学习Spring,本质上就是在学这些设计模式解决了哪些问题?

2 工厂设计模式

工厂设计模式:使用工厂类创建对象,替换传统的new创建对象。

new创建对象的问题:

在这里插入图片描述

new模式下:类和类之间是强耦合,如果要扩展程序,必须要修改源码,违背开闭原则。

解决方案:工厂模式(解耦合)

在这里插入图片描述

  1. 创建一个工厂类BeanFactory+配置文件(applicationContext.properties)

    applicationContext.properties

    userService=com.bz.service.impl.UserServiceImpl2
    

    BeanFactory.java

    public class BeanFactory {
        private static Properties env = new Properties();
        static {
            InputStream in = BeanFactory.class.getResourceAsStream("/applicationContext.properties");
            try {
                env.load(in);
                in.close();
            }catch(IOException e){
                e.printStackTrace();
                throw new RuntimeException(e);
            }
    
        }
        //用于创建对象
        public static Object getBean(String id){
            //通过流读取配置文件,获取id和全类名的对应关系
            try {
                //通过反射创建对象
                Class c = Class.forName(env.getProperty(id));
                return c.newInstance();
            }catch(Exception e){
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
    }
    
  2. 将new替换为工厂创建对象

  3. 面向接口编程(定义接口类型的引用)

    UserService service = //面向接口编程
        (UserService) BeanFactory.getBean("userService");
    

总结:工厂模式特点:配置文件+反射+面向接口编程。好处:解耦合

3 第1个Spring程序

Spring框架最基本的使用:对象工厂(容器)。通过Spring工厂创建对象,解耦合从而提高程序的可维护性和扩展性。

3.1 Spring工厂的使用步骤

  1. 搭建开发环境

    1. 新建项目

    2. 导入依赖

      <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>5.2.8.RELEASE</version>
      </dependency>
      
    3. 导入配置文件

      applicationContext.xml 位置任意,建议resources根目录下

  2. 编码+配置

    配置:在applicationContext.xml中配置要创建哪些对象

    <bean id="唯一标识" class="全类名"/>
    

    编码:从Spring工厂中获取对象

    ApplicationContext 工厂类型(接口)

    ​ 实现类:

    ​ ClassPathXmlApplicationContext (非web环境)

    ​ XmlWebApplicationContext (Web环境)

    ​ 方法:

    ​ Object getBean(String id)

3.2 实战

配置:

<!-- new UserServiceImpl1() -->
    <!--<bean id="唯一标识" class="全类名"/>-->
    <bean id="userService" class="com.bz.service.impl.UserServiceImpl1"/>

编码:

//创建Spring工厂
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

//从工厂中获取对象
UserService userService = (UserService) context.getBean("userService");
userService.removeUser(1);

3.3 获取Bean的多种方法

@Test
public void testGetBean(){
    //1 创建Spring工厂
    ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    //2 调用方法从工厂获取对象
    XxxService xxxService = (XxxService) ctx.getBean("xxxService");//根据id从工厂中获取bean
    System.out.println("xxxService = " + xxxService);

    //XxxService xxxService2 = ctx.getBean(XxxService.class);//根据指定的类型从工厂中获取对象,此时要求满足类型的bean最多只能有1个
    //System.out.println("xxxService2 = " + xxxService2);

    //根据id和类型从工厂中获取匹配的bean
    XxxService xxxService3 = ctx.getBean("xxxService", XxxService.class);
    System.out.println("xxxService3 = " + xxxService3);

    System.out.println("=========================");
    //获取指定类型的所有bean
    Map<String, XxxService> beansOfType = ctx.getBeansOfType(XxxService.class);
    beansOfType.forEach((k,v)->{
        System.out.println(k+ "= " + v);
    });


}

4 Spring框架的模块一览

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YeaDoy8l-1673343439887)(Spring day01.assets/image-20200330140458611.png)]

  1. Test:简化Spring项目的测试
  2. 核心容器:Spring作为工厂的实现
  3. AOP:面向切面编程,是面向对象编程有利的补充,可以非侵入的为代码添加额外功能。
  4. 辅助功能
  5. Data Access:提供数据库访问
  6. Web:Spring对JavaWeb开发的支持

Spring族系的框架种类丰富:SpringMVC、SpringData、SpringTask、SpringSecurity、SpringBoot、SpringCloud…。除此之外,Spring框架可以轻松的和其它框架整合,调度其它框架。

5 Spring工厂的实现原理

Spring工厂创建对象:读取配置文件(applicationContext.xml)中的信息,获取class属性配置的全类名,通过反射,默认调用类的无参构造方法创建对象。

bean标签的scope属性控制创建的对象是否是单例的。

​ scope 属性值

​ singleton(默认值)单例 Spring在工厂创建时随即创建对象

​ prototype 多例 Spring工厂默认不主动创建,直到getBean时创建

Spring工厂创建对象为什么默认单例?节省内存资源。

可以被用户共用(单例):dao 、service、 Controller、sqlSessionFactory

不可以被用户公用(多例):connection、sqlSession、ShoppingCart

步骤:

1.引入依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.8.RELEASE</version>
    <scope>runtime</scope>
</dependency>

2.创建配置文件

<?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 -->
    <bean class="com.bz.service.impl.XxxServiceImpl" id="xxxService"></bean>
</beans>

3.创建测试类

package com.bz.test;

import com.bz.service.XxxService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    @org.junit.Test
    public void a(){
        //获取spring中的bean对象
        //1.创建工厂内对象
        //ApplicationContext是Spring常用的工厂类型,继承了Factory接口
        // classpath  main/java main/resources都属于classpath的路径
        ApplicationContext ac= new ClassPathXmlApplicationContext("classpath:application.xml");
        //2.获取bean对象   getBean("id");
        XxxService xxxService = (XxxService) ac.getBean("xxxService");
        xxxService.deleteXxxById(8);
    }
}

6 注入(Injection)

为对象的属性赋值(注入值)。

在这里插入图片描述

6.1 Set注入

本质:通过无参构造方法创建对象后,调用属性的set方法赋值。

前提:类中必须有无参构造方法,属性必须提供set方法。

操作:在bean标签中,定义property子标签给属性赋值。

6.1.1 简单类型(基本类型、包装类+String)

用法:
<property name="属性名">
    <value>基本类型或String数据</value>
</property>

<property name="属性名" value="基本类型或String数据"/>
示例:
<bean id="s1" class="com.bz.entity.Student" scope="prototype">
        <!--<property name="id">
            <value>1</value>
        </property>
        <property name="name">
            <value>xiaohei</value>
        </property>
        <property name="sex">
            <value>true</value>
        </property>
        <property name="score">
            <value>100.0</value>
        </property>-->
        <property name="id" value="1"/>
        <property name="name" value="xiaohei"/>
        <property name="sex" value="true"/>
        <property name="score" value="100.0"/>
    </bean>

6.1.2 自定义类型

用法:
<property name="属性名">
	<ref bean="另外一个Bean的id属性"/>
</property>

<property name="属性名" ref="另外一个Bean的id属性"/>

示例:
 <bean class="com.bz.entity.Address" id="ad">
        <property name="city" value="郑州市"></property>
        <property name="street" value="航海路"></property>
    </bean>
    <bean class="com.bz.entity.Teacher" id="teacher">
        <property name="id" value="1"></property>
        <property name="name" value="2"></property>
        <property name="age" value="33"></property>
        <property name="address" ref="ad"></property>
    </bean>

6.1.3 数组、List、Set类型

用法:
<property name="数组属性名">
	<array>
    	<value>基本类型或者String</value>
        <ref bean="另外一个bean的id"/>
        ...
    </array>
</property>

<property name="数组属性名">
	<list>
    	<value>基本类型或者String</value>
        <ref bean="另外一个bean的id"/>
        ...
    </list>
</property>

<property name="数组属性名">
	<set>
    	<value>基本类型或者String</value>
        <ref bean="另外一个bean的id"/>
        ...
    </set>
</property>

示例:
<bean class="com.bz.entity.User" id="user">
        <property name="id" value="1"></property>
        <property name="name" value="张三"></property>
        <!--数组类型 -->
        <property name="os" >
            <array>
                <value>1</value>
                <value>张三</value>
                <ref bean="ad"></ref>
                <ref bean="teacher"></ref>
            </array>
        </property>
        <!--list类型 -->
        <property name="myList">
            <list>
                <value>1</value>
                <value>试试</value>
                <ref bean="student"></ref>
            </list>
        </property>
        <property name="mhySet">
            <set>
                <value>1</value>
                <value>撒旦</value>
                <ref bean="student"></ref>
            </set>
        </property>
       

    </bean>

注意:array、list、set 3个标签通用,但仍建议针对性使用。

6.1.4 Map类型

用法:
<property name="map属性名">
	<map>
    	<entry key="基本类型或String的key" value="基本类型或String的value"/>
        <entry key="基本类型或String的key" value-ref="bean的id"/>
    </map>
</property>

示例:
 <property name="myMap">
            <map>
                <entry key="1" value="zsf"></entry>
                <entry key="总是丢失" value="wqe"></entry>
                <entry key="asd" value-ref="teacher"></entry>
                <entry key-ref="student" value-ref="ad"></entry>
            </map>
 </property>

6.1.5 Properties类型

用法:
<property name="properties属性名">
	<props>
    	<prop key="键字符串">值字符串</prop>
        ...
    </props>
</property>

示例:
<property name="properties">
    <props>
        <!-- 每一个键值对都是String -->
        <prop key="name">xiaohei</prop>
        <prop key="age">18</prop>
    </props>
</property>

6.2 构造注入

本质:在调用有参构造方法创建对象时,为属性赋值。

前提:类中必须有有参构造方法。

操作:在bean标签中添加constructor-arg子标签进行配置。

6.2.1基本使用

/*当形参数量不同时,直接根据constructor-arg的数量进行匹配,按照constructor-arg标签的顺序给参数赋值。*/

package com.bz.entity;

public class Student {
    private int id;
    private String name;
    private int age;
    private String sex;

    public Student() {
    }

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public Student(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public Student(int id, String name, int age, String sex) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
//省略get/set
}
 <!--通过构造注入为属性赋值-->
 <!--    两个参数的构造方法-->
    <bean class="com.bz.entity.Student" id="s1">
        <constructor-arg value="1"></constructor-arg>
        <constructor-arg value="张三"></constructor-arg>
    </bean>
    <!--    三个参数的构造方法-->
    <bean class="com.bz.entity.Student" id="s2">
        <constructor-arg value="1"></constructor-arg>
        <constructor-arg value="张三"></constructor-arg>
        <constructor-arg value="18"></constructor-arg>
    </bean>

在contructor-arg的基本使用中,Spring会根据数量匹配构造方法,并严格按照顺序为属性赋值。

6.2.2 type属性

type属性设置参数的类型,解决构造方法数量相同类型不同的匹配难题。

public User(Integer id) {
    System.out.println("id = [" + id + "]");
    this.id = id;
}
public User(String name) {
    System.out.println("name = [" + name + "]");
    this.name = name;
}
 <!--一个参数,类型不同 -->
    <bean class="com.bz.entity.Student" id="s4">
        <constructor-arg value="1" type="int"></constructor-arg>
    </bean>
    <bean class="com.bz.entity.Student" id="s5">
        <constructor-arg value="张三" type="java.lang.String"></constructor-arg>
    </bean>

注意:当构造参数多个时,一旦使用type属性,constructor-arg标签的顺序和构造方法参数的顺序不再严格对照。

6.2.3 index属性

index属性用于设置constructor-arg标签的参数顺序,配合type属性一起解决形参数量相同、形参类型相同但顺序不同的匹配难题。

 public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
  <bean class="com.bz.entity.Student" id="s6">
        <constructor-arg value="张三" type="java.lang.String" index="0"></constructor-arg>
        <constructor-arg value="1" type="java.lang.Integer" index="1"></constructor-arg>
    </bean>

对应源码地址:https://download.csdn.net/download/qq_36827283/87378024

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

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

相关文章

ansible作业五

1、jinjia2模板 hosts.j2&#xff0c;内容如下(主机名和ip地址使用变量)&#xff1a; Welcome to 主机名 &#xff01;&#xff08;比如servera.lab.example.com&#xff09; My ip is ip地址. 要求在所有受管主机生成文件&#xff1a;/etc/welcome.txt。 2、角色部分 根据下列…

【Java|golang】2283. 判断一个数的数字计数是否等于数位的值

给你一个下标从 0 开始长度为 n 的字符串 num &#xff0c;它只包含数字。 如果对于 每个 0 < i < n 的下标 i &#xff0c;都满足数位 i 在 num 中出现了 num[i]次&#xff0c;那么请你返回 true &#xff0c;否则返回 false 。 示例 1&#xff1a; 输入&#xff1a;…

EXCEL的几个取整函数对比,int() round() ceiling() ceiling.math()等

1目标 我们处理EXCEL数据经常要遇到以下的需求 取整取倍数按任意数取倍数2 简单取整函数 int() int()只能最简单取整&#xff0c;无任何参数3 round() 四舍五入取整函数 & 整数位取整美化 round() roundup() rounddown() roundup() 和 rounddown() 除了向上和向下取整…

【树莓派4B】搭建HomeAssistant服务端

前言 发挥树莓派的剩余价值&#xff0c;看到知乎有大神利用siri语音控制小米生态的智能家居&#xff0c;他就是利用HA实现的&#xff0c;HA打通不同品牌智能硬件的生态壁垒&#xff0c;而且还是开源&#xff0c;而我刚好手里有一块闲置的树莓派&#xff08;斜眼笑&#xff09;…

【Linux】Linux调试器——gdb的使用以及一些指令

gdb的使用1.背景2.使用3.相关指令1.背景 程序的发布方式有两种&#xff0c;debug模式和release模式 Linux gcc/g出来的二进制程序&#xff0c;默认是release模式 要使用gdb调试&#xff0c;必须在源代码生成二进制程序的时候, 加上 -g 选项 2.使用 使用前先确保自己的Linux上有…

MongoDB的行转列查询

项目组数据需求&#xff0c;需要将Mongo库中的列按日期分组转成行的格式进行显示。Mongo群里问了下&#xff0c;群里热心的大佬小徐 同学果断出手相助&#xff0c;顺利解决了数据问题。现将内容总结梳理如下&#xff0c;帮助有需要的其他同学 表结构 建表语句 db.class.inse…

OSCP_vulnhub digitalworld.local: DEVELOPMENT

DIGITALWORLD.LOCAL: DEVELOPMENT安装&环境下载Description攻击寻找受害主机及端口服务nmap就提示了ctrl u的内容&#xff0c;意思是有隐藏目录搜索slogin_lib.inc.php site:exploit-db.comubantu系统&#xff0c;4.15.0 查找版本漏洞第二种vim sudo提权第三种nano sudo提权…

【前端修炼场】— table 表格的构建

此文为【前端修炼场】第七篇&#xff0c;上一篇文章链接&#xff1a;超链接 文章目录前言一、table 表格的引入二、table 表格属性2.1 边框( border )2.2 宽度( width )2.3 高度( height )2.4 水平对齐( align"left 或 right 或 center )2.5 单元格间距( cellspacing)2.6 …

极客时间学习笔记:04芯片-设计之路

其实一颗芯片项目就是一个标准的产品项目&#xff0c;项目的起点是市场需求分析&#xff0c;接着是设计和制造&#xff0c;如果产品成功完成了商业落地&#xff0c;那么就可以开启下一代产品的迭代升级新周期了。 如果只看芯片设计&#xff0c;它主要包含需求分析、架构设计、逻…

基于Openl启智平台如何提交代码至远程仓库

基于Openl启智平台如何提交代码至远程仓库Openl启智简介快速创建项目克隆项目到本地提交和更新文件Openl启智简介 面向新一代人工智能开源共性技术&#xff0c;面向AI领域的一站式协同开发环境&#xff0c;提供集代码开发环境&#xff0c;数据管理、模型调试、推理和评测为一体…

【Linux】常用基本指令(始)

文章目录&#x1f3aa; Linux下基本指令1.1 &#x1f680; 登录相关指令1.2 &#x1f680; ls1.3 &#x1f680; pwd1.4 &#x1f680; cd1.5 &#x1f680; touch1.6 &#x1f680;mkdir1.7 &#x1f680;rmdir && rm1.8 &#x1f680;man1.9 &#x1f680;cp2.0 &…

windows环境使用PHPStudy安装Redis

windows环境使用PHPStudy安装Redis 目录 安装Redis 开启php redis扩展 查看php扩展 启动redis 连接测试 总结 安装Redis 从软件管理中找到redis&#xff0c;点击安装 开启php redis扩展 选择相应网站管理 > php扩展> redis 查看是否勾选&#xff0c;如果未勾…

力扣刷题记录——412. Fizz Buzz、414. 第三大的数、415. 字符串相加

本专栏主要记录力扣的刷题记录&#xff0c;备战蓝桥杯&#xff0c;供复盘和优化算法使用&#xff0c;也希望给大家带来帮助&#xff0c;博主是算法小白&#xff0c;希望各位大佬不要见笑&#xff0c;今天要分享的是——《412. Fizz Buzz、414. 第三大的数、415. 字符串相加》。…

ccc-sklearn-15-XGBoost(1)

文章目录XGBoost集成算法介绍xgboost 库与sklearn中的XGB APIXGBoost的三大板块梯度提升树-集成算法参数n_estimators建模使用sklearn中的XBGboost&#xff1a;参数subsample使用波士顿房价数据集&#xff0c;来看学习曲线参数eta探索eta参数的性质n_estimators&#xff0c;lea…

【操作系统实验/Golang】实验2:进程(线程)同步

1 实验问题描述以生产者-消费者模型为基础&#xff0c;在Windows环境下创建一个控制台进程&#xff0c;在该进程中创建读者写者线程模拟生产者和消费者。Writer线程写入数据&#xff0c;然后将数据放置在一个空缓冲区buffer中供Reader线程读取。Reader线程从缓冲区中获得数据&a…

YOLOv5+Tesseract-OCR 实现车牌号文本识别

来源&#xff1a;投稿 作者&#xff1a;王同学 编辑&#xff1a;学姐 最近看到了各种各样的车牌识别&#xff0c;觉得挺有意思&#xff0c;自己也简单搞一个玩玩。 1.预期效果2.整体流程3.准备数据集4.训练YOLOv5模型 4.1 下载源码 4.2 安装环境 4.3 修改配置文件 4.4 训练模型…

史上最详python中while语句循环(建议收藏)

名字&#xff1a;阿玥的小东东 学习&#xff1a;python正在学习c 主页&#xff1a;阿玥的小东东 目录 前言 1. 什么是while语句&#xff1f; 2. while语句可以干啥吖 3.while的详细讲解 4.死循环 5.用while语句写个小游戏 前言 今天呢我们来学习一下python中的while语句 …

「Moonbeam社区之声」首期活动回顾

感谢大家参加本次Moonbeam Community Voice「社区之声」新系列活动。Moonbeam计划定期举行这个系列活动&#xff0c;分享Moonbeam社区近期状况&#xff0c;以及来自社区的建议和分享。顾名思义&#xff0c;这是基于社区的分享活动。 Community Voice「社区之声」旨在成为讨论影…

第8章:切片

1.切片的引入 【1】切片(slice)是golang中一种特有的数据类型 【2】数组有特定的用处&#xff0c;但是却有一些呆板(数组长度固定不可变)&#xff0c;所以在 Go 语言的代码里并不是特别常见。相对的切片却是随处可见的&#xff0c;切片是一种建立在数组类型之上的抽象&#xf…

AVL平衡树

前置知识 平衡树 平衡树指的是任意节点的子树的高度差都小于等于 111 的二叉查找树。 因为他是平衡的&#xff0c;我们做树上的操作就可以降到 O(logn)O(log_n)O(logn​) 的时间复杂度。 AVL平衡树 因为对于树有可能进行插入或删除操作&#xff0c;使得树有可能不平衡&…