前言

笔记整合自

  • 未名湖畔种千玺:跟着狂神学Spring(官方资料+自己整合+细节补充+整合MyBatis)

  • 黑心白莲:【狂神说】Spring学习笔记(全)

  • 酷狗蛋儿的:Spring c命名和p命名空间注入(maven项目)

主要整合自 未名湖畔种千玺,整合内容是对这些博客中不易理解的部分辅以其他文章进行理解并修改,以及对目录结构的修改,以达到见文知意的效果

未名湖畔种千玺的博客结尾有源码的git链接,下载后结合代码查看笔记效果更佳!

适用范围

初学快速入门
往常看十几个小时的视频,并不断暂停做笔记或跟敲代码,往往需要花费视频时长两倍甚至更多的时间才能学完一门课程

而一篇记得好的笔记类博客,能把十几个小时的课程浓缩为一篇文章,大概一两小时能看完,即使需要跟着敲代码,只要笔记中的代码罗列清晰亦可以跟敲

在笔记的基础上跟敲代码,遇到问题加以思考,学习效果是不会比视频差太多的,而时间却节省了极多

并且推荐大家使用类似于我的方法,对照一篇博客学习,不断复制粘贴做成笔记,对不理解的地方查找其他博客并在理解后修改笔记内容,这样能很大程度上深化你的记忆,加强对技术的理解。

老手回顾复习
对于以前学过的技术我就经常忘记,但是我会把做过的代码都留存并记录相关笔记,如需要某些做过学过功能,往往会回头查看笔记和代码

闲谈

我一般是使用印象笔记做笔记,它提供了很强大的管理功能、搜索功能(图片中文字能识别并搜索等)和图片存储功能等

相比于使用md记笔记会流畅不少,以前曾经使用过md做笔记,但是除了发博客方便和使用公式等会比较好用,其他地有很多不方便。

之前没用印象笔记的原因也是因为不适合发博客,不过在后来我研究出了把印象笔记转为博客,现在用印象笔记记笔记可快乐了

如果需要把笔记发成博客,可以参考我写的这篇文章:如何将印象笔记转换为博客

简介

  • Spring:春天------>给软件行业带来了春天!

  • 2002,首次推出了Spring框架的雏形:interface21框架!

  • Spring框架即以interface21框架为基础,经过重新设计,并不断丰富其内涵,于2004年3月24日发布了1.0正式版。

  • Rod Johnson,Spring Framework创始人,著名作者。很难想象Rod Johnson的学历,真的让好多人大吃一惊,他是悉尼大学的博士,然而他的专业不是计算机,而是音乐学。

  • Spring理念:使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架!

  • SSH:Struct2 + Spring + Hibernate!

  • SSM:SpringMVC + Spring + Mybatis!

  • 官网:https://spring.io/projects/spring-framework#overview

  • 官方下载地址:https://repo.spring.io/release/org/springframework/spring/

  • GitHub:https://github.com/spring-projects/spring-framework

优点

  • Spring是一个开源的免费的框架(容器)!

  • Spring是一个轻量级的、非入侵式的框架!

  • 控制反转(IOC),面向切面编程(AOP)!

  • 支持事务的处理,对框架整合的支持!

总结一句话:Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架!

组成

  • Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式 .

  • 核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。

  • Spring Context (上下文):Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。

  • Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向切面的编程功能 , 集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理任何支持 AOP的对象。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖组件,就可以将声明性事务管理集成到应用程序中。

  • Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。

  • Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。

  • Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。

  • Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。

拓展:Spring、SpringMVC、Spring Boot与Spring Cloud

  • 现代化的Java开发!说白就是基于Spring的开发!

  • Spring Boot

    • 是 Spring 的一套快速配置脚手架,可以基于Spring Boot 快速开发单个微服务;

    • 约定大于配置。

    • 因为现在大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提,需要完全掌握Spring及SpringMVC!承上启下的作用!

  • Spring Cloud

    • 是基于Spring Boot实现的;

    • SpringBoot在SpringClound中起到了承上启下的作用,如果你要学习SpringCloud必须要学习SpringBoot。

  • Spring Boot专注于快速、方便集成的单个微服务个体,Spring Cloud关注全局的服务治理框架;

  • Spring Boot使用了约束优于配置的理念,很多集成方案已经帮你选择好了,能不配置就不配置 , Spring Cloud很大的一部分是基于Spring Boot来实现,Spring Boot可以离开Spring Cloud独立使用开发项目,但是Spring Cloud离不开Spring Boot,属于依赖的关系。

项目搭建

  • 新建一个空白的maven项目,删除src目录,以便后续可以建更多的model

以前的写法(案例一)

  • UserDao接口

  • dao实现类

  • UserService接口

  • Service实现类

  • 测试

