【JavaEE进阶篇1】认识Spring、认识IoC、使用spring创建对象

目录

一、什么是Spring

1.1容器

1.2什么是IoC

传统方式创建对象的问题: 类与类之间的耦合性过大

Ioc的优点

Spring IoC容器最核心的功能

1.3DI概念说明(Dependency Injection)

IoC和DI的区别是什么

二、Spring项目的创建

三、Spring的使用(把对象存储到spring当中)

3.1添加spring的配置文件

3.2先创建一个bean对象

3.3在配置文件当中,配置需要存储的对象

3.4从spring容器当中读取出这一个bean

使用ApplicationContext来获取对象

步骤1:得到spring的上下文对象(写法1:使用ApplicationContext)

步骤2:根据spring上下文对象(context)提供的getbean方法来获取到对象

注意事项 

使用BeanFactory来获取对象

ApplicationContext和BeanFactory的区别是什么

1、ApplicationContext是属于BeanFactory的子类。

2、性能不同(饿加载、懒加载)

关于getBean的更多用法

用法1:getBean(传入的字符串是对象的名称)

用法2:根据bean的类型来获取bean

用法3:根据bean name和类型获取bean


一、什么是Spring

先总览概括一下:Spring方法是一个包含了众多工具方法的IoC容器

1.1容器

容器是用来容纳某种物品的基本装置。

例如我们之前学的:

lIst是容器,用来装载一些元素。

Tomcat是容器,用来存放Web应用程序的容器。

那么,同理:Spring也是一个Ioc的容器。


1.2什么是IoC

在聊Ioc之前,我们先聊一下传统new创建对象的问题:

传统方式创建对象的问题: 类与类之间的耦合性过大

举一个例子:如果想要创造一个汽车"car"模型出来,那么,按照传统的思想,是这样创造的:

如果按照代码实现,那么就是这样的:在每一层都new下一层的对象。

       如果想要修改最底层的类的信息,那么就需要沿着调用栈一直往上修改。

       但是,如果新增一个需求:就是要允许用户输入轮胎的属性,来生成不同的轮胎大小,那么这样的话,可能就需要从头到尾一直修改(给每一个方法都新增一个size参数)

因此,可以这样修改:在每一层当中,提供一个属性引用,指向下一层的对象。

public class Car {

    /**
     * 保存下一级调用的引用
     */
    private Frame frame;

    /**
     * 令这个引用指向下一级的对象
     * frame对象@param frame
     */
    public Car(Frame frame){
        this.frame=frame;
    }

    /**
     * 执行下一级的逻辑
     */
    public void init(){
        frame.init();
    }

    //车架类
    static class Frame{
        /***
         * 这个引用指向下一级的轮胎类
         */
       private Tire tire;
       public Frame(Tire tire){
           this.tire=tire;
       }
       public void init(){
           tire.init();
       }
    }

    //轮胎类
    static class Tire{
        private int size;
        
        public Tire(int size){
            this.size=size;
        }
        public void init() {
            System.out.println("轮胎的大小是:"+this.size);
        }
    }

    public static void main(String[] args) {
        //首先,创建一个轮胎类,制定大小
        Tire tire=new Tire(20);
        //然后,创建一个车架类,把轮胎作为属性传递进去
        Frame frame=new Frame(tire);
        //最后,创建一个car类,把frame作为属性传递下去
        Car car=new Car(frame);
    }
}

这样子修改,可以看到,假如需要修改tire,想要新增参数,那么就只用改动两个地方:

一个地方是Tire类的属性,另外一个是main方法当中实例化tire对象的参数

 中间的调用过程全都不用修改。每一层之间的耦合度降低了许多。


Ioc的优点

       实现代码的解耦,把对象(Bean)的生命周期交给了IoC框架来维护,作为程序员无需再次关注了。

       通过代码的实现,可以发现:不再是上级对象创建并且控制下一级对象了。而是把下一级的对象注入到上一级的对象当中。也就是把控制对象生命周期的权力交给了IoC容器。


Spring IoC容器最核心的功能

1、将对象(Bean)储到Spring(容器)当中。

2、将对象(Bean)从Spring(容器)当中出来。


1.3DI概念说明(Dependency Injection)

翻译成中文就是:依赖注入的意思。

