基于Spring原生框架构建原生Spring的第一个程序!

news2024/12/23 1:23:47

😉😉 学习交流群:

✅✅1:这是孙哥suns给大家的福利!

✨✨2:我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料

🥭🥭3:QQ群:583783824   📚📚  工作微信:BigTreeJava 拉你进微信群,免费领取!

🍎🍎4:本文章内容出自上述:Spring应用课程!💞💞

💞💞5:以上内容,进群免费领取呦~ 💞💞💞💞

第一个Spring应用程序目录

一:第一个Spring程序

1:Spring依赖 

2:Spring核心配置文件

(一):Spring配置文件的要求

(二):Spring核心API

二:程序开发

1:Spring核心配置文件

2:Java代码

3:实现思路

4:补充说明

三:细节分析

1:什么叫做Bean或者组件

2:Spring工厂提供的一些方法

3:Bean标签的特殊写法

四:Spring工厂实现问答


一:第一个Spring程序

1:Spring依赖 

        当前我们都是基于maven进行jar包的管理,我们只需要引入相应的坐标就可以了。maven会自动为我们下载我们所以来的jar包和依赖的依赖进行下载下来,单纯的使用一个Spring的IOC的话,spring-context就够用了,我们使用的版本是spring-context 5.1.4release版本。

        一个spring-context一个junit单元测试,对于我们编写第一个Spring程序就够了!

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
        </dependency>

2:Spring核心配置文件

(一):Spring配置文件的要求

        任何一个框架都需要进行配置文件,Spring框架的配置文件,不要求具体的放置位置,在项目中都可以,也没有具体的配置名称。但是ApplicationContext.xml是Spring官方推荐的配置名称, 日后应用Spring框架时需要进行配置文件路径的配置,需要告诉Spring我们的配置文件的位置在哪里,在创建对象的时候有体现。

在Spring核心配置文件的根标签是一个Beans标签,在里边引入了Spring的一个默认的Schema【书写提示】,方便进行获取标签中的xml语法书写提示

(二):Spring核心API

        ApplicationContext是Spring的核心Api就是指的spring的核心类,这是一个框架最核心的类。这是一个接口。Spring当中最为核心的API就是提出的那个工厂ApplicationContext.java工厂主要作用是对象的创建,他的好处就是解耦合。

        为什么spring进行设计的时候会把核心Api设计成接口:

        Spring设计工厂的时候会设计成接口,接口的最主要的目的是为了屏蔽实现的差异,提供规范性作者考虑到这个工厂会应用到不同的开发环境(例如web与非web),为了屏蔽具体工厂类型之间的差异,Spring将工厂API设计成了接口,可以屏蔽具体工厂之间的差异,提供规范性。

        Spring当中提供的常用的两种工厂类型:
        1:非web环境:ClassPathXmlApplicationContext (main junit)
        2:web环境: XmlWebApplicationContext

        补充说明:
        1:以上是Spring中主要提供了两种类型的工厂
        2:对于web环境,我们很熟悉,非web英勇主要指的是我们的,main函数和Junit单元测试,在main函数和Junit单元测试里边是不启动服务器的,在main函数和Junit当中和在web当中用到的工厂类是不一样的
        3:查看继承关系,idea快捷键是ctrl+h,如果查看继承关系图当中没有这个类的话,是因为没有导入相关的web依赖。添加依赖的快捷键是<dep

        为什么ApplicationContext是一个重量级资源
        1:ApplicationContext工厂的对象会占用大量内存资源。
        2:ApplicationContext工厂对象不会频繁的创建,一个应用只会有一个工厂对象。
        3:ApplicationContext工厂一定是线程安全的。


        重量级资源都具有以下三种特性:
        1:区分一个资源或者对象的轻重量级的区别在于在内存中占用资源的多少,如果一个对象占用内存比较小,就是一个轻量级资源,重量级资源就是会占用大量内存
        2:我们在这值得工厂是他的具体的实现类,主要指的是那两种的实现类,我们不会频繁的创建这两个的对象,一个应用只会创建一个工厂对象
        3:在一个项目中只有一个这个对象,在一个项目中只会有一个这个对象实例,大家都会访问,那么就会产生比并发访问问题,但凡是这种重量级资源可以被多线程多用户访问,说明他们一定是线程安全的,一定做了锁的设置,它是线程安全的,可以被多线程并发访问