缺陷

  • 假如上面是从电脑获取数据的方法,那么如果现在我们从mysql获取数据,就不得不在加一个UserDao实现类

  • 对应的我们也要新增一个Services实现类,如下

  • 如果还要从Oracle获取数据,又要加一个UserDao类

  • 对应的又要写一个Services实现类

  • 通过上面代码我们能发现,

    • userDao和service是一对一匹配的,用户的需求一改就很可能可能会影响我们原来的代码,我们需要根据用户的需求去修改原代码!

    • 如果程序代码量十分大,修改一次的成本代价十分昂贵!

  • 为了避免这种繁琐的写法,我们可以使用IOC方式写

    • 通过依赖注入的方式能实现Service和userDao的一对多匹配(一个service能适应多个userDao)
  • 下面我们先介绍IOC,并举例说明用法,之后我们用IOC的方式修改上面的代码

IOC

简介

  • 控制反转IoC(Inversion of Control):

    • 控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。

      • DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。

  • IOC是Spring框架的核心内容 ,spring使用多种方式完美的实现了IOC,可以使用XML配置,也可以使用注解( @Component ),新版本的Spring甚至可以零配置实现IOC。

  • Spring容器在初始化时会读取配置文件,根据配置文件或元数据直接创建与并组装成bean对象,然后存入容器中,程序使用时直接从IOC容器中取出需要的bean对象,而不用程序员自己创建对象。

    • bean对象 :使用Spring来创建对象,在Spring这些都称为Bean

IOC实例

  • 导入jar包

  • 编写一个Hello实体类

  • 编写spring文件,这里命名为 beans.xml

  • class:对象类型

  • property:令对象中默认一个值

  • 测试

思考

  • Hello对象是谁创建的? 由spring创建

  • Hello对象的属性是怎么设置的? 由spring容器设置

  • 这个过程就叫控制反转 :

    • 控制 : 即谁来控制对象的创建 , 传统应用程序的对象是由程序本身控制创建的 , 使用Spring后 , 对象是由Spring来创建的

    • 反转 :

      • 程序本身不创建对象 (不直接new需要对象)

      • 而变成被动的接收对象 (直接Hello hello = 从Bean中获取的的对象)

    • 依赖注入 : 就是利用set方法来进行注入的.

  • IOC是一种编程思想,即由主动的编程变成被动的接收

用IOC的方式修改案例一

  • 新增一个beam.xml文件

  • ref:引用spring容器中创建好的独享

  • value:具体的值(基本数据类型)

  • 测试

  • OK , 到了现在 , 我们彻底不用再程序中去改动了 , 要实现不同的操作 , 只需要在xml配置文件中进行修改 ,而不用修改源代码了!

  • 所谓的IoC,一句话搞定 : 对象由Spring 来创建 , 管理 , 装配 !

IOC创建对象的方式

无参构造方法

  • user.java

  • beans.xml

  • 测试类

  • 结果可以发现,在调用show方法之前,User对象已经通过无参构造初始化了!

有参构造方法

  • UserT.java

  • beans.xml 有三种编写方式

  • 测试

  • 结论:在配置文件加载的时候。其中管理的对象都已经初始化了!

Spring配置

别名

  • 在bean.cml中 使用 alisa标签可以为bean对象设置别名,一个bean对象可以有多个别名

Bean的配置

import

  • 般用于团队开发使用,它可以将多个配置文件,导入合并为一个。

  • 假设,现在项目中有多个人开发,这两个人负责不同的类开发,不同的类需要注册在不同的bean中,我们可以利用import将所有人的beans.xml合并为一个总的!

  • applicationContext.xml

    • 使用时直接使用这个总的xml就行,beans.xml和beans2.xml的内容都在这里面了

  • 到此为止你就算spring入门了,认真体会他的好处吧

依赖注入(DI)

  • 依赖:bean对象的创建依赖于容器

  • 注入:bean对象中的所有属性,由容器来注入

构造器注入

  • 参考上文 IOC创建对象的方式(有参、无参)

set注入(重点)

  • 要求被注入的属性 , 必须有set方法 , set方法的方法名由set + 属性首字母大写 ,

    • 如果属性是boolean类型 , 则不是使用set , 而是 is
  • 不同类型属性,注入方法不同,接下来各个讲解

搭建环境(复杂类型)

  • Address.java

  • Student

常量注入

bean(对象)注入

  • ref:表示引用

数组(array)注入

list注入

map注入

set注入

  • 这里的set表示集合,是一种常用数据结构

null注入

properties注入

  • Properties 类表示了一个持久的属性集。

  • Properties 可保存在流中或从流中加载。

  • 属性列表中每个键及其对应值都是一个字符串。

  • 测试

拓展方式注入:p命名和c命名注入

p命名注入

P命名空间注入是简化构造方法的注入 使用P命名空间注入的两个条件

  • xmlns:p=“http://www.springframework.org/schema/p”

  • 对需要注入的属性提供set方法

c命名注入

C命名空间注入是简化构造方法的注入 使用C命名空间注入的两个条件

  • xmlns:c=“http://www.springframework.org/schema/c”

  • 对需要注入的类提供构造方法

测试

Bean的作用域

  • 在Spring中,那些组成应用程序的主体及由Spring IoC容器所管理的对象,被称之为bean。

    • 简单地讲,bean就是对象但是,是由IOC容器初始化、装配及管理的对象 .
  • 有四种bean四种作用域,对应不同功能