指的是把对象(Bean)注入IoC容器当中,如果外界想要获取这一个对象,就可以从IoC当中获取


IoC和DI的区别是什么

       IoC是一种思想,这种思想就是:控制反转,把对象的生命周期交给IoC容器。DI就是IoC思想的一种实现,也就是IoC思想是依靠DI这种方式来实现的。

       这就好像乐观锁和CAS的关系一样:乐观锁这种思想是依靠CAS这种机制来实现的


二、Spring项目的创建

第一步:创建一个maven项目;

第二步:在maven项目当中添加spring支持

这两个支持分别是:(spring-context/spring-beans)

第三步:编写一个测试的main方法

在maven当中导入的内容如下: 

 <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.15.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.2.15.RELEASE</version>
        </dependency>
    </dependencies>

然后,创建一个App类,用于测试后面的代码。

public class Application {



    public static void main(String[] args) {
        System.out.println("hello spring");
    }
}

三、Spring的使用(把对象存储到spring当中)

3.1添加spring的配置文件

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

3.2先创建一个bean对象

任意新建一个对象即可。


3.3在配置文件当中,配置需要存储的对象

需要使用到bean标签,

里面要指定id属性:这个属性的含义是指定对象的名称

还需要指定class属性:这个属性的含义是类的文件路径。

在spring容器当中,bean的存储就是按照:一个类似于哈希表的结构:

Map<String,Object> map

其中,id属性对应的对象名称相当于一个key,对应的对象相当于一个value

<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">
     <!--把一个user对象存放到容器当中-->
    <bean id="user" class="Bean.User"/>
</beans>

3.4从spring容器当中读取出这一个bean

使用ApplicationContext来获取对象

步骤1:得到spring的上下文对象(写法1:使用ApplicationContext)

 //需要在此处得到spring配置文件的名称
 ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");

步骤2:根据spring上下文对象(context)提供的getbean方法来获取到对象

//此处的对象名称一定要和配置文件当中的id一样
User user= (User) context.getBean("user");

此后,就可以通过这个user对象来进行调用了。

另外,还可以使用BeanFactory来获取对象。

代码整体实现:

public static void main(String[] args) {
        //需要在此处得到spring配置文件的名称
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        //此处的对象名称一定要和配置文件当中的id一样
        User user= (User) context.getBean("user");
        user.say("张三");
    }

注意事项 

1、一个容器当中不可以出现相同的id名称,否则运行时候会报错。

2、getBean方法传入的参数一定要在xml文件当中指定、


使用BeanFactory来获取对象

跟上面的步骤类似,也是需要经历下面的几个步骤

public static void main(String[] args) {
        //得到bean工厂
        BeanFactory beanFactory=new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
        //获取bean对象
        User user= (User) beanFactory.getBean("user");
        //使用bean
        user.say("李四");
    }

ApplicationContext和BeanFactory的区别是什么

相同点:都可以从Ioc容器当中获取bean。

不同点:

1、ApplicationContext是属于BeanFactory的子类。

        ApplicationContext继承于BeanFactory。BeanFactory只提供了最基础的访问bean的方法,而ApplicationContext除了拥有BeanFactory以外,还拥有一些其他的机制,例如:支持国际化等等.....后面的文章会说明


2、性能不同(饿加载、懒加载)

       ApplicationContext采用的是"饿加载"的方式来进行加载的。而BeanFactory采用的是"懒加载"的方式来进行加载的。

      当在xml的配置文件当中配置了多个bean的时候,

       如果使用ApplicationContext一次加载所有的bean

       如果使用BeanFactory,那么仅仅只会在调用getBean方法时候指定了对应的bean的名称之后,找到了Bean对象,才会进行加载。


关于getBean的更多用法

用法1:getBean(传入的字符串是对象的名称)

        //获取bean对象
        User user= (User) beanFactory.getBean("user");

用法2:根据bean的类型来获取bean

此时传入getBean方法的参数就是需要获取类型的字节码对象(class对象)

public static void main(String[] args) {
        //得到bean工厂
        BeanFactory beanFactory=new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
        //无需强制类型转换
        User user=beanFactory.getBean(User.class);
        user.say("小明");
    }

好处:避免了强制类型转换。

坏处:当同一个类在spring容器当中注入了两个不同的对象的时候,就会抛出异常。

 