二:程序开发

1:Spring核心配置文件

    <!--id属性:起个名字,要求:唯一-->
    <!--class属性:写全限定类名-->
    <bean id = "person" class = "com.pactera.spring.Person"/>

2:Java代码

        //获取spring的工厂对象,这里我们在单元测试当中指定的是非web工厂。
        ApplicationContext clx = new ClassPathXmlApplicationContext("/applicationContext.xml");
        //getBean返回的是Object对象。
        Person person = (Person)clx.getBean("person");//这里边传入的是id值。
        System.out.println(person.getClass());


3:实现思路

        1:创建Bean的类文件。
        2:在ApplicationContext.xml文件中配置该对象属性;
        3:使用spring原生工厂类获取对象;

4:补充说明

        Spring最大的特点就是为我们提供了工厂对象,而这个工厂创建对象起到了一个很好的解耦合的作用,Spring提供的工厂和我们写的工厂本质上是没有区别的,都是创建对象解耦合,对于Spring工厂和通用工厂模式是没有本质区别的

        如果在Junit当中进行测试的话,应该使用ClassPathXmlApplicationContext这个类

三:细节分析

1:什么叫做Bean或者组件

        Spring工厂为我们创建对象,由spring为我们创建的对象叫做bean或者组件(Component)这些指的都是spring工厂为我们创建的对象

2:Spring工厂提供的一些方法

        这些都是Spring工厂为我们提供的获取Bean的方法!

