SSM学习之Spirngday01
创始人
2025-05-28 03:03:54
0

Spring

Spirng是什么?
在这里插入图片描述
大佬讲解点击急用
spirng是轻量级开源的j2ee框架 是一个容器框架,用来装javabean(java对象) 她不仅是容器框架还是中间层框架 实际还是利用装JavaBean aop这个功能 连接其他框架 structs和hibenate粘在一起使用 因为spring IOC帮我们造出对象 而不用我们自己去new 所以他能帮我们融合其他框架的对象 而不用沃尔玛呢一个个造出来

1.Spring相关概念

Spring发展到今天已经形成了一种开发的生态圈,Spring提供了若干个项目,每个项目用于完成特定的功能。

  • Spring已形成了完整的生态圈,也就是说我们可以完全使用Spring技术完成整个项目的构建、设计与开发。

  • Spring有若干个项目,可以根据需要自行选择,把这些个项目组合起来,起了一个名称叫全家桶,如下图所示

  • 在这里插入图片描述
    说明:

图中的图标都代表什么含义,可以进入https://spring.io/projects网站进行对比查看。
在这里插入图片描述

这些技术并不是所有的都需要学习,额外需要重点关注Spring FrameworkSpringBootSpringCloud:

  • Spring Framework:Spring框架,是Spring中最早最核心的技术,也是所有其他技术的基础。重点:其他所有技术依赖他执行底层框架设计框架所有东西放在上面运行
  • SpringBoot:Spring是来简化开发,而SpringBoot是来帮助Spring在简化的基础上能更快速进行开发。
  • SpringCloud:这个是用来做分布式之微服务架构的相关开发。

除了上面的这三个技术外,还有很多其他的技术,也比较流行,如SpringData,SpringSecurity等,这些都可以被应用在我们的项目中。我们今天所学习的Spring其实指的是Spring Framework

1.2 Spring系统架构

1.2.1 系统架构图

  • Spring Framework是Spring生态圈中最基础的项目,是其他项目的根基。

  • Spring Framework的发展也经历了很多版本的变更,每个版本都有相应的调整 这里我们才有SpringFramework4.0技术
    在这里插入图片描述
    (1)核心层

  • Core Container:核心容器,这个模块是Spring最核心的模块,其他的都需要依赖该模块 对于容器而言就是装东西 java程序就一种东西可以装 就是对象 Spring就是用来管对象

(2)AOP层 aop依赖核心容器执行core container

  • AOP:面向切面编程,它依赖核心层容器,目的是在不改变原有代码的前提下对其进行功能增强 aop是教你程序应该如何做
  • Aspects:AOP是思想,Aspects是对AOP思想的具体实现 它是真正实现了aop

(3)数据层

  • Data Access:数据访问,Spring全家桶中有对数据访问的具体实现技术
  • Data Integration:数据集成,Spring支持整合其他的数据层解决方案,比如Mybatis
  • Transactions:事务,Spring中事务管理是Spring AOP的一个具体实现,也是后期学习的重点内容

(4)Web层

  • 这一层的内容将在SpringMVC框架具体学习

(5)Test层

  • Spring主要整合了Junit来完成单元测试和集成测试

1.2.2学习路线

介绍完Spring的体系结构后,从中我们可以得出对于Spring的学习主要包含四部分内容,分别是:

  • Spring的IOC/DI
  • Spring的AOP
  • AOP的具体应用,事务管理
  • IOC/DI的具体应用,整合Mybatis

在这里插入图片描述
在这里插入图片描述

1.3 Spring核心概念

1.3.1 目前项目中的问题

要想解答这个问题,就需要先分析下目前咱们代码在编写过程中遇到的问题:
在这里插入图片描述
(1)业务层需要调用数据层的方法,就需要在业务层new数据层的对象

(2)如果数据层的实现类发生变化,那么业务层的代码也需要跟着改变,发生变更后,都需要进行编译打包和重部署
(3)所以,现在代码在编写的过程中存在的问题是:耦合度偏高
针对这个问题,该如何解决呢?

我们就想,如果能把框中的内容给去掉,不就可以降低依赖了么,但是又会引入新的问题,去掉以后程序能运行么?

答案肯定是不行,因为bookDao没有赋值为Null,强行运行就会出空指针异常。

所以现在的问题就是,业务层不想new对象,运行的时候又需要这个对象,该咋办呢?

