0


初识Spring -- Spring入门保姆级教程(一)

文章目录


前言

为了巩固所学的知识,作者尝试着开始发布一些学习笔记类的博客,方便日后回顾。当然,如果能帮到一些萌新进行新技术的学习那也是极好的。作者菜菜一枚,文章中如果有记录错误,欢迎读者朋友们批评指正。
(博客的参考源码以及可以在我主页的资源里找到,如果在学习的过程中有什么疑问欢迎大家在评论区向我提出)


一、Spring是什么?

1.概述

  • Spring Framework 是一个功能强大的 Java 应用程序框架,旨在提供高效且可扩展的开发环境。
  • 它结合了轻量级的容器(IOC)和 依赖注入(DI) 功能,提供了一种使用 POJO 进行容器配置和面向切面的编程的简单方法,以及一组用于 AOP(切面编程) 的模块。
  • Spring 框架还支持各种移动应用开发技术,如 Android 和 iOS。此外,它还提供了对事务管理、对象/关系映射、JavaBeans、JDBC、JMS 和其他技术的支持,从而确保高效开发。

2.了解spring家族

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

3.spring系统概述

Spring 有可能成为所有企业应用程序的一站式服务点,然而,Spring 是模块化的,允许你挑选和选择适用于你的模块,不必要把剩余部分也引入。下面的部分对在 Spring 框架中所有可用的模块给出了详细的介绍。

Spring 框架提供约 20 个模块,可以根据应用程序的要求来使用。

在这里插入图片描述

  1. 核心容器(Core Container)

核心容器由 spring-core,spring-beans,spring-context,spring-context-support和spring-expression(SpEL,Spring 表达式语言,Spring Expression Language)等模块组成,它们的细节如下:

spring-core 模块提供了框架的基本组成部分,包括 IoC 和依赖注入功能。

spring-beans 模块提供 BeanFactory,工厂模式的微妙实现,它移除了编码式单例的需要,并且可以把配置和依赖从实际编码逻辑中解耦。

context 模块建立在由 core和 beans 模块的基础上建立起来的,它以一种类似于 JNDI 注册的方式访问对象。Context 模块继承自 Bean 模块,并且添加了国际化(比如,使用资源束)、事件传播、资源加载和透明地创建上下文(比如,通过 Servelet 容器)等功能。Context 模块也支持 Java EE 的功能,比如 EJB、JMX 和远程调用等。ApplicationContext 接口是 Context 模块的焦点。spring-context-support 提供了对第三方集成到 Spring 上下文的支持,比如缓存(EhCache, Guava, JCache)、邮件(JavaMail)、调度(CommonJ, Quartz)、模板引擎(FreeMarker, JasperReports, Velocity)等。

spring-expression 模块提供了强大的表达式语言,用于在运行时查询和操作对象图。它是 JSP2.1 规范中定义的统一表达式语言的扩展,支持 set 和 get 属性值、属性赋值、方法调用、访问数组集合及索引的内容、逻辑算术运算、命名变量、通过名字从 Spring IoC 容器检索对象,还支持列表的投影、选择以及聚合等。
  1. 数据访问/集成(Data Access/Integration) 数据访问/集成层包括 JDBC,ORM,OXM,JMS 和事务处理模块,它们的细节如下:

(注:JDBC=Java Data Base Connectivity,ORM=Object Relational Mapping,OXM=Object XML Mapping,JMS=Java Message Service)

JDBC 模块提供了 JDBC 抽象层,它消除了冗长的 JDBC 编码和对数据库供应商特定错误代码的解析。

ORM 模块提供了对流行的对象关系映射 API 的集成,包括 JPA、JDO 和 Hibernate 等。通过此模块可以让这些 ORM 框架和 spring的其它功能整合,比如前面提及的事务管理。

OXM 模块提供了对 OXM 实现的支持,比如 JAXB、Castor、XML Beans、JiBX、XStream 等。

JMS 模块包含生产(produce)和消费(consume)消息的功能。从 Spring 4.1 开始,集成了 spring-messaging 模块。

事务模块为实现特殊接口类及所有的 POJO 支持编程式和声明式事务管理。(注:编程式事务需要自己写 beginTransaction()、commit()、rollback() 等事务管理方法,声明式事务是通过注解或配置由 spring 自动处理,编程式事务粒度更细)
  1. Web

Web 层由 Web,Web-MVC,Web-Socket 和 Web-Portlet 组成,它们的细节如下:

Web 模块提供面向 web 的基本功能和面向 web 的应用上下文,比如多部分(multipart)文件上传功能、使用 Servlet 监听器初始化 IoC 容器等。它还包括 HTTP 客户端以及 Spring 远程调用中与 web 相关的部分。

Web-MVC 模块为 web 应用提供了模型视图控制(MVC)和 REST Web服务的实现。Spring 的 MVC 框架可以使领域模型代码和 web 表单完全地分离,且可以与 Spring 框架的其它所有功能进行集成。

