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

😉😉 学习交流群:

✅✅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:以上内容,进群免费领取呦~ 💞💞💞💞

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

找免费4K高清图片素材,就上这6个网站

使用图片素材怕侵权&#xff1f;那就上这6个网站&#xff0c;免费下载&#xff0c;4K高清无水印&#xff0c;赶紧收藏起来~ 1、菜鸟图库 https://www.sucai999.com/pic.html?vNTYxMjky 一个很大的素材库&#xff0c;站内主要还是以设计素材为主&#xff0c;像图片素材就有上百…

2023极客大挑战-AGRT战队wp

目录 RE Shiftjmp 点击就送的逆向题 幸运数字 ​编辑 砍树 小黄鸭 flower-or-tea mySelf 是男人就来扎针 听说cpp很难&#xff1f; Easymath 寻找初音未来 Rainbow 浪漫至死不渝 ezandroid Pwn nc_pwntools password ret2text write1 ret2libc ezpwn wr…

Kubernetes基础(九)-标签管理

1 概述 Label&#xff08;标签&#xff09;是Kubernetes系统中一个比较重要的概念&#xff0c;给某个资源对象&#xff08;Node、Pod、Service等&#xff09;定义一个Label&#xff0c;就相当于给它打了一个标签&#xff0c;然后可以通过Label Selector&#xff08;标签选择器…

【C++】类型转换 ⑤ ( 常量和非常量之间的类型转换 - 常量类型转换 const_cast | const 左数右指原则 | 代码示例 )

文章目录 一、const 关键字简介1、const 修饰普通数据2、const 修饰指针 ( 左数右指原则 | 指针常量 | 常量指针 ) 二、常量和非常量 之间的类型转换 - 常量类型转换 const_cast1、常量类型转换 const_cast2、常量不能直接修改3、修改常量值的方法4、特别注意 - 确保指针指向的…

vs2019 - MFC对话框程序的工程名称不支持下划线命名法

文章目录 vs2019 - MFC对话框程序的工程名称不支持下划线命名法概述笔记备注END vs2019 - MFC对话框程序的工程名称不支持下划线命名法 概述 正在写账单分析程序, 用MFC 对话框. 因为比较习惯下划线命名法, 就在向导中给工程名称起了一个my_test这样的名称(下划线命名法, 小…

SpringBoot自动配置注入Bean工具autoconfigure

依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId></dependency> yml配置 student:red: com.ma.config.MinIOConfigProperties spring.factories org.springframework.…

LeetCode Hot100 42.接雨水

题目&#xff1a; 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 方法一&#xff08;相向双指针&#xff09;&#xff1a;竖着计算面积 代码&#xff1a; class Solution {public int trap(int[] he…

Taro3+Vue3重构Mpvue小程序项目踩坑记

1、Taro小程序编译时报错&#xff1b; 原因:页面中存在小程序识别不了的标签&#xff1b;如div解决方法&#xff1a; 将div标签替换成小程序可识别的标签&#xff1b; 安装Taro中提供的插件:tarojs/plugin-html, 使其可被识别&#xff1b; 插件安装教程参考Taro官网&#xff1…

Flink Flink中的合流

一、Flink中的基本合流操作 在实际应用中&#xff0c;我们经常会遇到来源不同的多条流&#xff0c;需要将它们的数据进行联合处理。所以 Flink 中合流的操作会更加普遍&#xff0c;对应的 API 也更加丰富。 二、联合&#xff08;Union&#xff09; 最简单的合流操作&#xf…

「我在淘天做技术」迈步从头越 - 阿里妈妈广告智能决策技术的演进之路

作者&#xff1a;妙临、霁光、玺羽 一、前言 在线广告对于大多数同学来说是一个既熟悉又陌生的技术领域。「搜广推」、「搜推广」等各种组合耳熟能详&#xff0c;但广告和搜索推荐有本质区别&#xff1a;广告解决的是“媒体-广告平台-广告主”等多方优化问题&#xff0c;其中媒…

手机便签app哪个比较好用?

手机便签类软件的种类是比较多的&#xff0c;不管是安卓手机品牌还是苹果手机品牌的手机&#xff0c;在手机的应用商店中搜索“便签”&#xff0c;大家会找到很多便签类软件。那么&#xff0c;手机便签APP哪个比较好用呢&#xff1f; 在选择手机便签APP时&#xff0c;大家比较…

详解原生Spring中的控制反转和依赖注入-构造注入和Set注入

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

Java变量理解

成员变量VS局部变量的区别 语法形式&#xff1a;从语法形式上看&#xff0c;成员变量是属于类的&#xff0c;而局部变量是在代码块或方法中定义的变量或是方法的参数&#xff1b;成员变量可以被 public,private,static 等修饰符所修饰&#xff0c;而局部变量不能被访问控制修饰…

如何高效批量生成条形码?

条形码作为商品、库存和信息管理的基础工具&#xff0c;扮演着至关重要的角色。为了满足用户对于高效、专业、多样化的条形码生成需求&#xff0c;我们推出了一款专业高效的在线条形码生成工具。 网址&#xff1a;https://www.1txm.com/ 多样化条形码支持 易条形支持多种常见…

【算法萌新闯力扣】:旋转链表

力扣题目&#xff1a;旋转链表 开篇 今天是备战蓝桥杯的第25天和算法村开营第3天&#xff01;经过这3天的学习&#xff0c;感觉自己对链表的掌握程度大大地提升&#xff0c;尤其是在帮村里的同学讨论相关问题时。本篇文章&#xff0c;给大家带来一道旋转链表的题目&#xff0c…

leetcode:用队列实现栈(后进先出)

题目描述 题目链接&#xff1a;225. 用队列实现栈 - 力扣&#xff08;LeetCode&#xff09; 题目分析 我们先把之前写的队列实现代码搬过来 用队列实现栈最主要的是实现栈后进先出的特点&#xff0c;而队列的特点是先进先出&#xff0c;那么我们可以用两个队列来实现 一个队…

PTA-6-48 使用面向对象的思想编写程序描述动物

题目&#xff1a; 使用面向对象的思想编写程序描述动物&#xff0c;说明&#xff1a; &#xff08;1) 分析兔子和青蛙的共性&#xff0c;定义抽象的动物类&#xff0c;拥有一些动物共有的属性&#xff1a;名字、颜色、类别&#xff08;哺乳类、非哺乳类&#xff09;&#xff0c…

Redis 事件轮询

1 Redis 为什么快 数据存在内存中, 直接操作内存中的数据单线程处理业务请求避免了多线的上下文切换, 锁竞争等弊端使用 IO 多路复用支撑更高的网络请求使用事件驱动模型, 通过事件通知模式, 减少不必要的等待… 这些都是 Redis 快的原因。 但是这些到了代码层面是如何实现的呢…

出纳常用的月报表,熬夜做了这8份直接用!

做出纳&#xff0c;公司财务的日报表是必不可少的&#xff0c;收支了多少&#xff0c;支出了多少&#xff0c;这些都是要记录下来的&#xff01; 一份出纳日报表通常包含以下内容&#xff1a; 1. 日期&#xff1a;报告涵盖的具体日期&#xff0c;标明是哪一天的财务数据。 2. 收…

【论文阅读】An Experimental Survey of Missing Data Imputation Algorithms

论文地址&#xff1a;An Experimental Survey of Missing Data Imputation Algorithms | IEEE Journals & Magazine | IEEE Xplore 处理缺失数据最简单的方法就是是丢弃缺失值的样本&#xff0c;但这会使得数据更加不完整并且导致偏差或影响结果的代表性。因此&#xff0c;…