Singleton(单例)

  • 当一个bean的作用域为Singleton,那么Spring IoC容器中只会存在一个共享的bean实例,只会返回bean的同一实例

  • Singleton是单例类型,就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的bean对象都是同一个bean对象。注意,Singleton作用域是Spring中的缺省作用域(默认,不做其他配置时默认为单例模式)

  • 配置例子:

Prototype(原型)

  • 当一个bean的作用域为Prototype,表示一个bean定义对应多个对象实例。

  • Prototype作用域的bean会导致在每次对该bean请求时都会创建一个新的bean实例。

    • 例如,将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法
  • Prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。

    • 根据经验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。
  • 两种配置方式:

Request

  • 当一个bean的作用域为Request,表示在一次HTTP请求中,一个bean定义对应一个实例;即每个HTTP请求都会有各自的bean实例,它们依据某个bean定义创建而成。

    • 该作用域仅在基于web的Spring ApplicationContext情形下有效。
  • 针对每次HTTP请求,Spring容器会根据loginAction bean的定义创建一个全新的LoginAction bean实例,且该loginAction bean实例仅在当前HTTP request内有效,因此可以根据需要放心的更改所建实例的内部状态,而其他请求中根据loginAction bean定义创建的实例,将不会看到这些特定于某个请求的状态变化。当处理请求结束,request作用域的bean实例将被销毁。

  • 配置方法

Session

  • 当一个bean的作用域为Session,表示在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。

  • 针对某个HTTP Session,Spring容器会根据userPreferences bean定义创建一个全新的userPreferences bean实例,且该userPreferences bean仅在当前HTTP Session内有效。与request作用域一样,可以根据需要放心的更改所创建实例的内部状态,而别的HTTP Session中根据userPreferences创建的实例,将不会看到这些特定于某个HTTP Session的状态变化。当HTTP Session最终被废弃的时候,在该HTTP Session作用域内的bean也会被废弃掉。

Bean的自动装配

  • 自动装配是使用spring满足bean依赖的一种方法

  • spring会在应用上下文中为某个bean寻找其依赖的bean

Spring中bean有三种装配机制,分别是:

  1. 在xml中显式配置;

  2. 在java中显式配置;

  3. 隐式的bean发现机制和自动装配。(重要)

Spring的自动装配需要从两个角度来实现,或者说是两个操作:

  1. 组件扫描(component scanning):spring会自动发现应用上下文中所创建的bean;

  2. 自动装配(autowiring):spring自动满足bean之间的依赖,也就是我们说的IOC/DI;

组件扫描和自动装配组合发挥巨大威力,使得需要写的配置降低到最少。

测试环境搭建

  • 新建一个项目

  • 新建两个实体类,Cat Dog 都有一个叫的方法

  • 新建一个用户类User

  • 编写spring配置文件

  • 测试

autowire byName(按名字自动装配)

  • 由于在手动配置xml过程中,常常发生字母缺漏和大小写等错误,而无法对其进行检查,使得开发效率降低。

  • 采用自动装配将避免这些错误,并且使配置简单化。

  • 需要改bean配置,增加一个autowire=“byName”

  • 再次测试,结果依旧成功输出!

  • 我们将 cat 的bean id修改为 catXXX

  • 再次测试, 执行时报空指针java.lang.NullPointerException。

    • 因为按byName规则找不对应set方法,真正的setCat就没执行,对象就没有初始化,所以调用时就会报空指针错误。

小结:

当一个bean节点带有 autowire byName的属性时。

  1. 将查找其类中所有的set方法名,例如setCat,获得将set去掉并且首字母小写的字符串,即cat。

  2. 去spring容器中寻找是否有此字符串名称id的对象。

  3. 如果有,就取出注入;如果没有,就报空指针异常。

autowire byType (按类型自动装配)

  • 使用autowire byType首先需要保证:

    • 同一类型的对象,在spring容器中唯一。

      • 如果不唯一,会报不唯一的异常。
  • 将user的bean配置修改一下 : autowire=“byType”

  • 测试,正常输出

  • 再注册一个cat 的bean对象!

  • 测试,报错:NoUniqueBeanDefinitionException

  • 删掉cat2,将cat的bean名称改掉!测试!因为是按类型装配,所以并不会报异常,也不影响最后的结果。甚至将id属性去掉,也不影响结果。

总结

  • byname的时候, 需要保证所有bean的id唯一, 并且这个bean需要和自动注入的属性的set方法的值一致!

  • bytype的时候, 需要保证所有bean的class唯一, 并且这个bean需要和自动注入的属性的类型一致!

使用注解自动装配

  • jdk1.5开始支持注解,spring2.5开始全面支持注解。

准备

  • 在spring配置文件(beans.xml)中引入context文件头 并 开启属性注解支持!

@Autowired

  • @Autowired是按类型自动转配的,不支持id匹配。

  • 需要导入 spring-aop的包!

  • 直接在属性上使用即可,也可以在set方式上使用

    • 使用Autowired我们可以不用编写Set方法了,前提是你这个自动装配的属性在I0C (Spring) 容器中存在,且符合名字byname!

  • 此时配置文件内容

  • 测试,成功输出结果

  • @Autowired(required=false)

    • 值为false,对象可以为null

    • 值true,对象必须存在,不能为null