针对这个问题,Spring就提出了一个解决方案:

使用对象时,在程序中不要主动使用new产生对象,转换为由"外部"提供对象

这种实现思就是Spring的一个核心概念

1.3.2 IOC、IOC容器、Bean、DI

在这里插入图片描述
在这里插入图片描述
原来是new出来的 现在不能new的 来个ioc容器 把对象放入ioc容器中。
由ioc容器帮你创建对象 对象由ioc容器提供 dao对象bookdao可以放入 bookserviceimp也能放入啊 IOC容器可以管理大量对象创建和初始化 你对象不用自己造 我帮你造,我造给你的对象叫bean对象 我给你
在这里插入图片描述
现在我们程序运行需要Service对象 IOC容器直接调用Service对象 你把程序运行起来看看 这个程序有问题 你的service方法需要dao对象调用的方法 而你的save方法需要dao对象方法才能运行 你运行还是报错 IOC看到你的Service对象依赖dao对象运行 巧了 这两对象都在ioc容器中 所以ioc容器把这活给你干了 也就是service和dao对象的依赖关系帮你干了 也就是绑定上
也就是在这里插入图片描述
你现在要的dao对象直接给到你 这样你就能直接运行了 这种思想叫IDI 依赖注入
在这里插入图片描述
容器中如果bean与bean之间存在依赖关系 则IOC容器自动帮你绑定好 绑定关系的过程叫依赖注入

  1. IOC(Inversion of Control)控制反转

(1)什么是控制反转呢?

  • 使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转。
    • 业务层要用数据层的类对象,以前是自己new
    • 现在自己不new了,交给别人[外部]来创建对象
    • 别人[外部]就反转控制了数据层对象的创建权
    • 这种思想就是控制反转
    • 别人[外部]指定是什么呢?继续往下学

(2)Spring和IOC之间的关系是什么呢?

  • Spring技术对IOC思想进行了实现
  • Spring提供了一个容器,称为IOC容器,用来充当IOC思想中的"外部"
  • IOC思想中的别人[外部]指的就是Spring的IOC容器
    一句话 由主动new出对象转换为IOC容器提供对象

(3)IOC容器的作用以及内部存放的是什么?

  • IOC容器负责对象的创建、初始化等一系列工作,其中包含了数据层和业务层的类对象
  • 被创建或被管理的对象在IOC容器中统称为Bean
  • IOC容器中放的就是一个个的Bean对象

(4)当IOC容器中创建好service和dao对象后,程序能正确执行么?

  • 不行,因为service运行需要依赖dao对象
  • IOC容器中虽然有service和dao对象
  • 但是service对象和dao对象没有任何关系
  • 需要把dao对象交给service,也就是说要绑定service和dao对象之间的关系
  • 像这种在容器中建立对象与对象之间的绑定关系就要用到DI:
  1. DI(Dependency Injection)依赖注入

1)什么是依赖注入呢?

  • 在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入
    • 业务层要用数据层的类对象,以前是自己new
    • 现在自己不new了,靠别人[外部其实指的就是IOC容器]来给注入进来
    • 这种思想就是依赖注入

(2)IOC容器中哪些bean之间要建立依赖关系呢?

  • 这个需要程序员根据业务需求提前建立好关系,如业务层需要依赖数据层,service就要和dao建立依赖关系

  • 介绍完Spring的IOC和DI的概念后,我们会发现这两个概念的最终目标就是:充分解耦,具体实现靠:

  • 使用IOC容器管理bean(IOC)

  • 在IOC容器内将有依赖关系的bean进行关系绑定(DI)

  • 最终结果为:使用对象时不仅可以直接从IOC容器中获取,并且获取到的bean已经绑定了所有的依赖关系.

1.3.3 核心概念

1.3.3 核心概念小结

这节比较重要,重点要理解什么是IOC/DI思想什么是IOC容器什么是Bean

(1)什么IOC/DI思想?

  • IOC:控制反转,控制反转的是对象的创建权
  • DI:依赖注入,绑定对象与对象之间的依赖关系

(2)什么是IOC容器?

Spring创建了一个容器用来存放所创建的对象,这个容器就叫IOC容器

(3)什么是Bean?

容器中所存放的一个个对象就叫Bean或Bean对象在这里插入图片描述

2.1.1 入门案例思路分析

idea中source目录和resource目录的作用 resource添加依赖 source主要用来保存java文件且打包后汇编编译成class文件 而resource则是直接复制不会变成class文件