Web-Socket 模块为 WebSocket-based 提供了支持,而且在 web 应用程序中提供了客户端和服务器端之间通信的两种方式。

Web-Portlet 模块提供了用于 Portlet 环境的 MVC 实现,并反映了 spring-webmvc 模块的功能。 
  1. Test模块

Test 模块:Spring 支持 Junit 和 TestNG 测试框架,而且还额外提供了一些基于 Spring 的测试功能,比如在测试 Web 框架时,模拟 Http 请求的功能。

  1. 其他

还有其他一些重要的模块,像 AOP,Aspects,Instrumentation,Web 和测试模块,它们的细节如下:

AOP 模块提供了面向方面(切面)的编程实现,允许你定义方法拦截器和切入点对代码进行干净地解耦,从而使实现功能的代码彻底的解耦出来。使用源码级的元数据,可以用类似于.Net属性的方式合并行为信息到代码中。

Aspects 模块提供了与 AspectJ 的集成,这是一个功能强大且成熟的面向切面编程(AOP)框架。

Instrumentation 模块在一定的应用服务器中提供了类 instrumentation 的支持和类加载器的实现。

Messaging 模块为 STOMP 提供了支持作为在应用程序中 WebSocket 子协议的使用。它也支持一个注解编程模型,它是为了选路和处理来自 WebSocket 客户端的 STOMP 信息。

测试模块支持对具有 JUnit 或 TestNG 框架的 Spring 组件的测试

4.spring优点

  • 方便解耦,简化开发

Spring 就是一个大工厂,可以将所有对象的创建和依赖关系的维护交给 Spring 管理

  • 方便集成各种优秀框架

Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如 Struts2、Hibernate、MyBatis 等)的直接支持

  • 降低 Java EE API 的使用难度

Spring 对 Java EE 开发中非常难用的一些 API(JDBC、JavaMail、远程调用等)都提供了封装,使这些 API 应用的难度大大降低

  • 方便程序的测试

Spring 支持 JUnit4,可以通过注解方便地测试 Spring 程序

  • AOP 编程的支持

Spring 提供面向切面编程,可以方便地实现对程序进行权限拦截和运行监控等功能

  • 声明式事务的支持

只需要通过配置就可以完成对事务的管理,而无须手动编程。

5.spring学习路线

在这里插入图片描述

二、入门spring