@Qualifier

  • @Autowired是根据类型自动装配的,加上@Qualifier则可以根据byName的方式自动装配

  • @Qualifier不能单独使用。

    • 如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解[@Autowired]完成的时候、

    • 我们可以使用@Qualifier(value=“xx”)去配置@Autowired的使用,指定一个唯一的bean对象注入!

  • 配置文件内容修改,保证类型存在对象,且名字部位类的默认名字

  • 此时,不加@qualifier时,直接报错

  • 再属性上添加@Qualifier注解,后成功输出

@Resource

  • @Resource如有指定的name属性,先按该属性进行byName方式查找装配;

  • 其次再进行默认的byName方式进行装配;

  • 如果以上都不成功,则按byType的方式自动装配。

  • 都不成功,则报异常。

  • 实体类

  • beans.xml

  • 配置文件2:beans.xml 删掉cat2

  • 实体类上只保留注解

  • 测试结果:ok

    • 因为 先进行byName查找,失败;再进行byType查找,成功

@Autowired与@Resource异同

  • @Autowired与@Resource都可以用来装配bean。都可以写在字段上,或写在setter方法上。

  • @Autowired默认按类型装配(属于spring规范),默认情况下必须要求依赖对象必须存在

    • 如果异要允许null 值,可以设置它的required属性为false如:@Autowired(required=false)

    • 如果我们想使用名称装配可以结合@Qualifier注解进行使用

    • @ Autowired通过byType的方式实现,而且默认要求这个必须对象存在

  • @Resource(属于J2EE复返),默认按照名称进行装配,名称可以通过name属性进行指定。

    • 如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找

    • 如果注解写在setter方法上默认取属性名进行装配

    • 当找不到与名称匹配的bean时才按照类型进行装配

    • 但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

    • Resource默认通过byname的方式实现,如果找不到名字,则通过byType实现! 如果两个都找不到的情况 下,就报错!

  • 它们的作用相同都是用注解方式注入对象,但执行顺序不同。@Autowired先byType,@Resource先byName。

使用注解自动注入

准备

  • 在spring4之后,想要使用注解形式,必须得要引入aop的包

  • 在配置文件当中,还得要引入一个context约束

applicationContext.xml

Bean的实现

  • 我们之前都是使用 bean 的标签进行bean注入,但是实际开发中,我们一般都会使用注解!

配置扫描注解路径

  • 默认情况下,需要配置扫描哪些包下的注解

  • 但是如果开启了注解注释则可以省去

编写类,增加注解(默认名字小写)

测试

属性注入

  • 不使用注解,可以直接在属性上添加@value(“值”)

  • 如果提供了set方法,可以在set方法上添加@value(“值”)

衍生注解@Controlle、@Service、@Repository

  • 注解,就是替代了在配置文件当中配置步骤而已!更加的方便快捷!

  • @conponent的几个衍生注解

    • @Controller:web层

    • @Service:service层

    • @Repository:dao层

  • 四个注解的功能都是一样的,相当于把这个类个spring管理装配,只是我们对不同层用不同注解,我们看代码时能快速理解

自动装配注解和作用域(@scope)

  • 在Bean的自动装配已经讲过了,可以回顾

  • 这里主要是介绍,不修改bean.xml文件,而是使用注解方式配置的办法

  • 作用域回顾

    • singleton:默认的,Spring会采用单例模式创建这个对象。关闭工厂 ,所有的对象都会销毁。

    • prototype:多例模式。关闭工厂 ,所有的对象不会销毁。内部的垃圾回收机制会回收

  • @scope用法

小结

XML与注解比较

  • XML可以适用任何场景 ,结构清晰,维护方便

  • xml更加万能,适用于任何场合!维护简单方便

    • 所以很多使用spring的公司依旧使用xml文件,而springboot解决了这个问题

xml与注解整合开发 :推荐最佳实践

  • xml管理Bean

  • 注解完成属性注入

  • 我们在使用的过程中,只需要注意一个问题: 必须让注解生效

    • 就需要开启注解的支持

    • 扫描对应的包

基于Java类进行配置

  • JavaConfig 原来是 Spring 的一个子项目,它通过 Java 类的方式提供 Bean 的定义信息,在 Spring4 的版本, JavaConfig 已正式成为 Spring4 的核心功能 。

准备测试环境

  • 编写一个实体类,Dog

  • 建一个config配置包,编写一个MyConfig配置类

    • @Bean 通过方法注册一个bean,相当于我们之前写的一个bean标签

      • 这个方法的名字,就相当于bean标签中id属性

      • 这个方法的返回值,就相当于bean标签中的class属性

    • 两个注释写一个就可以了,作用相同

      • @Configuration //代表这是一个配置类

      • @ComponentScan(“com. kuang.pojo”)//扫描指定包下类

  • 测试类

    • 如果完全使用了配置关方式去做,我们就只能通过AnnotationConfig上下文来获取容器。

    • 通i过配置类的class对象加载

导入其他配置类

  • 新类

  • 利用之前的配置类导入新类

  • 关于这种Java类的配置方式,我们在之后的SpringBoot 和 SpringCloud中还会大量看到,我们需要知道这些注解的作用即可!