(1)Spring是使用容器来管理bean对象的,那么管什么?

  • 主要管理项目中所使用到的类对象,比如(Service和Dao)

(2)如何将被管理的对象告知IOC容器?

  • 使用配置文件 也就是配置bean

(3)被管理的对象交给IOC容器,要想从容器中获取对象,就先得思考如何获取到IOC容器?

  • Spring框架提供相应的接口

(4)IOC容器得到后,如何从容器中获取bean?

  • 调用Spring框架提供对应接口中的方法

(5)使用Spring导入哪些坐标?

用别人的东西,就需要在pom.xml添加对应的依赖

applicationContext.xml 文件配置
项目结构
在这里插入图片描述

* 










BookDaoImpl

public class BookDaoImpl implements BookDao {public void save() {System.out.println("book dao save ...");}
}

BookServiceImpl

public class BookServiceImpl implements BookService {private BookDao bookDao = new BookDaoImpl();public void save() {System.out.println("book service save ...");bookDao.save();}
}

App2.java

import org.springframework.context.support.ClassPathXmlApplicationContext;public class App2 {public static void main(String[] args) {
//        步骤6:获取IOC容器 创建  ApplicationContext接口的实现类 括号内填写配置文件路径配置对应的容器 getBean 方法的参数要和 spring-config.xml 配置文件中的 id 对应ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 步骤7:从容器中获取对象进行方法调用 获取bean
//        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
//        bookDao.save();BookService bookService = (BookService) ctx.getBean("bookService");bookService.save();}
}

book service save …
book dao save …

2.2.1 入门案例思路分析

(1)要想实现依赖注入,必须要基于IOC管理Bean

  • DI的入门案例要依赖于前面IOC的入门案例

(2)Service中使用new形式创建的Dao对象是否保留?

  • 需要删除掉,最终要使用IOC容器中的bean对象

(3)Service中需要的Dao对象如何进入到Service中?

  • 在Service中提供方法,让Spring的IOC容器可以通过该方法传入bean对象
  • 比如setBookDao方法

(4)Service与Dao间的关系如何描述?

  • 使用配置文件

2.2.2 入门案例代码实现

需求:基于IOC入门案例,在BookServiceImpl类中删除new对象的方式,使用Spring的DI完成Dao层的注入

1.删除业务层中使用new的方式创建的dao对象

2.在业务层提供BookDao的setter方法

3.在配置文件中添加依赖注入的配置

4.运行程序调用方法

步骤1: 去除代码中的new

在BookServiceImpl类中,删除业务层中使用new的方式创建的dao对象
BookServiceimpl.java

public class BookServiceImpl implements BookService {//5.删除业务层中使用new的方法创建的dao对象private BookDao bookDao;public void save() {System.out.println("book service save ...");bookDao.save();}//6.提供对应的set方法 这个方法是谁调用的?重点 这个set方法是容器执行的public void setBookDao(BookDao bookDao) {this.bookDao = bookDao;}
}
步骤2:为属性提供setter方法

在BookServiceImpl类中,为BookDao提供setter方法

public class BookServiceImpl implements BookService {//5.删除业务层中使用new的方法创建的dao对象private BookDao bookDao;public void save() {System.out.println("book service save ...");bookDao.save();}//6.提供对应的set方法 这个方法是谁调用的?重点 这个set方法是容器执行的public void setBookDao(BookDao bookDao) {this.bookDao = bookDao;}
}
步骤3:修改配置完成注入

在配置文件中添加依赖注入的配置















注意:配置中的两个bookDao的含义是不一样的

  • name="bookDao"中bookDao的作用是让Spring的IOC容器在获取到名称后,将首字母大写,前面加set找对应的setBookDao()方法进行对象注入
  • ref="bookDao"中bookDao的作用是让Spring能在IOC容器中找到id为bookDao的Bean对象给bookService进行注入
  • 综上所述,对应关系如下:
  • 在这里插入图片描述
  • 这两对象都在ioc容器帮你创建好并在容器中中 所以ioc容器把这活给你干了 也就是service和dao对象的依赖关系帮你干了 也就是绑定上也就是你现在要的dao对象直接给到你 这样你就能直接运行了 这种思想叫IDI 依赖注入 容器中如果bean与bean之间存在依赖关系 则IOC容器自动帮你绑定好 绑定关系的过程叫依赖注入

3.1.1 bean基础配置(id与class)

在这里插入图片描述
这其中需要大家重点掌握的是:bean标签的id和class属性的使用

思考:

  • class属性能不能写接口如BookDao的类全名呢?

答案肯定是不行,因为接口是没办法创建对象的。

  • 前面提过为bean设置id时,id必须唯一,但是如果由于命名习惯而产生了分歧后,该如何解决?

3.1.2 bean的name属性

环境准备好后,接下来就可以在这个环境的基础上来学习下bean的别名配置,首先来看下别名的配置说明:
在这里插入图片描述

步骤1:配置别名

打开spring的配置文件applicationContext.xml

 

步骤2:根据名称这里可以用name 而不是id 容器中获取bean对象

public class AppForName {public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");//此处根据bean标签的id属性和name属性的任意一个值来获取bean对象BookService bookService = (BookService) ctx.getBean("service4");bookService.save();}

运行结果
在这里插入图片描述

3.1.3 bean作用范围scope配置

关于bean的作用范围是bean属性配置的一个重点内容。

看到这个作用范围,我们就得思考bean的作用范围是来控制bean哪块内容的?

我们先来看下`bean作用范围的配置属性

3.1.3.1 验证IOC容器中对象是否为单例

验证思路

​ 同一个bean获取两次,将对象打印到控制台,看打印出的地址值是否一致。

具体实现

  • 创建一个AppForScope的类,在其main方法中来验证`:
* public class AppForScope {public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");BookDao bookDao1 = (BookDao) ctx.getBean("bookDao1");BookDao bookDao2 = (BookDao) ctx.getBean("bookDao1");System.out.println(bookDao1);System.out.println(bookDao2);// 这里是运行结果//com.itheima.dao.impl.BookDaoImpl@25bbe1b6//com.itheima.dao.impl.BookDaoImpl@25bbe1b6 也就是说Spring默认的是单例模式//        com.itheima.dao.impl.BookDaoImpl@25bbe1b6
//        com.itheima.dao.impl.BookDaoImpl@5702b3b1 若applicationContext.xml 中 改为scope="prototype"则不是单例模式创建的是两个对象}
}

获取到结论后,问题就来了,那如果我想创建出来非单例的bean对象,该如何实现呢?

3.1.3.2 配置bean为非单例

在Spring配置文件中,配置scope属性来实现bean的非单例创建

  • 在Spring的配置文件中,修改的scope属性
    applicationContext.xml 将scope设置为singleton scope属性默认是singleton 单例模式默认创建一个对象 改为prototype之后每次获取就创建一个新的对象

3.1.3.3 scope使用后续思考

介绍完scope属性以后,我们来思考几个问题:

  • 为什么bean默认为单例?
    • bean为单例的意思是在Spring的IOC容器中只会有该类的一个对象
    • bean对象只有一个就避免了对象的频繁创建与销毁,达到了bean对象的复用,性能高
  • bean在容器中是单例的,会不会产生线程安全问题?
    • 如果对象是有状态对象,即该对象有成员变量可以用来存储数据的,
    • 因为所有请求线程共用一个bean对象,所以会存在线程安全问题。
    • 如果对象是无状态对象,即该对象没有成员变量没有进行数据存储的,
    • 因方法中的局部变量在方法调用完成后会被销毁,所以不会存在线程安全问题。
  • 哪些bean对象适合交给容器进行管理?
    • 表现层对象
    • 业务层对象
    • 数据层对象
    • 工具对象
  • 哪些bean对象不适合交给容器进行管理?
    • 封装实例的域对象,因为会引发线程安全问题,所以不适合。

3.2 bean实例化

对象已经能交给Spring的IOC容器来创建了,但是容器是如何来创建对象的呢?

就需要研究下bean的实例化过程,在这块内容中主要解决两部分内容,分别是

  • bean是如何创建的
  • 实例化bean的三种方式,构造方法,静态工厂实例工厂

在讲解这三种创建方式之前,我们需要先确认一件事:

bean本质上就是对象,对象在new的时候会使用构造方法完成,那创建bean也是使用构造方法完成的。

基于这个知识点出发,我们来验证spring中bean的三种创建方式,

3.2.2 构造方法实例化

在上述的环境下,我们来研究下Spring中的第一种bean的创建方式构造方法实例化:

步骤1:准备需要被创建的类
准备一个BookDao和BookDaoImpl类
public interface BookDao {public void save();
}public class BookDaoImpl implements BookDao {public void save() {System.out.println("book dao save ...");}}
步骤2:将类配置到Spring容器


步骤3:编写运行程序

public class AppForInstanceBook {public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");BookDao bookDao = (BookDao) ctx.getBean("bookDao");bookDao.save();}
}

步骤4:类中提供构造函数测试

在BookDaoImpl类中添加一个无参构造函数,并打印一句话,方便观察结果。
在这里插入图片描述

步骤5:将构造函数改成private测试

public class BookDaoImpl implements BookDao {//public BookDaoImpl(int i) { 报错了 spring 创建bean的时候调用的是无参构造方法//        System.out.println("book dao constructor is running ....");//    }private BookDaoImpl() {System.out.println("book dao constructor is running ....");}public void save() {System.out.println("book dao save ...");}
}

在这里插入图片描述

步骤6:构造函数中添加一个参数测试

public class BookDaoImpl implements BookDao {private BookDaoImpl(int i) {System.out.println("book dao constructor is running ....");}public void save() {System.out.println("book dao save ...");}}

运行程序,

程序会报错,说明Spring底层使用的是类的无参构造方法。

3.2.3 分析Spring的错误信息 结论大多数报错都从最后一行看起就行 从最后往前两行看

接下来,我们主要研究下Spring的报错信息来学一学如阅读。

  • 错误信息从下往上依次查看,因为上面的错误大都是对下面错误的一个包装,最核心错误是在最下面
  • Caused by: java.lang.NoSuchMethodException: com.itheima.dao.impl.BookDaoImpl.()
    • Caused by 翻译为引起,即出现错误的原因
    • java.lang.NoSuchMethodException:抛出的异常为没有这样的方法异常
    • com.itheima.dao.impl.BookDaoImpl.():哪个类的哪个方法没有被找到导致的异常,()指定是类的构造方法,即该类的无参构造方法

如果最后一行错误获取不到错误信息,接下来查看第二层:

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.itheima.dao.impl.BookDaoImpl]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.itheima.dao.impl.BookDaoImpl.()

  • nested:嵌套的意思,后面的异常内容和最底层的异常是一致的
  • Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.itheima.dao.impl.BookDaoImpl]: No default constructor found;
    • Caused by: 引发
    • BeanInstantiationException:翻译为bean实例化异常
    • No default constructor found:没有一个默认的构造函数被发现