ApplicationContext clx = new ClassPathXmlApplicationContext("/applicationContext.xml");
Person person = (Person)clx.getBean("person");
Person person = clx.getBean("person", Person.class);
Person person1 = clx.getBean(Person.class);
package com.pactera.spring;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestSpring {
    /**
     * 研究目的:用于测试第一个spring的程序。
     * */
    @Test
    public void test03(){
        //获取spring的工厂对象,这里我们在单元测试当中指定的是非web工厂。
        ApplicationContext clx = new ClassPathXmlApplicationContext("/applicationContext.xml");
        Person person = (Person)clx.getBean("person");//这里边传入的是id值。
        System.out.println(person.getClass());
    }
    /**
     * 用于测试Spring工厂为我们提供的其他的方法。
     * 研究目的:Spring工厂对象核心方法getBean方法的重载。
     * */
    @Test
    public void test04(){
        ApplicationContext clx = new ClassPathXmlApplicationContext("/applicationContext.xml");
        //这个重载的getBean的方法的好处在于不用进行强制类型转换了。
        Person person = clx.getBean("person", Person.class);
        System.out.println("person="+person);//person=com.pactera.spring.Person@2a4fb17b
        System.out.println("person="+person.getClass());//person=class com.pactera.spring.Person

        //这个重载的getBean的方法的好处在于不用进行强制类型转换了。
        //如果是这种方式:
            //<bean id = "person" class = "com.pactera.spring.Person"/>
            //<bean id = "person1" class = "com.pactera.spring.Person"/>
        //使用getBean(Person.class)会抛出异常,因为无法保证一个唯一性。
        //使用这个方法的时候必须保证spring配置文件中标签的唯一性。
        //Person person1 = clx.getBean(Person.class);//expected single matching bean but found 2
        /**
         * 在上边创建了一次Person的对象,将这个对象储存了起来,如果下边使用的话直接拿给我们
         * spring当中的当前这个对象只创建了一次,默认是单例设计模式。
         * */
        //System.out.println("person1="+person1);//person1=com.pactera.spring.Person@2a4fb17b

        //获取spring核心配置文件当中所有的id值;
        //---bean的定义:就是在spring核心配置文件当中的bean标签就叫做bean的定义
        //---bean定义的名字就是获取的是:id的值,返回的是是一个名字的数组。
        String[] beanDefinitionNames = clx.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println("beanDefinitionName="+beanDefinitionName);
        }

        //根据类型获取spring配置文件当中的所有的id值
        //---获取工厂类型当中所有Person类的值。获取的都是id
        String[] beanNamesForType = clx.getBeanNamesForType(Person.class);
        for (String id : beanNamesForType) {
            System.out.println("id="+id);
        }

        //判断spring工厂中是否存在这个bean,参数传入的是id值;
        boolean b = clx.containsBeanDefinition("a");
        System.out.println("b="+b);

        //判断spring工厂中是否存在指定id的bean
        System.out.println(clx.containsBean("person"));
        //目前角度来讲这两个方法是没啥区别的。

    }
     /**
     * 研究目的:在spring核心配置文件中的bean标签当中值配置class,spring可以不可以创建对象。
     *        :可以
     *        :spring会不会为他默认分配一个id值呢?
     *        :会,默认是 全限定名+#+num,这个id是spring按照一定的算法生成的。这个num是因为在
     *          配置文件当中可能默认不止配置一次。
     * 应用场景:如果这个bean只使用一次,那么就可以省略id值,如果这个bean会被使用多次,或者被其他bean
     *          就需要进行设置。
     * 研究目的2:name属性在spring配置文件中的使用
     *         :为bean对象定义别名,小名。id是大名,是唯一标识,name属性定义的内容是别名,是小名,
     *           spring当中通过大名和小名都是找到这个bean对象的,可以获取到这个bean对象。
     * */
    @Test
    public void test05(){
        ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
        Person person = ctx.getBean(Person.class);
        System.out.println("person="+person);//person=com.pactera.spring.Person@128d2484
        String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println("beanDefinitionName="+beanDefinitionName);//beanDefinitionName=com.pactera.spring.Person#0
        }
    }
    /**
     *研究目的2:name属性在spring配置文件中的使用
     *        :为bean对象定义别名,小名。id是大名,是唯一标识,name属性定义的内容是别名,是小名,
     *          spring当中通过大名和小名都是找到这个bean对象的,可以获取到这个bean对象。
     *应用场景:id和name有共性,他们相同的地方在于都能使用获取对象,相同的地方在于<bean id,class/>等效与
     * <bean name,class/>都可以定义一个对象。
     *       :区别在于别名可以定义多个,别名之间用,间隔就可以了使用任何一个别名都可以找到这个。,id只能定义一个,
     *         applicationContext.xml(xml语法导致的区别)这个文件当中id属性值命名的时候必须以字母开头,后面可以根字母、数字、下划线、连字符。
     *         name属性定义的时候比较灵活没有要求,可以明明在特殊场景下,比方说\的使用
     *         到了今天xml里的id属性的限制已经不存在了,已经没有这个约束了。
     *        :区别当中的类的 containsBeanDefinition()和containsBean;
     *
     *  */
    @Test
    public void test06(){
        ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
        Person person = (Person)ctx.getBean("p");
        System.out.println("person="+person);//person=com.pactera.spring.Person@2a4fb17b
        Person person1 = (Person)ctx.getBean("p",Person.class);
        System.out.println("person1="+person1);//person=com.pactera.spring.Person@2a4fb17b
        boolean p1 = ctx.containsBean("p1");//既能判断id也能判断name属性。
        System.out.println(p1);//true
        boolean p11 = ctx.containsBeanDefinition("p1");//只能判断id,不能判断name值。
        System.out.println(p11);//false

    }
}


3:Bean标签的特殊写法

1.只配置class属性不配置id属性
<bean class =  "..."/>

        这样是可以的,spring会默认分配一个默认的id值,格式一般是全限定类名+特殊符号+num