代理模式

  • 为什么要学习代理模式,因为AOP的底层机制就是动态代理!

  • 两种代理模式

    • 静态代理

    • 动态代理

静态代理

静态代理角色分析

  • 抽象角色 : 一般使用接口或者抽象类来实现

  • 真实角色 : 被代理的角色

  • 代理角色 : 代理真实角色 ; 代理真实角色后 , 一般会做一些附属的操作 .

  • 客户 : 使用代理角色来进行一些操作 .

代码实现

  • Rent.java(抽象角色)

  • Host.java (真实角色)

  • Proxy.java (代理角色)

  • Client.java(客户)

  • 分析:

    • 在这个过程中,你直接接触的就是中介,就如同现实生活中的样子,

    • 你看不到房东,但是你依旧租到了房东的房子通过代理,这就是所谓的代理模式

      • 程序源自于生活,所以学编程的人,一般能够更加抽象的看待生活中发生的事情。

好处

  • 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .

  • 公共的业务由代理来完成 . 实现了业务的分工 ,

  • 公共业务发生扩展时变得更加集中和方便 .

缺点

  • 类多了 , 多了代理类 , 工作量变大了 . 开发效率降低 .

    • 我们想要静态代理的好处,又不想要静态代理的缺点,所以 , 就有了动态代理 !

静态代理深化

  • 创建一个抽象角色,比如咋们平时做的用户业务,抽象起来就是增删改查!

  • 我们需要一个真实对象来完成这些增删改查操作

  • 需求来了,现在我们需要增加一个日志功能,怎么实现!

    • 思路1 :在实现类上增加代码 【麻烦!】

    • 思路2:使用代理来做,能够不改变原来的业务情况下,实现此功能就是最好的了!

  • 设置一个代理类来处理日志!代理角色

  • 测试访问类

  • 我们在不改变原来的代码的情况下,实现了对原有功能的增强,这是AOP中最核心的思想

AOP闲谈:纵向开发和横向开发

动态代理

  • 动态代理的角色和静态代理的一样 .

  • 动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的

  • 动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理

    • 基于接口的动态代理----JDK动态代理

    • 基于类的动态代理–cglib

    • 现在用的比较多的是 javasist 来生成动态代理 . 百度一下javasist

    • 我们这里使用JDK的原生代码来实现,其余的道理都是一样的!

需要了解的两个类

InvocationHandler 和 Proxy , 打开JDK帮助文档看看

  • InvocationHandler:调用处理程序

  • Proxy : 代理

  • 生成代理类的方法

代码实现

  • Rent.java (抽象角色)

  • Host.java(真实角色)

  • ProxyInvocationHandler.java 代理角色

  • Client.java(租户)

  • 核心 :一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个类,代理的是接口!

动态代理深化

  • 我们来使用动态代理实现代理我们后面写的UserService!

  • 我们也可以编写一个通用的动态代理实现的类!所有的代理对象设置为Object即可!

更直观的举例

  • 动态代理: 在内存中形成的代理类

  • 实现步骤:

    • 代理对象和真实对象实现相同的接口

    • 代理对象= Proxy . newInstance();

    • 使用代理对象调用方法。

    • 增强方法

  • 抽象角色

  • 真实角色

  • 动态代理

动态代理的好处

  • 静态代理有的它都有,静态代理没有的,它也有!

  • 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .

  • 公共的业务由代理来完成 . 实现了业务的分工 ,

  • 公共业务发生扩展时变得更加集中和方便 .

  • 一个动态代理 , 一般代理某一类业务

  • 一个动态代理可以代理多个类,代理的是接口!

AOP

什么是AOP