抛出异常:NoUniqueBeanDefinitionException 


用法3:根据bean name和类型获取bean

 public static void main(String[] args) {
        //得到bean工厂
        BeanFactory beanFactory=new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
        //无需强制类型转换
        //传入的第一个参数为bean的名称:对应到bean属性的id值
        //传入的第二个参数为获取对象的类型
        User user=beanFactory.getBean("user",User.class);
        user.say("小明");
    }

 这一种做法,相比于前两种,代码的健壮性明显提升了。


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

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

相关文章

ChatGPT是如何训练得到的?通俗讲解

首先声明喔&#xff0c;我是没有任何人工智能基础的小白&#xff0c;不会涉及算法和底层原理。 我依照我自己的简易理解&#xff0c;总结出了ChatGPT是怎么训练得到的&#xff0c;非计算机专业的同学也应该能看懂。看完后训练自己的min-ChatGPT应该没问题 希望大牛如果看到这…

stm32外设-中断详解

0. 写在最前 本栏目笔记都是基于stm32F10x 1. 中断是啥&#xff1f; 什么是中断&#xff1a;CPU在处理某一事件A时&#xff0c;发生的另外某一事件B请求CPU去处理&#xff08;产生了中断&#xff09;&#xff0c;随后CPU暂时中断当前正在执行的任务&#xff0c;去对事件B进行处…

Java的二叉树、红黑树、B+树

数组和链表是常用的数据结构&#xff0c;数组虽然查找快&#xff08;有序数组可以通过二分法查找&#xff09;&#xff0c;但是插入和删除是比较慢的&#xff1b;而链表&#xff0c;插入和删除很快&#xff08;只需要改变一些引用值&#xff09;&#xff0c;但是查找就很慢&…

【C#】组件化开发,调用dll组件方法

系列文章 C#项目–业务单据号生成器&#xff08;定义规则、自动编号、流水号&#xff09; 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/129129787 C#项目–开始日期结束日期范围计算&#xff08;上周、本周、明年、前年等&#xff09; 本文链接&…

快排函数 -- qsort函数(Quick Sort)

文章目录&#x1f50e;1.qsort函数简介&#x1f4a1;1.1.函数原型&#x1f4a1;1.2.参数含义&#x1f50e;2.比较函数介绍&#x1f50e;3.比较函数使用案例&#x1f4a1;3.1.整型数组&#x1f4a1;3.2.浮点型数组&#x1f4a1;3.3.结构体类型 - 字符串&#x1f50e;4.利用冒泡排…

震撼,支持多模态模型的ChatGPT 4.0发布了

最近几个月&#xff0c;互联网和科技圈几乎ChatGPT刷屏了&#xff0c;各种关于ChatGPT的概念和应用的帖子也是围绕在周围。当去年年底ChatGPT发布的那几天&#xff0c;ChatGPT确实震撼到了所有人&#xff0c;原来AI还可以这么玩&#xff0c;并且对国内的那些所谓的人工智能公司…

Tesla都使用什么编程语言?

作者 | 初光 出品 | 车端 备注 | 转载请阅读文中版权声明 知圈 | 进“汽车电子与AutoSAR开发”群&#xff0c;请加微“cloud2sunshine” 总目录链接>> AutoSAR入门和实战系列总目录 带着对更美好未来的愿景&#xff0c;特斯拉不仅成为有史以来最有价值的汽车公司&…

多线程(初阶)

文章目录一.初始线程(Thread)1.1.线程的概念1.2.线程的优势1.2.1.线程比进程更轻量1.2.2.并发编程1.3.线程和进程的区别二.Thread类方法2.1. java 中创建线程的方法2.1.1. 继承Thread,重写run2.1.2. 实现Ruuable接口2.1.3. 使用匿名内部类,继承Thread2.1.4.使用匿名内部类,实现…

[蓝桥杯单片机]——八到十一届初赛决赛客观题

第八届初赛 一、填空题 采用外部12MHz晶振&#xff0c;经过系统12分频时定时器获得最大定时长度&#xff0c;此时定时器定时脉冲为1MHz&#xff0c;周期为1s&#xff0c;而定时器计时均为16位加法计数器&#xff0c;即计时长度为。 二、 选择题 ①带阻滤波器是指能通过大多数频…