四:Spring工厂实现问答

        为什么我们应用了Spring工厂实现类,写了类搞了配置之后,就可以通过工厂创建对象呢?

        当我们定义好类,在applicationContext.xml配置文件中配置好Bean标签之后,创建工厂对象就可以获取相应的配置文件中的对象配置,Spring在Junit或者main方法的程序入口执行之后,创建工厂类对象的时候,Spring会读取applicationContext.xml配置文件,读取之后获取每个bean标签的id和class,根据class采用反射的方式获取对象,并将引用地址赋值给id属性,随后可以通过Spring工厂对象中重载的getBean的方法进行获取对应的对象引用

        反射创建对象调用不调用这个类的构造方法呢?

        一定会的,默认调用的是无参的构造方法。验证方法:在无参构造方法内部加入一个打印语句就可以了。虽然反射创建了对象,但是反射创建对象其实等效于new创建对象,底层也会调用new来创建对象。反射的底层调用的这个对象的无参构造方法

        如果一个类的构造方法是私有的怎么办呢?

        private修饰的内容只可以在本类中进行使用,如果构造器是private的,spring也能够创建对象,实际上底层通过反射调用私有的属性或者方法的,在反射中私有的内容也可以通过暴力反射的方式进行获取

        在开发过程中,是不是所有的对象都会交由spring进行创建?

        理论上来讲是这样的,但是有特例:实体对象(entity)这个对象中的属性是和数据库进行一一对应的,他的对象往往用于封装数据库中的数据,所以一般实体类对象都是交由Mybatis、hibernate等持久层框架进行创建。

😉😉 学习交流群:

✅✅1:这是孙哥suns给大家的福利!

✨✨2:我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料

🥭🥭3:QQ群:583783824   📚📚  工作微信:BigTreeJava 拉你进微信群,免费领取!

🍎🍎4:本文章内容出自上述:Spring应用课程!💞💞

💞💞5:以上内容,进群免费领取呦~ 💞💞💞💞

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

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

相关文章

Linux shell编程学习笔记31:alias 和 unalias 操作 命令别名

目录 0 前言1 定义别名2 查看别名 2.1 查看所有别名2.2 查看某个别名 2.2.1 alias 别名2.2.2 alias | grep 别名字符串2.2.3 使用 CtrlAltE 组合键3 unalias&#xff1a;删除别名4 如何执行命令本身而非别名 4.1 方法1&#xff1a;使用 CtrlAltE 组合键 && unalias4…

Appium自动化测试:sdk版本和手机版本不兼容你就这样做,分分钟解决问题

使用pythonappium执行自动化测试脚本提示报错 环境&#xff1a;python3.7以上&#xff0c;appium1.21.0&#xff1b;设备&#xff1a;华为max8真机 报错信息&#xff1a; android.intent.category.LAUNCHER -f 0x10200000 exited with code 4294967295; Stderr: Security ex…