AOP(Aspect Oriented
Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

AOP在Spring中的作用

  • 提供声明式事务;允许用户自定义切面

  • 以下名词需要了解下:

    • 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 …

    • 切面(ASPECT):横切关注点 被模块化 的特殊对象。即,它是一个类。

    • 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。

    • 目标(Target):被通知对象。

    • 代理(Proxy):向目标对象应用通知之后创建的对象。

    • 切入点(PointCut):切面通知 执行的 “地点”的定义。

    • 连接点(JointPoint):与切入点匹配的执行点。

  • SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice

  • Aop:在 不改变原有代码的情况下 , 去增加新的功能

使用Spring实现AOP

准备

  • 使用AOP织入,需要导入一个依赖包!

第一种方式(Spring API实现)

  • 首先编写我们的业务接口和实现类

  • 然后去写我们的增强类 , 我们编写两个 , 一个前置增强 一个后置增强

  • 最后去spring的文件中注册 , 并实现aop切入实现 , 注意导入约束

  • 测试

  • Aop的重要性 : 很重要 . 一定要理解其中的思路 , 主要是思想的理解这一块 .

  • Spring的Aop就是将公共的业务 (日志 , 安全等) 和领域业务结合起来 , 当执行领域业务时 , 将会把公共业务加进来 . 实现公共业务的重复利用 . 领域业务更纯粹 , 程序猿专注领域业务 , 其本质还是动态代理 .

第二种方式(自定义类实现AOP)

  • 目标业务类不变依旧是userServiceImpl

  • 第一步 : 写我们自己的一个切入类

  • 去spring中配置

  • 测试

第三种方式(使用注解实现)

  • 第一步:编写一个注解实现的增强类

  • 第二步:在Spring配置文件中,注册bean,并增加支持注解的配置

  • 测试

  • 执行顺序

    • 环绕前

    • 方法执行前

    • 增加了一个用户.

    • 环绕后

    • 方法执行后

aop:aspectj-autoproxy说明

  • 通过aop命名空间的<aop:aspectj-autoproxy />声明自动为spring容器中那些配置@aspectJ切面的bean创建代理,织入切面。当然,spring 在内部依旧采用AnnotationAwareAspectJAutoProxyCreator进行自动代理的创建工作,但具体实现的细节已经被<aop:aspectj-autoproxy />隐藏起来了

  • <aop:aspectj-autoproxy />有一个proxy-target-class属性,默认为false,表示使用jdk动态代理织入增强,当配为<aop:aspectj-autoproxy poxy-target-class=“true”/>时,表示使用CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接口,则spring将自动使用CGLib动态代理。

  • 到了这里,AOP的思想和使用相信大家就没问题了!

整合mybatis

配置

导入jar包

  • 需要导入的jar包

    • junit、mybatis、mysql-connector-java、

    • spring相关、aspectJ AOP 织入器、

    • mybatis-spring整合包 【重点】、lombok包

配置Maven静态资源过滤问题

  • 然后就可以编写配置文件,开始写代码了

回忆Mybatis

  • 开发流程

    • 编写实体类

    • 编写核心配置文件

    • 编写接口

    • 编写Mapper.xml

    • 测试

  • 编写pojo实体类

  • 实现mybatis-config.xml 配置文件

  • UserDao接口编写

  • 接口对应的Mapper映射文件

  • 测试类

MyBatis-Spring学习

  • 引入Spring之前需要了解mybatis-spring包中的一些重要类:http://www.mybatis.org/spring/zh/index.html

  • 什么是 MyBatis-Spring?

    • MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。*
  • 知识基础

    • 在开始使用 MyBatis-Spring 之前,你需要先熟悉 Spring 和 MyBatis 这两个框架和有关它们的术语。这很重要
  • MyBatis-Spring 需要以下版本:

  • 如果使用 Maven 作为构建工具,仅需要在 pom.xml 中加入以下代码即可:

  • 要和 Spring 一起使用 MyBatis,需要在 Spring 应用上下文中定义至少两样东西

    • 一个 SqlSessionFactory 和至少一个数据映射器类。
  • 在 MyBatis-Spring 中,可使用SqlSessionFactoryBean来创建 SqlSessionFactory。

    • 要配置这个工厂 bean,只需要把下面代码放在 Spring 的 XML 配置文件中:

  • 注意:SqlSessionFactory需要一个 DataSource(数据源)。这可以是任意的 DataSource,只需要和配置其它 Spring 数据库连接一样配置它就可以了。

  • 在基础的 MyBatis 用法中,是通过 SqlSessionFactoryBuilder 来创建 SqlSessionFactory 的。而在 MyBatis-Spring 中,则使用 SqlSessionFactoryBean 来创建。

  • 在 MyBatis 中,你可以使用 SqlSessionFactory 来创建 SqlSession。一旦你获得一个 session 之后,你可以使用它来执行映射了的语句,提交或回滚连接,最后,当不再需要它的时候,你可以关闭 session。

  • SqlSessionFactory有一个唯一的必要属性:用于 JDBC 的 DataSource。这可以是任意的 DataSource 对象,它的配置方法和其它 Spring 数据库连接是一样的。

  • 一个常用的属性是 configLocation,它用来指定 MyBatis 的 XML 配置文件路径。它在需要修改 MyBatis 的基础配置非常有用。通常,基础配置指的是 < settings> 或 < typeAliases>元素。

  • 需要注意的是,这个配置文件并不需要是一个完整的 MyBatis 配置。确切地说,任何环境配置(),数据源()和 MyBatis 的事务管理器()都会被忽略。SqlSessionFactoryBean 会创建它自有的 MyBatis 环境配置(Environment),并按要求设置自定义环境的值。

  • SqlSessionTemplate 是 MyBatis-Spring 的核心。作为 SqlSession 的一个实现,这意味着可以使用它无缝代替你代码中已经在使用的 SqlSession。

  • 模板可以参与到 Spring 的事务管理中,并且由于其是线程安全的,可以供多个映射器类使用,你应该总是用 SqlSessionTemplate 来替换 MyBatis 默认的 DefaultSqlSession 实现。在同一应用程序中的不同类之间混杂使用可能会引起数据一致性的问题。

  • 可以使用 SqlSessionFactory 作为构造方法的参数来创建 SqlSessionTemplate 对象。

  • 现在,这个 bean 就可以直接注入到你的 DAO bean 中了。你需要在你的 bean 中添加一个 SqlSession 属性,就像下面这样:

  • 按下面这样,注入 SqlSessionTemplate:

整合实现一

  • 引入Spring配置文件beans.xml

  • 配置数据源替换mybaits的数据源

  • 配置SqlSessionFactory,关联MyBatis(固定代码)

  • 关联之后mybatis-config.xml有关数据库连接属性的配置就可以省略掉了,省略部分如下:

  • 注册sqlSessionTemplate,关联sqlSessionFactory;(固定代码)

  • 增加Dao接口的实现类;私有化sqlSessionTemplate

  • 注册bean实现

  • 这一步可以放到另一个配置文件中,可以使得条理清晰。以上Spring配置文件写入spring-dao.xml中,此配置写入applicationContext.xml方便协同整合。

  • spring-dao.xml

  • applicationContext.xm

  • 测试

  • 结果成功输出!现在我们的Mybatis配置文件的状态!发现都可以被Spring整合!

  • mybatis-config.xml

  • Mybatis的配置文件官方定义名字为mybatis-config.xml

  • Spring的配置文件官方定义名字为applicationContext.xml

  • 流程

    • 编写数据源配置

    • sqlSessionFactory

    • sqlSessionTemplate

    • 需要给接口加实现类[]

    • 将自己写的实现类,注入到Spring中

    • 测试使用即可!

整合实现二

  • mybatis-spring1.2.3版以上的才有这个 .

  • dao继承Support类 , 直接利用 getSqlSession() 获得 , 然后直接注入SqlSessionFactory . 比起方式1 , 不需要管理SqlSessionTemplate , 而且对事务的支持更加友好 . 可跟踪源码查看

  • 测试:

  • 将我们上面写的UserDaoImpl修改一下

  • 使用这种方式则可以省略spring-dao.xml文件中的

  • 修改bean的配置

  • 测试

总结

  • 整合到spring以后可以完全不要mybatis的配置文件,除了这些方式可以实现整合之外,我们还可以使用注解来实现,这个等我们后面学习SpringBoot的时候还会测试整合!

声明式事务

回顾事务

  • 事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎!

  • 事务管理是企业级应用程序开发中必备技术,用来确保数据的完整性和一致性。

  • 事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用。

事务的四个属性ACID

  • 原子性(atomicity)

    • 事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用
  • 一致性(consistency)

    • 一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中
  • 隔离性(isolation)

    • 可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏
  • 持久性(durability)

    • 事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中

测试

  • 将上面的代码拷贝到一个新项目中

  • 在之前的案例中,我们给userDao接口新增两个方法,删除和增加用户;

  • mapper文件,我们故意把 deletes 写错,测试!

  • 编写接口的实现类,在实现类中,我们去操作一波

  • 测试

  • 结果

    • 报错:sql异常,delete写错了

    • 结果 :插入成功!

    • 没有进行事务的管理;

  • 我们想让他们都成功才成功,有一个失败,就都失败,我们就应该需要事务!

  • 以前我们都需要自己手动管理事务,十分麻烦!

  • 但是Spring给我们提供了事务管理,我们只需要配置即可;

spring中的事务管理

  • Spring在不同的事务管理API之上定义了一个抽象层,使得开发人员不必了解底层的事务管理API就可以使用Spring的事务管理机制。Spring支持编程式事务管理和声明式的事务管理。

编程式事务管理

  • 将事务管理代码嵌到业务方法中来控制事务的提交和回滚

  • 缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码

声明式事务管理

  • 一般情况下比编程式事务好用。

  • 将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。

  • 将事务管理作为横切关注点,通过aop方法模块化。Spring中通过Spring AOP框架支持声明式事务管理。

使用Spring管理事务,注意头文件的约束导入 : tx (sptring-dao.xml)

事务管理器

  • 无论使用Spring的哪种事务管理策略(编程式或者声明式)事务管理器都是必须的。

  • 就是 Spring的核心事务管理抽象,管理封装了一组独立于技术的方法。

JDBC事务 (sptring-dao.xml)

配置好事务管理器后我们需要去配置事务的通知 (sptring-dao.xml)

spring事务传播特性

事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播。spring支持7种事务传播行为:

  • propagation_requierd:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是最常见的选择,也是默认选择。

  • propagation_supports:支持当前事务,如果没有当前事务,就以非事务方法执行。

  • propagation_mandatory:使用当前事务,如果没有当前事务,就抛出异常。

  • propagation_required_new:新建事务,如果当前存在事务,把当前事务挂起。

  • propagation_not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

  • propagation_never:以非事务方式执行操作,如果当前事务存在则抛出异常。

  • propagation_nested:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作

Spring 默认的事务传播行为是 PROPAGATION_REQUIRED,它适合于绝大多数的情况。

假设 ServiveX#methodX() 都工作在事务环境下(即都被 Spring
事务增强了),假设程序中存在如下的调用链:Service1#method1()->Service2#method2()->Service3#method3(),那么这
3 个服务类的 3 个方法通过 Spring 的事务传播机制都工作在同一个事务中。