1.核心概念

  1. 依赖注入(DI
  • Spring 最认同的技术是控制反转的依赖注入(DI)模式。控制反转(IoC)是一个通用的概念,它可以用许多不同的方式去表达,依赖注入仅仅是控制反转的一个具体的例子
  • 当编写一个复杂的 Java 应用程序时,应用程序类应该尽可能的独立于其他的 Java 类来增加这些类可重用可能性,当进行单元测试时,可以使它们独立于其他类进行测试。依赖注入(或者有时被称为配线)有助于将这些类粘合在一起,并且在同一时间让它们保持独立。
  • 到底什么是依赖注入?让我们将这两个词分开来看一看。这里将依赖关系部分转化为两个类之间的关联。例如,类 A 依赖于类 B。现在,让我们看一看第二部分,注入。所有这一切都意味着类 B 将通过 IoC 被注入到类 A 中。
  • 依赖注入可以以向构造函数传递参数的方式发生,或者通过使用 setter 方法 post-construction。由于依赖注入是 Spring 框架的核心部分,所以我将在一个单独的章节中利用很好的例子去解释这一概念。

2.面向切面的程序设计(AOP):

  • Spring 框架的一个关键组件是面向切面的程序设计(AOP)框架。一个程序中跨越多个点的功能被称为横切关注点,这些横切关注点在概念上独立于应用程序的业务逻辑。有各种各样常见的很好的关于方面的例子,比如日志记录、声明性事务、安全性,和缓存等等。
  • 在 OOP 中模块化的关键单元是类,而在 AOP 中模块化的关键单元是方面。AOP 帮助你将横切关注点从它们所影响的对象中分离出来,然而依赖注入帮助你将你的应用程序对象从彼此中分离出来。
  • Spring 框架的 AOP 模块提供了面向方面的程序设计实现,可以定义诸如方法拦截器和切入点等,从而使实现功能的代码彻底的解耦出来。使用源码级的元数据,可以用类似于 .Net 属性的方式合并行为信息到代码中。我将在一个独立的章节中讨论更多关于 Spring AOP 的概念。
  1. Spring IoC 容器
  • Spring 容器是 Spring 框架的核心。容器将创建对象,把它们连接在一起,配置它们,并管理他们的整个生命周期从创建到销毁。Spring 容器使用依赖注入(DI)来管理组成一个应用程序的组件。这些对象被称为 Spring Beans
  • 通过阅读配置元数据提供的指令,容器知道对哪些对象进行实例化,配置和组装。配置元数据可以通过 XML,Java 注释或 Java 代码来表示。下图是 Spring 如何工作的高级视图。 Spring IoC 容器利用 Java 的 POJO 类和配置元数据来生成完全配置和可执行的系统或应用程序

在这里插入图片描述

  • IOC 容器具有依赖注入功能的容器,它可以创建对象,IOC 容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。通常new一个实例,控制权由程序员控制,而"控制反转"是指new实例工作不由程序员来做而是交给Spring容器来做。在Spring中BeanFactory是IOC容器的实际代表者。
  • Spring 提供了以下两种不同类型的容器。
    序号容器 & 描述1Spring BeanFactory 容器 :它是最简单的容器,给 DI 提供了基本的支持,它用 org.springframework.beans.factory.BeanFactory 接口来定义。BeanFactory 或者相关的接口,如 BeanFactoryAware,InitializingBean,DisposableBean,在 Spring 中仍然存在具有大量的与 Spring 整合的第三方框架的反向兼容性的目的。2Spring ApplicationContext 容器 :该容器添加了更多的企业特定的功能,例如从一个属性文件中解析文本信息的能力,发布应用程序事件给感兴趣的事件监听器的能力。该容器是由 org.springframework.context.ApplicationContext 接口定义。
    ApplicationContext 容器包括 BeanFactory 容器的所有功能,所以通常不建议使用BeanFactory。BeanFactory 仍然可以用于轻量级的应用程序,如移动设备或基于 applet 的应用程序,其中它的数据量和速度是显著。
  1. Spring Bean 定义
  • 被称作 bean 的对象是构成应用程序的支柱也是由 Spring IoC 容器管理的。bean 是一个被实例化,组装,并通过 Spring IoC 容器所管理的对象。这些 bean 是由用容器提供的配置元数据创建的,例如,已经在先前章节看到的,在 XML 的表单中的 定义。
  • bean 定义包含称为配置元数据的信息,下述容器也需要知道配置元数据:- 如何创建一个 bean- bean 的生命周期的详细信息- bean 的依赖关系

上述所有的配置元数据转换成一组构成每个 bean 定义的下列属性。
属性描述class这个属性是强制性的,并且指定用来创建 bean 的 bean 类。name这个属性指定唯一的 bean 标识符。在基于 XML 的配置元数据中,你可以使用 ID 和/或 name 属性来指定 bean 标识符。scope这个属性指定由特定的 bean 定义创建的对象的作用域,它将会在 bean 作用域的章节中进行讨论。constructor-arg它是用来注入依赖关系的,并会在接下来的章节中进行讨论。properties它是用来注入依赖关系的,并会在接下来的章节中进行讨论。autowiring mode它是用来注入依赖关系的,并会在接下来的章节中进行讨论。lazy-initialization mode延迟初始化的 bean 告诉 IoC 容器在它第一次被请求时,而不是在启动时去创建一个 bean 实例。initialization 方法在 bean 的所有必需的属性被容器设置之后,调用回调方法。它将会在 bean 的生命周期章节中进行讨论。destruction 方法当包含该 bean 的容器被销毁时,使用回调方法。它将会在 bean 的生命周期章节中进行讨论。

  • Bean 与 Spring 容器的关系

在这里插入图片描述## 5.spring三层架构

A 表现层   web层    MVC是表现层的一个设计模型 

B 业务层  service层

C 持久层  dao层

2.IOC入门案例

  1. 入门案例思路分析

在这里插入图片描述

  1. 创建maven模块

在这里插入图片描述

  1. 编写接口和Dao实现类(此时无spring环境,纯JAVA开发)
  • 模块代码结构在这里插入图片描述
  • BookDao
publicinterfaceBookDao{publicvoidsave();}
  • BookDaoImpl
publicclassBookDaoImplimplementsBookDao{publicvoidsave(){System.out.println("book dao save ...");}}
  • BookService
publicinterfaceBookService{publicvoidsave();}
  • BookServiceImpl
publicclassBookServiceImplimplementsBookService{privateBookDao bookDao =newBookDaoImpl();publicvoidsave(){System.out.println("book service save ...");
        bookDao.save();}}
  • Main
publicclassMain{publicstaticvoidmain(String[] args){BookService bookService =newBookServiceImpl();
        bookService.save();}}
  • Main类运行结果

在这里插入图片描述

  1. 示例代码解析
  • 首先写了两个数据层接口 BookDao 和 BookService,两个接口中都定义了save()方法
  • 然后写了两个数据层接口的实现类 BookDaoImpl 和 BookServiceImpl,分别实现了save() 方法,方法里都要一条输出语句,但是两个实现类save方法打印的内容不同
  • 其中 BookServiceImpl 类中还通过new创建对象的方式调用了 BookDaoImpl的save方法
  • 最后在Main类中通过new创建对象的方式调用了BookServiceImpl的save方法将两个save()方法中的语句打印了出来
  1. 在pom.xml中导入spring坐标spring-context
<dependencies><!--spring坐标--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.21.RELEASE</version></dependency></dependencies>
  1. 创建spring核心配置文件applicationContext.xml

resources 目录右键 --> new --> XML Configuration File --> Spring Config(导入spring坐标后才有对应选项)

在这里插入图片描述

  1. 配置Bean(如下)
<?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"><!--1.导入spring的坐标spring-context,对应版本是5.2.10.RELEASE--><!--2.配置bean--><!--bean标签标示配置bean
       id属性标示给bean起名字
       class属性表示给bean定义类型--><bean id="bookDao"class="org.example.dao.impl.BookDaoImpl"/><bean id="bookService"class="org.example.service.impl.BookServiceImpl"/></beans>
  1. 在org.example下新建一个类Main2
publicclassMain2{publicstaticvoidmain(String[] args){//3.获取IoC容器ApplicationContext ctx =newClassPathXmlApplicationContext("applicationContext.xml");//4.获取bean(根据bean配置id获取)//左边是对象,右边是接口,所以要强转类型BookDao bookDao =(BookDao) ctx.getBean("bookDao");
        bookDao.save();BookService bookService =(BookService) ctx.getBean("bookService");
        bookService.save();}}
  • 程序运行结果(通过spring创建对象而不是通过new创建对象)

在这里插入图片描述

  1. 总结 :spring程序的开发步骤

在这里插入图片描述

3.DI入门案例

  1. 删除BookServiceImpl类中通过new方式创建对象的代码,并提供对应的setter方法
packageorg.example.service.impl;importorg.example.dao.BookDao;importorg.example.service.BookService;publicclassBookServiceImplimplementsBookService{//5.删除业务层中使用new的方式创建的dao对象privateBookDao bookDao;//    private BookDao bookDao = new BookDaoImpl();publicvoidsave(){System.out.println("book service save ...");
        bookDao.save();}//    6.提供对应的set方法publicvoidsetBookDao(BookDao bookDao){this.bookDao = bookDao;}}
  1. 在全局配置文件applicationContext.xml文件中将BookDao注入到BookService中
<?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"><!--1.导入spring的坐标spring-context,对应版本是5.2.10.RELEASE--><!--2.配置bean--><!--bean标签标示配置bean
       id属性标示给bean起名字
       class属性表示给bean定义类型--><bean id="bookDao"class="org.example.dao.impl.BookDaoImpl"/><bean id="bookService"class="org.example.service.impl.BookServiceImpl"><!--7.配置server与dao的关系--><!--property标签表示配置当前bean的属性
       name属性表示配置哪一个具体的属性
       ref属性表示参照哪一个bean--><property name="bookDao" ref="bookDao"/></bean></beans>
  1. 运行结果

在这里插入图片描述

  1. 注意事项

name 的值是类的属性值,ref的值是id值

在这里插入图片描述

4.bean的配置

  1. bean的基础配置

在这里插入图片描述

  1. bean的别名设置

在这里插入图片描述

  1. 控制bean的作用范围

在这里插入图片描述

5.spring 中 bean的实例化–构造方法

  1. 创建新的maven模块respr_newbean,并在pom.xml添加spring的坐标

在这里插入图片描述

<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.22</version><scope>compile</scope></dependency>
  1. 创建核心配置文件applicationContext.xml文件、dao接口及其实现类以及相关的类(先写标记部分)

在这里插入图片描述

  1. 编写dao接口及其实现类
  • BookDao接口
publicinterfaceBookDao{publicvoidsave();}
  • BookDaoImpl实现类
publicclassBookDaoImplimplementsBookDao{//无参构造publicBookDaoImpl(){System.out.println("book dao constructor is running ....");}publicvoidsave(){System.out.println("book dao save ...");}}
  • 进行测试的类 AppForInstanceBook
publicclassAppForInstanceBook{publicstaticvoidmain(String[] args){ApplicationContext ctx =newClassPathXmlApplicationContext("applicationContext.xml");BookDao bookDao =(BookDao) ctx.getBean("bookDao");

        bookDao.save();}}
  • applicationContext.xml
<?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 id="bookDao"class="org.example.dao.impl.BookDaoImpl"/></beans>
  • AppForInstanceBook运行结果

在这里插入图片描述

  • 结论

spring构造方法实例化bean使用了无参构造器,可以省略无参构造器的书写。实例化bean就是用构造方法来实例化对象。

6.bean的实例化 – 静态工厂实例化

  1. 创建dao接口及其实现类以及相关的类(先写标记部分)

在这里插入图片描述

  1. 编写dao接口及其实现类以及相关的类
  • OrderDao接口
packageorg.example.dao;publicinterfaceOrderDao{publicvoidsave();}
  • OrderDaoImpl实现类
在这里插入代码片packageorg.example.dao.impl;importorg.example.dao.OrderDao;publicclassOrderDaoImplimplementsOrderDao{publicvoidsave(){System.out.println("order dao save ...");}}
  • 工厂类OrderDaoFactory(静态工厂类代理生成对象)
packageorg.example.factory;importorg.example.dao.OrderDao;importorg.example.dao.impl.OrderDaoImpl;//静态工厂创建对象publicclassOrderDaoFactory{publicstaticOrderDaogetOrderDao(){System.out.println("factory setup....");returnnewOrderDaoImpl();}}
  • AppForInstanceOrder模拟测试类编写(纯JAVA开发,此处还没有Spring)
publicclassAppForInstanceOrder{publicstaticvoidmain(String[] args){//通过静态工厂创建对象OrderDao orderDao =OrderDaoFactory.getOrderDao();
        orderDao.save();}}
  • 模拟测试类的运行结果

在这里插入图片描述

  • 简要分析

将 OrderDaoImpl 创建对象的 工作交给 静态工厂 OrderDaoFactory 类来完成,如果用spring代理这种工厂模式的开发,写法如下

  • spring 代理静态工厂实例化对象
publicclassAppForInstanceOrder{publicstaticvoidmain(String[] args){//通过静态工厂创建对象//        OrderDao orderDao = OrderDaoFactory.getOrderDao();//        orderDao.save();//      spring代理静态工厂实例化对象ApplicationContext ctx =newClassPathXmlApplicationContext("applicationContext.xml");OrderDao orderDao =(OrderDao) ctx.getBean("orderDao");

        orderDao.save();}}
  • applicationContext.xml文件配置静态工厂 OrderDaoFactory bean (注意factory-method属性)
<?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 id="bookDao"class="com.itheima.dao.impl.BookDaoImpl"/>--><!--    方式二:使用静态工厂实例化bean--><bean id="orderDao"class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao"/></beans>
  • 运行结果

在这里插入图片描述

7.bean实例化–实例工厂和FactoryBean

  1. 创建dao接口及其实现类以及相关的类(标记部分)

在这里插入图片描述

  1. 编写dao接口及其实现类以及相关的类
  • UserDao接口
publicinterfaceUserDao{publicvoidsave();}
  • UserDaoImpl实现类
publicclassUserDaoImplimplementsUserDao{publicvoidsave(){System.out.println("user dao save ...");}}
  • UserDaoFactoryBean实例工厂类
//实例工厂创建对象publicclassUserDaoFactory{publicUserDaogetUserDao(){returnnewUserDaoImpl();}}
  • AppForInstanceUser模拟测试类(纯JAVA开发)
publicclassAppForInstanceUser{publicstaticvoidmain(String[] args){//        //创建实例工厂对象UserDaoFactory userDaoFactory =newUserDaoFactory();//        //通过实例工厂对象创建对象UserDao userDao = userDaoFactory.getUserDao();
        userDao.save();}}
  1. 运行结果

在这里插入图片描述

  1. 简要分析

此时与静态工厂的区别是模拟测试类中多了创建工厂对象的步骤

  • spring代理下的实例工厂bean实例化模拟测试类
publicclassAppForInstanceUser{publicstaticvoidmain(String[] args){//        //创建实例工厂对象//        UserDaoFactory userDaoFactory = new UserDaoFactory();//        //通过实例工厂对象创建对象//        UserDao userDao = userDaoFactory.getUserDao();//        userDao.save();ApplicationContext ctx =newClassPathXmlApplicationContext("applicationContext.xml");UserDao userDao =(UserDao) ctx.getBean("userDao");

        userDao.save();}}
  1. applicationContext.xml(分辨方式二和方式三的写法)
<?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 id="bookDao"class="org.example.dao.impl.BookDaoImpl"/>--><!--    方式二:使用静态工厂实例化bean--><!--<bean id="orderDao"class="org.example.factory.OrderDaoFactory" factory-method="getOrderDao"/>--><!--方式三:使用实例工厂实例化bean--><bean id="userFactory"class="org.example.factory.UserDaoFactory"/><bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/></beans>
  1. 模拟测试类运行结果

在这里插入图片描述

  1. spring代理实例工厂bean实例化简要分析 --> 改进为BeanFactory bean实例化

在这里插入图片描述

  1. 创建并编写BeanFactory工厂类UserDaoFactoryBean
//FactoryBean创建对象//实现接口,创建什么对象写什么泛型publicclassUserDaoFactoryBeanimplementsFactoryBean<UserDao>{//实现抽象方法//代替原始实例工厂中创建对象的方法,以后方法名不用指定,就用getObjectpublicUserDaogetObject()throwsException{returnnewUserDaoImpl();}//配置的类是什么类型publicClass<?>getObjectType(){returnUserDao.class;}}
  1. 配置applicationContext.xml文件
<?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 id="bookDao"class="org.example.dao.impl.BookDaoImpl"/>--><!--    方式二:使用静态工厂实例化bean--><!--<bean id="orderDao"class="org.example.factory.OrderDaoFactory" factory-method="getOrderDao"/>--><!--方式三:使用实例工厂实例化bean--><!--<bean id="userFactory"class="org.example.factory.UserDaoFactory"/>--><!--<bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>--><!--方式四:使用FactoryBean实例化bean--><bean id="userDao"class="org.example.factory.UserDaoFactoryBean"/></beans>
  1. 模拟测试类运行结果

在这里插入图片描述

8.bean的生命周期

  1. 概念

在这里插入图片描述

  • 理解 Spring bean 的生命周期很容易。当一个 bean 被实例化时,它可能需要执行一些初始化使它转换成可用状态。同样,当 bean 不再需要,并且从容器中移除时,可能需要做一些清除工作
  • 尽管还有一些在 Bean 实例化和销毁之间发生的活动,有两个重要的生命周期回调方法,它们在 bean 的初始化销毁的时候是必需的
  • 为了定义安装和拆卸一个 bean,我们只要声明带有 init-method 和/或 destroy-method 参数的 。init-method 属性指定一个方法,在实例化 bean 时,立即调用该方法。同样,destroy-method 指定一个方法,只有从容器中移除 bean 之后,才能调用该方法
  • Bean的生命周期可以表达为:Bean的定义——Bean的初始化——Bean的使用——Bean的销毁
  1. 编写代码(IOC 和 DI入门案例的代码,模块名为respr_ioc)
  • 在BookDaoImpl实现类中定义代表创建bena初始化和销毁的方法
packageorg.example.dao.impl;importorg.example.dao.BookDao;publicclassBookDaoImplimplementsBookDao{publicvoidsave(){System.out.println("book dao save ...");}//表示bean初始化对应的操作publicvoidinit(){System.out.println("init...");}//表示bean销毁前对应的操作publicvoiddestory(){System.out.println("destory...");}}
  1. 在applicationContext.xml文件中配置BookDao bean 的 初始化方法 int-method 和销毁方法 destory-method

在这里插入图片描述

  1. 将BookService的代码注释掉,运行模拟测试类,观察BookDao bean的创建和销毁过程

在这里插入图片描述

  • 运行结果

在这里插入图片描述

  1. 简要分析 我们从运行结果可以看到bean初始化成功了,但是并没有进行销毁工作,原因是java虚拟机(java在虚拟机运行)在执行玩程序退出时并没有做销毁操作,我们需要自己添加关闭语句,**ctx.close()**。但是ApplicationContext接口中并没有这个方法,而它的实现类中有,所以我们要用它的实现类ClassPathXmlApplicationContext来调用这个方法
  2. 关闭ioc容器的代码及运行结果如下

在这里插入图片描述

  1. 关闭ioc容器的第二种方式:关闭钩子(概念、代码及运行结果如下)

在Java程序退出时——尤其是非正常退出时,我们可能需要先执行一些善后工作,如关闭线程池、连接池、文件句柄等。如何保证善后工作的代码能够被执行到呢?Java为用户提供了关闭钩子(shutdown hook)registerShutdownHook()方法来注册关闭钩子

在这里插入图片描述

  1. 两种关闭ioc容器的简要分析 关闭钩子函数代码在程序中的位置要求没有close()方法那么苛刻,如果将其挪到bookDao.save()方法的下面也能用,close()方法比较暴力
  2. 绑定销毁方法和初始化方法的改进–继承接口(以BookServiceImpl为例)
  • 实现InitializingBean, DisposableBean接口
  • 重写 destroy(销毁) 和 afterPropertiesSet(初始化) 方法
publicclassBookServiceImplimplementsBookService,InitializingBean,DisposableBean{privateBookDao bookDao;publicvoidsetBookDao(BookDao bookDao){this.bookDao = bookDao;}publicvoidsave(){System.out.println("book service save ...");
        bookDao.save();}publicvoiddestroy()throwsException{System.out.println("service destroy");}publicvoidafterPropertiesSet()throwsException{System.out.println("service init");}}
  1. 模拟测试类Main2运行结果

(尽管在模拟测试类Main2并没有调用BookService 的bean,但是在核心配置文件中定义了BookService 的 bean,该创建bean的时候就创建,该初始化就初始化,该销毁就销毁)

在这里插入图片描述

9.依赖注入 – setter注入

  1. 思考

在这里插入图片描述

  1. 依赖注入 – setter注入引用类型的步骤方法(DI入门案例所用的就是setter注入引用类型)

在这里插入图片描述(代码见DI入门案例)

  1. 探讨引用多个引用对象(在DI入门的代码基础上编码)
  • 在dao包下创建并编写UserDao接口
packageorg.example.dao;publicinterfaceUserDao{publicvoidsave();}
  • 在impl包下创建并编写UserDaoImpl实现类
packageorg.example.dao.impl;importorg.example.dao.UserDao;publicclassUserDaoImplimplementsUserDao{publicvoidsave(){System.out.println("user dao save ...");}}
  • 在BookServiceImpl实现类中setter注入UserDao
publicclassBookServiceImplimplementsBookService{privateBookDao bookDao;privateUserDao userDao;//setter注入需要提供要注入对象的set方法publicvoidsetUserDao(UserDao userDao){this.userDao = userDao;}//setter注入需要提供要注入对象的set方法publicvoidsetBookDao(BookDao bookDao){this.bookDao = bookDao;}publicvoidsave(){System.out.println("book service save ...");
        bookDao.save();
        userDao.save();}}
  • 在核心配置类applicationContext中配置userDAO的bean,并将其注入到BookService中

在这里插入图片描述

  • 执行模拟测试类App2

在这里插入图片描述
(从运行结果中可以看到多个引用类型是可以用setter注入的)

  1. 依赖注入 – setter注入普通类型的步骤方法

在这里插入图片描述

  1. 在BookDaoImpl中提供两个变量,并提供对应的setter方法(以BookDaoImpl为例)
publicclassBookDaoImplimplementsBookDao{privateString databaseName;privateint connectionNum;//setter注入需要提供要注入对象的set方法publicvoidsetConnectionNum(int connectionNum){this.connectionNum = connectionNum;}//setter注入需要提供要注入对象的set方法publicvoidsetDatabaseName(String databaseName){this.databaseName = databaseName;}publicvoidsave(){System.out.println("book dao save ..."+databaseName+","+connectionNum);}}
  • 在核心配置类applicationContext.xml文件中配置中注入普通变量

在这里插入图片描述

  • 模拟测试类App2类的运行结果

在这里插入图片描述

10.依赖注入 – 构造器注入

(在依赖注入–setter注入的基础上编码,将依赖注入相关的代码删掉,具体见个人主页上传的代码respr_diconstouctor)

1 . 依赖注入 – 构造器注入引用类型的步骤方法

在这里插入图片描述

  1. 在BookService类中提供构造方法
publicclassBookServiceImplimplementsBookService{//5.删除业务层中使用new的方式创建的dao对象privateBookDao bookDao;//提供构造方法publicBookServiceImpl(BookDao bookDao){this.bookDao = bookDao;}publicvoidsave(){System.out.println("book service save ...");
        bookDao.save();}}
  1. 在核心配置类中注入BookDao相关的bean
<?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 id="bookDao"class="org.example.dao.impl.BookDaoImpl"/><bean id="bookService"class="org.example.service.impl.BookServiceImpl"><constructor-arg name="bookDao" ref="bookDao"/></bean></beans>
  1. 模拟测试类App2运行结果(同理,构造器注入可以注入多个引用类型,此处省略相关代码)

在这里插入图片描述

  1. 依赖注入 – 构造器注入普通类型的步骤和方法

在这里插入图片描述

  1. 在BookDao中定义两个变量,并编写对应的构造器方法
publicclassBookDaoImplimplementsBookDao{privateString databaseName;privateint connectionNum;publicBookDaoImpl(String databaseName,int connectionNum){this.databaseName = databaseName;this.connectionNum = connectionNum;}publicvoidsave(){System.out.println("book dao save ..."+databaseName+","+connectionNum);}}
  1. 在核心配置文件配置相关属性
  • 方式一:根据构造方法参数名称注入

在这里插入图片描述

  • 方式二:根据构造方法参数类型注入

在这里插入图片描述

  • 方式三:根据构造方法参数位置注入

在这里插入图片描述

  1. 模拟测试类App2运行结果

在这里插入图片描述

  1. 依赖注入的选择

在这里插入图片描述

11.自动装配

  1. 自动装配基础知识
  • 我们已经学会如何使用元素来声明 bean 和通过使用 XML 配置文件中的和元素来注入 。
  • Spring 容器可以在不使用和 元素的情况下自动装配相互协作的 bean 之间的关系,这有助于减少编写一个大的基于 Spring 的应用程序的 XML 配置的数量。
  • 下列自动装配模式,它们可用于指示 Spring 容器为来使用自动装配进行依赖注入。你可以使用元素的 autowire 属性为一个 bean 定义指定自动装配模式。
    模式描述no这是默认的设置,它意味着没有自动装配,你应该使用显式的bean引用来连线。你不用为了连线做特殊的事。在依赖注入章节你已经看到这个了。byName(按名称)由属性名自动装配。Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byName。然后尝试匹配,并且将它的属性与在配置文件中被定义为相同名称的 beans 的属性进行连接。byType(按类型)由属性数据类型自动装配。Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byType。然后如果它的类型匹配配置文件中的一个确切的 bean 名称,它将尝试匹配和连接属性的类型。如果存在不止一个这样的 bean,则一个致命的异常将会被抛出。constructor类似于 byType,但该类型适用于构造函数参数类型。如果在容器中没有一个构造函数参数类型的 bean,则一个致命错误将会发生。autodetect(3.0版本不支持)Spring首先尝试通过 constructor 使用自动装配来连接,如果它不执行,Spring 尝试通过 byType 来自动装配。
    可以使用 byType 或者 constructor 自动装配模式来连接数组和其他类型的集合。
  1. 在入门案例的基础上编码(详情见个人主页spring代码资源respr_autowire模块)

在这里插入图片描述

  1. 自动装配
  • 手动配置

在这里插入图片描述

  • 按类型自动装配(byType)

在这里插入图片描述

(需要提供setter方法,ioc通过setter入口给bean)

在这里插入图片描述

  • 按名称装配

(要确保BookDao装配bean的id与BookService中的其中一个属性名对应上)
在这里插入图片描述

  • 依赖自动装配特征

在这里插入图片描述

  • 集合注入(比较少用)(数组,List,Set,Map,properties)
  • 新建BookDao2接口及其实现类
packageorg.example.dao;publicinterfaceBookDao2{publicvoidsave();}
publicclassBookDaoImpl2implementsBookDao2{//数组privateint[] array;//列表privateList<String> list;//集合privateSet<String> set;//图privateMap<String,String> map;//propertiesprivateProperties properties;//提供对应的setter方法作为ioc提供bean的入口publicvoidsetArray(int[] array){this.array = array;}publicvoidsetList(List<String> list){this.list = list;}publicvoidsetSet(Set<String> set){this.set = set;}publicvoidsetMap(Map<String,String> map){this.map = map;}publicvoidsetProperties(Properties properties){this.properties = properties;}//编写测试方法publicvoidsave(){System.out.println("book dao save ...");System.out.println("遍历数组:"+Arrays.toString(array));System.out.println("遍历List"+ list);System.out.println("遍历Set"+ set);System.out.println("遍历Map"+ map);System.out.println("遍历Properties"+ properties);}}
  • 核心配置类文件编写
<?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 id="bookDao"class="org.example.dao.impl.BookDaoImpl"/>--><!--<bean id="bookService"class="org.example.service.impl.BookServiceImpl" autowire="byName"/>--><bean id="bookDao2"class="org.example.dao.impl.BookDaoImpl2"><!--数组注入--><property name="array"><array><value>100</value><value>200</value><value>300</value></array></property><!--list集合注入--><property name="list"><list><value>itcast</value><value>itheima</value><value>boxuegu</value><value>chuanzhihui</value></list></property><!--set集合注入--><property name="set"><set><value>itcast</value><value>itheima</value><value>boxuegu</value><value>boxuegu</value></set></property><!--map集合注入--><property name="map"><map><entry key="country" value="china"/><entry key="province" value="henan"/><entry key="city" value="kaifeng"/></map></property><!--Properties注入--><property name="properties"><props><prop key="country">china</prop><prop key="province">henan</prop><prop key="city">kaifeng</prop></props></property></bean></beans>
  • 模拟测试类编写及运行结果

在这里插入图片描述

12.数据源对象管理

  1. 导入数据源坐标(以druid数据源为例)
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.16</version></dependency>
  1. 在核心配置文件中配置管理数据源对象(由于第三方技术已经写好,注入方式以及具体属性名需要查
<bean class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/spring_db"/><property name="username" value="root"/><property name="password" value="root"/></bean>
  1. 创建编写模拟配置类App及其运行结果
publicclassApp{publicstaticvoidmain(String[] args){ApplicationContext ctx =newClassPathXmlApplicationContext("applicationContext.xml");DataSource dataSource =(DataSource) ctx.getBean("dataSource");System.out.println(dataSource);}}

在这里插入图片描述

13.加载properties配置文件

  1. 在resources目录下创建jdbc.properties文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db
jdbc.username=root
jdbc.password=root
  1. 在核心配置类中开启context命名空间

在这里插入图片描述

  1. 使用context空间加载properties文件
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
            "><!--1.开启context命名空间--><!--2.使用context空间加载properties文件--><!--    属性占位符,location:加载的文件--><context:property-placeholder location="jdbc.properties" system-properties-mode="NEVER"/><!--3.使用属性占位符${}读取properties文件中的属性--><!--    说明:idea自动识别${}加载的属性值,需要手工点击才可以查阅原始书写格式--><bean class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean><bean id="bookDao"class="org.example.dao.impl.BookDaoImpl"><property name="name" value="${jdbc.driver}"/></bean></beans>
  1. 将绑定好的properties属性注入到bookdao中,通过bookdao中的save方法输出
publicinterfaceBookDao{publicvoidsave();}
publicclassBookDaoImplimplementsBookDao{privateString name;publicvoidsetName(String name){this.name = name;}publicvoidsave(){System.out.println("book dao save ..."+ name);}}
  1. 模拟测试类及输出结果

在这里插入图片描述
6. 小结和拓展

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

14.IOC容器相关

  1. 创建容器

在这里插入图片描述

  1. 获取bean的方式

在这里插入图片描述

  1. 容器类层次结构

(BeanFactory接口创建完毕后,所有的bean均为延迟加载)

在这里插入图片描述

15.spring入门总结

  1. IOC容器相关

在这里插入图片描述

  1. bean相关

在这里插入图片描述

  1. 依赖注入相关

在这里插入图片描述

16.Spring整合Junit

在这里插入图片描述

引用网站及博客

1.【w3cschool】
2. 【sprign教学视频】

总结

欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下。
(博客的参考源码可以在我主页的资源里找到,如果在学习的过程中有什么疑问欢迎大家在评论区向我提出)

标签: spring java 后端

本文转载自: https://blog.csdn.net/HHX_01/article/details/130351973
版权归原作者 东离与糖宝 所有, 如有侵权,请联系我们删除。

“初识Spring -- Spring入门保姆级教程(一)”的评论:

还没有评论