【Python】python天气数据抓取与数据分析(源码+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

MySQL企业版之Firewall(SQL防火墙)

​​​1. 关于Firewall插件 2. Firewall插件的工作方式 3. Firewall插件测试 4. 总结延伸阅读 1. 关于Firewall插件 Friewall是MySQL企业版非常不错的功能插件之一,启用Firewall功能后,SQL的执行流程见下图示意: 2. Firewall插件的工作方式 Firewall插件的工作机制大概是…

算法基础二

回文数 给你一个整数 x &#xff0c;如果 x 是一个回文整数&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。回文数是指正序&#xff08;从左向右&#xff09;和倒序&#xff08;从右向左&#xff09;读都是一样的整数。 示例 1&#xff1a; 输入&#xff1…

振南技术干货集:znFAT 硬刚日本的 FATFS 历险记(8)

注解目录 1、znFAT 的起源 1.1 源于论坛 &#xff08;那是一个论坛文化兴盛的年代。网友 DIY SDMP3 播放器激起了我的兴趣。&#xff09; 1.2 硬盘 MP3 推了我一把 &#xff08;“坤哥”的硬盘 MP3 播放器&#xff0c;让我深陷 FAT 文件系统不能自拔。&#xff09; 1.3 我…

智慧化工~工厂设备检修和保全信息化智能化机制流程

化工厂每年需要现场检修很多机器&#xff0c;比如泵、压缩机、管道、塔等等&#xff0c;现场检查人员都是使用照相机&#xff0c;现场拍完很多机器后&#xff0c;回办公室整理乱糟糟的照片&#xff0c;但是经常照了之后无法分辨是哪台设备&#xff0c;而且现场经常漏拍&#xf…

ROC及曲线面积汇总学习

目录 ROC基础 生成模拟数据 率的计算 R语言计算测试 ROCR&#xff1a; pROC ROC绘制 单个ROC 两个ROC Logistic回归的ROC曲线 timeROC ROC基础 ROC曲线的横坐标是假阳性率&#xff0c;纵坐标是真阳性率&#xff0c;需要的结果是这个率表示疾病阳性的率&#xff08;…

第六节HarmonyOS UIAbility内页面的跳转和数据传递

一、页面跳转 在一个应用包含一个UIAbility的场景下&#xff0c;可以通过新建多个页面来实现和丰富应用的内容。这会涉及到UIAbility内页面的新建以及UIAbility内页面的跳转和数据传递。 打开DevEco Studio&#xff0c;选择一个Empty Ability工程模板&#xff0c;创建一个工程&…

基于Python+OpenCV+dlib+Tensorflow深度学习的人脸表情识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 人脸表情识别是一种重要的计算机视觉任务&#xff0c;它涉及到对人脸图像中的表情进行分类和理解。在这个系统中&am…

力扣23. 合并 K 个升序链表(java,最小堆解法)

Problem: 23. 合并 K 个升序链表 文章目录 题目描述思路解题方法复杂度Code 题目描述 给你一个链表数组&#xff0c;每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中&#xff0c;返回合并后的链表。 思路 1.对于合并k个有序链表&#xff0c;我们较为容易想…

使用Tensorboard可视化 遇到无法访问此网站

问题&#xff1a; 使用Tensorboard可视化 遇到无法访问此网站 解决方法&#xff1a;后面加上服务器ip[参考] tensorboard --logdir目标目录 --hostxxx.xxx.xxx.xx

简要介绍Spring原生框架与Spring是轻量级框架的原因

&#x1f609;&#x1f609; 学习交流群&#xff1a; ✅✅1&#xff1a;这是孙哥suns给大家的福利&#xff01; ✨✨2&#xff1a;我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 &#x1f96d;&#x1f96d;3&#xff1a;QQ群&#xff1a;583783…

C++ 泛型编程,函数模版和类模版

1.泛型编程 泛型编程&#xff1a;编写与类型无关的通用代码&#xff0c;是代码复用的一种手段。模板是泛型编程的基础 就比如说活字印刷术&#xff0c;就是提供一个模具&#xff0c;然后根据模具来印刷出不同的字。 泛型编程跟着类似&#xff0c;提供一个模版&#xff0c;根据这…

Node.js入门指南(完结)

目录 接口 介绍 RESTful json-server 接口测试工具 会话控制 介绍 cookie session token 上一篇文章我们介绍了MongoDB&#xff0c;这一篇文章是Node.js入门指南的最后一篇啦&#xff01;主要介绍接口以及会话控制。 接口 介绍 接口是前后端通信的桥梁 &#xff0…

【栈和队列(1)(逆波兰表达式)】

文章目录 前言什么是栈(Stack)栈方法栈的模拟实现链表也可以实现栈逆波兰表达式逆波兰表达式在栈中怎么使用 前言 什么是栈(Stack) 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0…

MySQL数据库【一】

博学而笃志&#xff0c;切问而近思 文章目录 数据库简介服务器、数据库以及表的关系连接数据库数据库操作命令创建数据库查看数据库创建语句查看数据库使用数据库修改数据库删除数据库 数据库字符集和校验规则查看系统默认字符集查看系统默认校验规则查看数据库支持的字符集查看…

文本编辑 换行符CRLF/CR/LF问题

参考资料 Linux—CRLF/CR/LF等回车换行符问题详解改行コードCRはなぜ&#xff08;^M&#xff09;で\rなのかテキストファイルの行末に^Mが表示されるLinux 替换^M字符 方法 目录 一. 遇到的问题二. 换行符释义三. 换行符查看四. 去除 ^M4.1 通过文本编辑器转换换行符4.2 在lin…

Html网页threejs显示obj,ply三维图像实例

程序示例精选 Html网页threejs显示obj,ply三维图像实例 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《Html网页threejs显示obj,ply三维图像实例》编写代码&#xff0c;代码整洁&#xff0…

【JavaScript框架】Vue与React中的组件框架概念

组件框架是用于构建应用程序的工具&#xff0c;以便将UI和逻辑划分为单独的可重用组件。目前的组件框架包括React、Vue、Angular、Ember、Svelte等。 Vue和React使用了常见的框架概念&#xff0c;如处理状态、道具、引用、生命周期挂钩、事件等。这两个框架在当今的web开发中被…