就好比,我们刚才的几个方法存在调用,所以会被放在一组事务当中!

配置AOP

导入aop的头文件!(sptring-dao.xml)

进行测试

删掉刚才插入的数据,再次测试!

思考

为什么需要配置事务?

  • 如果不配置,就需要我们手动提交控制事务;

  • 事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎!

狂神说java spring篇 学习笔记相关推荐

  1. Java基础篇 学习笔记

    List item Java基础篇 学习笔记 java基础篇 第1章 计算机.程序和java概述 学习笔记 1.1什么是计算机 简单来说:计算机就是 ' 存储 ' 和 ' 处理 ' 数据的电子设备. ...

  2. 【狂神说Java】Vue学习笔记01:前端知识体系

    本文根据B站[狂神说Java]vue系列视频整理,如需观看视频,请点击链接跳转 [狂神说Java]Vue视频 2.前端知识体系 想要成为真正的"互联网Java全栈工程师"还有很长的 ...

  3. 【狂神说Java】Vue学习笔记03-----基础语法指令

    本文根据B站[狂神说Java]vue系列视频整理,如需观看视频,请点击链接跳转 [狂神说Java]Vue视频 1.v-bind   我们已经成功创建了第一个Vue应用!看起来这跟渲染一个字符串模板非常 ...

  4. 狂神说java java基础篇 学习笔记

    java基础的视频内容笔记都在这了 前言等字数非常长的章节,使用了AI语音识别成文字后修改的,有错漏欢迎提出 面对对象模块的按照自己的理解进行了内容修改,可以对比原视频内容理解,如有建议欢迎提出 前言 ...

  5. Spring.NET学习笔记10——方法的注入(基础篇) Level 200

    多数用户都会将容器中的大部分对象布署为singleton模式.当一个singleton对象需要和另一个singleton对象协作,或者一个非singleton对象需要和另一个非singleson对象协 ...

  6. java/android 设计模式学习笔记(1)--- 单例模式

    前段时间公司一些同事在讨论单例模式(我是最渣的一个,都插不上嘴 T__T ),这个模式使用的频率很高,也可能是很多人最熟悉的设计模式,当然单例模式也算是最简单的设计模式之一吧,简单归简单,但是在实际使 ...

  7. Spring Boot学习笔记-实践建言

    2019独角兽企业重金招聘Python工程师标准>>> 本文延续<Spring Boot学习笔记-快速示例>,从开发指南中摘出一些实践经验可供参考.这也是笔者看到的眼前一 ...

  8. Spring.NET学习笔记——前言

    Spring.NET是一个应用程序框架,其目的是协助开发人员创建企业级的.NET应用程序.它提供了很多方面的功能,比如依赖注入.面向方面编程(AOP).数据访问抽象及ASP.NET扩展等等.Sprin ...

  9. Spring Cloud 学习笔记(2 / 3)

    Spring Cloud 学习笔记(1 / 3) Spring Cloud 学习笔记(3 / 3) - - - 56_Hystrix之全局服务降级DefaultProperties 57_Hystri ...