看到这其实错误已经比较明显,给大家个练习,把倒数第三层的错误分析下吧:

Exception in thread “main” org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘bookDao’ defined in class path resource [applicationContext.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.itheima.dao.impl.BookDaoImpl]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.itheima.dao.impl.BookDaoImpl.()。

至此,关于Spring的构造方法实例化就已经学习完了,因为每一个类默认都会提供一个无参构造函数,所以其实真正在使用这种方式的时候,我们什么也不需要做。这也是我们以后比较常用的一种方式。

3.2.4 静态工厂实例化

接下来研究Spring中的第二种bean的创建方式静态工厂实例化:

3.2.4.1 工厂方式创建bean

在讲这种方式之前,我们需要先回顾一个知识点是使用工厂来创建对象的方式:

(1)准备一个OrderDao和OrderDaoImpl类

public interface OrderDao {public void save();
}public class OrderDaoImpl implements OrderDao {public void save() {System.out.println("order dao save ...");}
}

(2)创建一个工厂类OrderDaoFactory并提供一个静态方法

//静态工厂创建对象
public class OrderDaoFactory {public static OrderDao getOrderDao(){return new OrderDaoImpl();}
}

(3)编写AppForInstanceOrder运行类,在类中通过工厂获取对象

public class AppForInstanceOrder {public static void main(String[] args) {//通过静态工厂创建对象OrderDao orderDao = OrderDaoFactory.getOrderDao();orderDao.save();}
}

在这里插入图片描述

3.2.4.2 静态工厂实例化

这就要用到Spring中的静态工厂实例化的知识了,具体实现步骤为:

(1)在spring的配置文件application.properties中添加以下内容:







class:工厂类的类全名

factory-mehod:具体工厂类中创建对象的方法名

对应关系如下图:
在这里插入图片描述

(2)在AppForInstanceOrder运行类,使用从IOC容器中获取bean的方法进行运行测试

public class AppForInstanceOrder {public static void main(String[] args) {//通过静态工厂创建对象
//        OrderDao orderDao = OrderDaoFactory.getOrderDao(); 个人体会就是调用new ClassPathXmlApplicationContext对象后帮我们创建这个dao对象的 因为调用无参方法就是这样的
//        orderDao.save();ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");OrderDao orderDao = (OrderDao) ctx.getBean("orderDao");orderDao.save();}
}

(3)运行后,可以查看到结果

在这里插入图片描述

3.2.5 实例工厂与FactoryBean

项目结构
在这里插入图片描述

接下来继续来研究Spring的第三种bean的创建方式实例工厂实例化:

3.2.3.1 环境准备

项目结构

(1)准备一个UserDao和UserDaoImpl类

public interface UserDao {public void save();
}public class UserDaoImpl implements UserDao {public void save() {System.out.println("user dao save ...");}
}

(2)创建一个工厂类OrderDaoFactory并提供一个普通方法,注意此处和静态工厂的工厂类不一样的地方是方法不是静态方法

public class UserDaoFactory {public UserDao getUserDao(){return new UserDaoImpl();}
}

(3)编写AppForInstanceUser运行类,在类中通过工厂获取对象

public class AppForInstanceUser {public static void main(String[] args) {//创建实例工厂对象UserDaoFactory userDaoFactory = new UserDaoFactory();//通过实例工厂对象创建对象UserDao userDao = userDaoFactory.getUserDao();userDao.save();
}

(4)运行后,可以查看到结果
在这里插入图片描述

3.2.3.2 实例工厂实例化

具体实现步骤为:

(1)在spring的配置文件中添加以下内容:



实例化工厂运行的顺序是:

  • 创建实例化工厂对象,对应的是第一行配置

  • 调用对象中的方法来创建bean,对应的是第二行配置

    • factory-bean:工厂的实例对象

    • factory-method:工厂对象中的具体创建对象的方法名,对应关系如下:
      在这里插入图片描述
      factory-mehod:具体工厂类中创建对象的方法名
      (2)在AppForInstanceUser运行类,使用从IOC容器中获取bean的方法进行运行测试

  public class AppForInstanceUser {public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");UserDao userDao = (UserDao) ctx.getBean("userDao");userDao.save();}
}

(3)运行后,可以查看到结果
在这里插入图片描述
实例工厂实例化的方式就已经介绍完了,配置的过程还是比较复杂,所以Spring为了简化这种配置方式就提供了一种叫FactoryBean的方式来简化开发。

3.2.3.3 FactoryBean的使用

具体的使用步骤为:

(1)创建一个UserDaoFactoryBean的类,实现FactoryBean接口,重写接口的方法

public class UserDaoFactoryBean implements FactoryBean {//代替原始实例工厂中创建对象的方法public UserDao getObject() throws Exception {return new UserDaoImpl();}public Class getObjectType() {return UserDao.class;}//改变工厂默认创建单例的对象方法 默认工厂就是true/*public boolean isSingleton() {return true;}*/
}

(2)在Spring的配置文件中进行配置
方式四:使用FactoryBean实例化Bean


(3)AppForInstanceUser运行类不用做任何修改,直接运行
在这里插入图片描述
这种方式在Spring去整合其他框架的时候会被用到,所以这种方式需要大家理解掌握。

查看源码会发现,FactoryBean接口其实会有三个方法,分别是:
方法一:getObject(),被重写后,在方法中进行对象的创建并返回

方法二:getObjectType(),被重写后,主要返回的是被创建类的Class对象

方法三:没有被重写,因为它已经给了默认值,从方法名中可以看出其作用是设置对象是否为单例,默认true,从意思上来看,我们猜想默认应该是单例,如何来验证呢?

思路很简单,就是从容器中获取该对象的多个值,打印到控制台,查看是否为同一个对象。

public class AppForInstanceUser {public static void main(String[] args) {
/*        //创建实例工厂对象UserDaoFactory userDaoFactory = new UserDaoFactory();//通过实例工厂对象创建对象UserDao userDao = userDaoFactory.getUserDao();userDao.save();*/ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");UserDao userDao1 = (UserDao) ctx.getBean("userDao");UserDao userDao2 = (UserDao) ctx.getBean("userDao");System.out.println(userDao1);System.out.println(userDao2);//  userDao.save();}
}

在这里插入图片描述
通过验证,会发现默认是单例,那如果想改成单例具体如何实现?

只需要将isSingleton()方法进行重写,修改返回为false,即可

//FactoryBean创建对象
public class UserDaoFactoryBean implements FactoryBean {//代替原始实例工厂中创建对象的方法public UserDao getObject() throws Exception {return new UserDaoImpl();}public Class getObjectType() {return UserDao.class;}public boolean isSingleton() {return false;}
}

在这里插入图片描述
从结果中可以看出现在已经是非单例了,但是一般情况下我们都会采用单例,也就是采用默认即可。所以isSingleton()方法一般不需要进行重写。

3.2.6 bean实例化小结

(1)bean是如何创建的呢?
构造方法
(2)Spring的IOC实例化对象的三种方式分别是:

  • 构造方法(常用)
  • 静态工厂(了解)
  • 实例工厂(了解)
    • FactoryBean(实用)

这些方式中,重点掌握构造方法FactoryBean即可。

需要注意的一点是,构造方法在类中默认会提供,但是如果重写了构造方法,默认的就会消失,在使用的过程中需要注意,如果需要重写构造方法,最好把默认的构造方法也重写下。

相关内容

热门资讯

最新或2023(历届)珠海市内...  办理对象  群众  办理条件  一、申请条件及所需资料:(以下有关证件由派出所审核原件后收取复印件...
Vue基础23之路由第二节 Vue基础23路由路由的query参数src/router/index.jsDetail.vueHo...
最新或2023(历届)清远户口...  办理对象  需户口迁移人员  办理条件  符合政策规定的户口迁移  所需材料  无  窗口办理流程...
最新或2023(历届)重庆户口...  办理程序、时限及相关迁移手续:  (一)、区内迁移的,居民持相关手续到入户地派出所办理入户,手续齐...
最新或2023(历届)佛山三水...  办理对象  拟迁入本区的非本市户籍人员  办理条件  市外户籍人员在我市购买商品房(不含二手房和自...
最新或2023(历届)汕尾户口...  办理对象  群众  办理条件  1、购房入户  2、夫妻迁移入户  3、子女投靠父母  所需材料 ...
基础数论算法刷题笔记 理论 最小公倍数、最大公约数 (a+b)%n = a%n+b%n (ab)...
LeetCode 112. 路... LeetCode 112. 路径总和        给你二叉树的根节点 root 和一个表示目标和的...
最新或2023(历届)新生婴儿...   新生儿落户口办理程序:  1、用医院开具的孩子出生证明到当地的妇幼保健站开具正式的出生医学证明。...
最新或2023(历届)新生儿户...   新生儿申报户口须知:  一、办理条件 新生婴儿可按随父随母自愿的原则申报户口。非婚生育的新生婴儿...
新生儿落户办理户口时间限制,新...   新生儿作为国家未来的主体,国家在一些政策上也是有规定的,那么新生儿落户政策有哪些呢?新生儿在落户...
最新或2023(历届)深圳户口...  第一项——调干条件 根据 人事局颁布相关政策,调干的方式及条件分别为:  一、单调 1、享受国务院...
最新或2023(历届)毕业生办... 市民您好!感谢您对公安工作的支持与理解。根据您提出的问题,依据我市现行的户口政策,现答复如下:需本人...
TDK| 电源——反激变压器设... 电源参数根据功率、输入输出的情况,我们选择反激电源拓扑。反激式变压器的优点有:1、 电...
[个人笔记] 投影矩阵的导数计... [个人笔记] 投影矩阵的导数计算(1) 问题(2ÿ...
19.特殊工具与技术 文章目录特殊工具与技术19.1控制内存分配19.1.1重载new和deleteoperator ne...
最新或2023(历届)最新户口... 户口迁移手续[网友提问]人在北京上班三年,现在想在北京定居落户。可是户口还在老家湖南。想把湖南户口迁...
揭秘:春秋战国时代的美食 春秋... 我们今天再来说说春秋战国的饮食。新春佳节,寒冬腊月,三五好友,围坐于火锅旁,天南海北的胡侃,便是人生...
宁都起义简介 起义的环境,过程... 宁都起义,又名26路军起义,1931年(民国二十年)12月,在第二次国内革命战争中,国民革命军第26...
他是战国猛将,一生做错三件事 ... 战国时期,诸侯皆有争霸之心,都养兵买马,意图问鼎天下,而乱世之中,最易脱颖而出的是四处征战的将领。战...