处理窄区路径规划的业务问题

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 TODO:写完再整理 文章目录系列文章目录前言一、通过栅格地图的处理解决二、使用bug绕障的方式走出窄区&#xff0c;或者结合边界图形参考bug算法沿边出来三、使用维诺图计…

字符串函数和内存函数

&#x1f355;博客主页&#xff1a;️自信不孤单 &#x1f36c;文章专栏&#xff1a;C语言 &#x1f35a;代码仓库&#xff1a;破浪晓梦 &#x1f36d;欢迎关注&#xff1a;欢迎大家点赞收藏关注 字符串函数和内存函数 文章目录字符串函数和内存函数前言1. 字符串函数介绍1.1 s…

【MySQL】MySQL的优化(一)

目录 查看SQL执行频率 定位低效率执行SQL 定位低效率执行SQL-慢查询日志 定位低效率执行SQL-show processlist 查看SQL执行频率 MySQL 客户端连接成功后&#xff0c;通过 show [session|global] status 命令可以查看服务器状态信息。通 过查看状态信息可以查看对当…

jvm类与类加载

1.类加载过程&#xff1a; 首先要加载某个类一定是出于某种目的&#xff0c;比如要运行java程序&#xff0c;那么久必须加载主类才能运行其中的方法&#xff0c;所以一般在这些情况下&#xff0c;如果类没有被加载&#xff0c;就会自动被加载&#xff1a; 1.使用new创建对象时 …

MyBatis开发环境搭建

1.创建工程 2.引入相关的依赖 pom.xml <dependencies><!--1.引入mybatis包--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.6</version></dependency><!--2.单元…

FPGA和IC设计怎么选?哪个发展更好?

很多人纠结FPGA和IC设计怎么选&#xff0c;其实往小了说&#xff0c;要看你选择的具体是哪个方向岗位。往大了说&#xff0c;将来你要是走更远&#xff0c;要成为大佬&#xff0c;那基本各个方向的都要有涉及的。 不同方向就有不同的发展&#xff0c;目前在薪资上IC设计要比FP…

Qt之高仿QQ系统设置界面

QQ或360安全卫士的设置界面都是非常有特点的,所有的配置项都在一个垂直的ScrollArea中,但是又能通过左侧的导航栏点击定位。这样做的好处是既方便查看指定配置项,又方便查看所有配置项。 一.效果 下面左边是当前最新版QQ的系统设置界面,右边是我的高仿版本,几乎一毛一样…

【Linux】进程的程序替换

文章目录1. 程序替换1.创建子进程的目的是什么&#xff1f;2.了解程序是如何进行替换的3. 程序替换的基本原理当创建进程的时候&#xff0c;先有进程数据结构&#xff0c;还是先加载代码和数据&#xff1f;程序替换是整体替换&#xff0c;不是局部替换execl 返回值4. 替换函数1…

【三维几何学习】从零开始网格上的深度学习-2:卷积网络CNN篇(Pytorch)

本文参加新星计划人工智能(Pytorch)赛道&#xff1a;https://bbs.csdn.net/topics/613989052 从零开始网格上的深度学习-2:卷积网络CNN篇引言一、概述1.1 卷积操作简述1.2 网格上的面卷积二、核心代码2.1 面卷积2.2 网络框架三、基于CNN的网格分类3.1 分类结果3.2 全部代码引言…

FPGA之时钟规划图解

目录 一、前言 二、时钟规划概念 三、时钟规划的模块 四、时钟规划之时钟单元布局 4.1 BUFG 4.2 BUFH 4.3 BUFR 4.4 BUFIO 五、时钟规划之时钟单元走线 5.1 BUFG->BUFH 5.2 BUFR->FF 5.3 BUFIO->FF 一、前言 对于vivado这类使用verilog语言的进…

《Netty》从零开始学netty源码(七)之NioEventLoop.selectStrategy

NioEventLoop是一个事件轮询器&#xff0c;在它的run方法中其实是一个for死循环&#xff0c;不断重复三个过程&#xff1a;1. 获取IO事件&#xff0c;2. 处理IO事件&#xff0c;3. 处理任务队列中的task&#xff0c;而SelectStractegy就是用于第一步获取IO事件&#xff0c;它的…