最新文章

  1. exsi vmfs 没了_它是“推粪机”,隔三差五吃一盘,口臭没了排出宿便,肠道变干净...
  2. pikachu安装以及安装时遇到的的问题——pikachu数据库链接不上config.inc.php 以及侧边栏访问没有反应,只有URL加了个#原因和解决办法
  3. 深度学习之眼睛状态识别混淆矩阵的绘制
  4. SQL语言:嵌入式SQL知识笔记
  5. ajax请求解析json,如何为Ajax请求解析json响应?
  6. js调用摄像头麦克风,截取摄像头图像 js调用摄像头录像保存本地
  7. python项目方案书模板格式_项目策划书格式及范文
  8. 三对角阵的一维数组表示
  9. html2canvas 截图丢失部分元素的问题
  10. Log4j 漏洞最早由阿里云团队发现;HashiCorp 挂牌上市,市值 152 亿美元;Go 1.18 Beta1 发布 | 开源日报
  11. 【原】群晖btrfs系统修复
  12. 前端CSS核心部分盒子模型
  13. 如何查看apk安装包源代码??Android反编译apk,解包,打包,签名一体化实测 ,修改图片音频软件名称版本号等入门
  14. 2021-04-24
  15. Latex论文写作小技巧记录,不断更新
  16. 【kimol君的无聊小发明】—用python写PDF转换器
  17. AlexNet_tensorflow2.1_实现狼狗分类
  18. 计算机配置好坏怎么看,怎么看电脑配置,电脑配置好坏信息一目了然-腾讯电脑管家...
  19. 影像组学平台助力又一位培训班学员论文见刊:基于机器学习的多参数MRI放射组学预测直肠癌患者新辅助放化疗后不良反应
  20. 需求定律公式和需求弹性推导——《可…

热门文章

  1. 比尔盖茨在警察局留下的照片
  2. realsenseD435i ros auto_exposure设置
  3. ICLR 2023 | 达摩院开源轻量人脸检测DamoFD
  4. 容器镜像[容器培训专题]
  5. idea社区版开发OSGi项目
  6. 解耦神器之观察者模式
  7. c语言java对电脑配置的要求,java程序员需要的电脑配置
  8. 互联网+管理,金蝶云ERP引领中国管理软件新时代
  9. 【python】pandas的append函数报错、不能使用
  10. 细说 QUEST CENTRAL FOR DB2 八宗罪