提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
一、前言🚀🚀🚀
☀️
风是自由的,你也是。
本文简介:本人是大二软件工程专业,java后端方向,学习路线:java基础->JDBC->Maven->MyBatis->SSM,通过做笔记分享到博客上的形式,激励自己学习,同时方便复习。由于水平为入门级别,如有错误,希望大佬们评论或私信斧正 Thanks♪(・ω・))ノ
二、Spring简介及学习路线:☀️☀️☀️
1.初识Spring
1.1 spring全家桶
下列这三个技术,基本上能够应对我们企业级开发所有的主流开发功能。这套课程我们讲的是Spring Framework,而这个技术是怎么发展过来的:
1.2 Spring发展史
Spring1.0 在2004年问世。现在24年已经到Spirng6了。。到了5的时候,spring框架全面支持jdk8,你要想做spring开发,你的jdk版本至少是8及以上。
2.Spring系统架构
2.1 Spring Framework系统架构
每个版本都有新的调整。由于这套课程是22年,当时官网没spring5的架构图,而4的架构也已经稳定成熟,故我们来学习Spring4的架构。
第一个模块叫核心容器,Core Container,这个模块是spring框架中最核心的部分,其他所有模块都是依赖它运行的。看到容器(装对象的),根据这样的一个结构设计来看,spirng是用来管对象的技术。
第二块叫AOP(面向切面编程),它放在这个位置说明了它要依赖核心容器的执行,跟面向对象编程一样,它也是一种编程的思想,教你程序应该怎么做,又是一种设计型的概念。具体是做什么的呢?它可以在不惊动原始程序的基础上,给它增强功能,aspect也是对aop思想进行了实现,spring发现aspect技术做的非常好了,于是大胆地将其收录到它的整个技术栈中(所以后面我们学习spirng的aop开发的时候,除了要导aop坐标,还要导aspect坐标)
第三块,叫做Data Access,在整个数据访问的这个大的模块中,Transactions需要单独介绍(spring在事务这个方面做了非常大的突破,开发起来效率非常高的控制方案。)
第四块Web开发这方面,这部分内容到后续的spring mvc的课程中再详细学习。
最下面,test(做测试的) spring在单元测试 (主要学习)和集成测试页给我们提供了一些帮助性的操作。
2.2 Spring 学习路线:
三、Spring全面学习:☀️☀️☀️
1. 核心概念
1.1 IoC控制反转/DI
引入: 将实现类去掉变成接口
new一个对象直接转为外部(Ioc容器,要管大量的对象,也是前面讲的Core Container)提供对象。
现在程序要使用servic对象,IoC可以给你造,但是问题来了,程序运行完,你的service运行完需要Dao,但是你光给我造了个service对象,但是需要Dao才能运行,这两个对象都在IoC容器中,直接把两个bean绑关系。这个过程叫 依赖注入。
(有关系才能绑)
目标
(1) IoC入门案例
思路分析
业务层service: 接口中对应的实现类在数据层。
数据层dao:
运行完后两行都能打印出来。
要交给它管理,需要创建个配置文件
发现没有spring这种结构,原因是还没导包呢,去pom.xml文件导入spring坐标。这里用的是5210的版本,相对稳定了。
加入dependency标签后,加完坐标,便在maven这里刷新一下便可以。
文件创建完后名称叫applicationContext.xml。
创建一个App2.java文件,获取IoC容器,拿到Dao对象
这里是运行两行。
IoC入门案例步骤小总结
(2) DI入门案例
1.基于上一个的基础上往下做,基于IoC管理bean。
2.Service中使用new形式创建的Dao对象是否保留?(否)
3.Service中需要的Dao对象如何进入带Service中?(提供方法)
4.Service与Dao间的关系如何描述?(配置)
1.2.3步骤
4.配置
这里的name名称指的是BookServicelmpl中的bookDao,ref(reference参照对象(参考))是指前边的id=“bookDao”。
DI入门案例步骤小总结
2. bean配置
2.1 bean基础配置
问题:bean的id你写好了,但你的命名习惯跟我的不太一样,我想换个名称。
方法:bean的别名,在配置文件xml中可以弄,通过name标签,中间隔空格或逗号分隔。
下图代码运行结果可以看出Spring创建的是单例对象。那要创建非单例的怎么办?要通过配置的形式完成了,我们需要在bean的属性中再加一个属性scope(作用范围),我们不写默认就是singleton,把它换成prototype,再来运行,它会是两个不同的地址,就是不同的对象了。
Spring为什么默认是单例模式?
为了提高性能,少创建实例,垃圾回收,缓存快速获取,因为要是多例,它会无穷无尽,用一次造一个,而spring在帮我们管理对象的时候,其实就是管理那些可以复用的对象。
上面那些对象是造一次就OK了,下面那种对象,特征是有状态的对象,它里面会记录成员变量的一些属性值。
那么bean是怎么创建出来的呢?
2.2 bean实例化
(1)使用构造方法(常用)
bean本质上就是对象,创建bean使用构造方法完成
现在创建了一个全新的模块
配置文件就定义一个bookDao,然后我们的运行程序是这样子:
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/e98a663780c344f7bac08ed 003577710.png)
加一个构造方法再运行一下,再搞个private私有的发现还可以访问到(运行结果一样)然后给该构造方法加个参数int i,发现报错了,说明spring创建bean的时候,调用的是无参的构造方法。这就是第一种实例化bean的方式一一用构造方法实例化对象。
这里学个知识点:看spring报错信息:
拉到最后面,看最后的信息,然后再看倒数第二个。
这里就是调用一个有参的构造方法,但是它没有所以就报错了。
小总结
第一种实例化bean的方式:
(2)使用静态工厂实例化bean(了解)
回顾:前面说使用静态工厂也能创建对象?这些年用的少,但早些年用的比较多。
什么东西都不用动,加这个东西就OK了。
发现能正常运行。
(3)实例工厂实例化bean(了解)
小结论:
(4)FactoryBean实例化bean(务必要掌握)
第三种方法做了个改良,使得在配置的时候更加方便。
小结论:
指定泛型以后,里面所有的类型都要对准这个泛型,配置的时候就跟我们原来的写法一样,注意:配置这里造出来的对象不是FactoryBean的对象,而是上面FactoryBean接口中getObject()造出来的对象。
2.3 bean的生命周期
这里是新建了一个新案例,结构如下图。.
在这运行的是Dao,也就是我配置的有Service,有Dao,但是我运行的时候只是拿了Dao,Service现在并没有参与到这个程序的运行,下面来控制这个Dao对象的生命周期。比如说你这个bean前边加载的时候要做一些准备,就可以在这个阶段,另外就是bean消亡之前做一些事情,这里面需要两个操作,来代表它的前或者后,这里定义两个方法。
init方法,其实得按照你的业务来写,比如说初始化的时候加载一些资源,获取读取一些文件等等。这里简单点。
把这两方法加上去运行发现是不会执行这两方法的,why?
要做配置,在这里改。
在bean id = bookDao,这里加两个属性,然后再执行,发现只有init操作,但是销毁操作并没有执行,why?
这里我们说一下,我们现在执行的程序是运行在java虚拟机上的, 虚拟机启动了,然后ioc容器加载配置也启动了,然后把bean初始化了,然后我们从里面拿到bean了,执行完了,下一个动作是虚拟机退出了,虚拟机退出没有给你bean销毁的机会。那么怎样才能做到这样呢?
其实方式有两种,这里简单的介绍,第一种:当你的虚拟机退出之前,我把我的容器给关闭了,那就是ctx.close()就行了(加在代码bookDao.save()后面),但是这里会标红,很遗憾这个ApplicantionContex接口不具有这个方法,但其实在下面这个ClassPathXmlApplicantionContex中是有close方法的。
这个close方法是从哪来的?是从它上面的父类继承过来的,追到最后是下面这个接口中来的。
那么想要在我们的程序中正常关闭bean怎么办,复制这个类,然后粘到前面即可。这种关闭的方式是比较暴力的。
方法二:
注册关闭钩子,两者的区别,close关闭相对来说暴力一些,直接关容器,registerShutdownHook则可以放在任意位置。其实这两者在我们实际开发中都不需要写,我们最终做的是web应用,关闭容器这件事是包括TomCat一块的,到后面web那里再说。
总结
接口(了解)
2. 依赖注入
2.1 使用setter注入一一引用类型
2.2 使用setter注入一一简单类型
这样配applicationContext.xml文件,如下图:
2.3使用构造器注入一一简单类型
2.4使用构造器注入一一引用类型(了解)
2.5 依赖自动装配(功能强大)
2.6 集合注入
主要学个格式
2.7 案例:数据源对象管理
第三方资源配置管理
我现在管的bean不是我自己写的,别人的。
导入连接池对象。
学到这里发现,这里也是出现硬编码的问题,代码也是写死了,如果后期账号密码要修改,还要跑到这里修改代码,维护性有待提高,那么接下来怎么办呢?
2.8 加载properties文件 +开启命名空间方式
以后要是有新的命名空间,基本上都是这个套路。
3. 容器
3. 2 容器、bean、依赖注入相关一一总结
4.注解开发
前提:从spring2.0开启,提供了各种各样的注解,到了2.5的时候就比较完善了。第一个内容是2.5,到了spring3.0的时候就推出了纯注解开发,也就是我们要讲的第二个内容。
4.1 注解开发定义bean
对于我们配置bean来说,两步,第一,在要配置的bean上面写上**@Component()可以给它指定名称(这个名称可以理解为ID**)然后在核心配置文件中加上component-scan,到这里bean定义就说完了。
这三个衍射注解的作用:作用其实完全一样,只不过通过不同的注解名称你知道是哪个层的bean。
4.2 纯注解开发
意味着一点配置文件都不写了
总结
第一使用注解形式怎么定义bean,有这么几点,第一个,@Component是通用的,如果说,你要是做表现层、数据层、应用层开发,建议使用下面这三个,第一个用于不是这三层,有可能是工具类。把它们配上后需要配合组件扫描context:component-scan/才能读取。
4.3 注解开发bean作用范围和生命周期
4.4 注解开发依赖注入
4.4.1 自动装配
4.4.2 读取properties文件
回顾以下,@Autowired是解决引用类型注入的,@Qualifier是指定注入的bean的id或者名称,@Value注入我们的简单类型。如果要加载外部的配置文件,用@PropertySource,
4.5 注解开发管理第三方bean
没有配置,只能用编程写。回到手写代码0.0
运行一下App,发现bean已经被创建出来了。
@bean配置完后,不建议写在SpringConfig类里面,两种方式,第一,使用独立的配置类管理第三方bean后,我们使用导入式,也就是@import来做。如下:
简单类型直接数据全都给就行了,引用类型这一块是spring做的比较牛的。它说你给个形参我就内给你数据,到时按类型检测我就给你。
总结:@Bean以后会经常用到,整合框架必须用到,都不是你自己写的,都是别人写的,所以你肯定得用它。
4.5 注解开发总结
5. Spring整合MyBaits开发
5.1 回顾mybatis独立开发
先快速回顾一下Mybatis独立开发是怎么做的, 进入idea中,这里建了一个全新的模块,里边是一套最基本的mybatis操作。
1.先看一下操作的数据库表:
- 与数据库表对应相关的domain里面的Account类,封装数据的。
3.对应的数据层操作接口(),看到着我们能发现是用注解型,在我们的配置文件中就没有那个映射的.xml文件了。
4.没有实现类,说明是用自动代理做的。
5.看一下核心配置,加载jdbc配置
6.这些配置都是比较常规的了,直接下一步看应用程序。
7.首先前三行是造sqlSessionFactory对象。
这里分析得出核心对象为SqlSessionFactory,
这方框里面的数据库连接信息也是为了SqlSessionFactory服务的,而mappers这里是属于我们的业务操作,不属于Mybatis管,所以这一块是伴随着业务改变的。所以到这里应该得出的结论是:mybatis应该管SqlSessionFactory对象。
5.2 Spring整合mybatis
5.2.1 pom文件中加相应坐标
1.打开pom,我们看看现在有哪些坐标,spring-context核心,然后对于我们后面的这个数据源,我们就用druid数据源了,咱们已经整合过了,再往下,mybatis对应的jar包,这个必定少不了,以及mysql对应的jar包。
那么下面还需要两个包,第一个是 spring操作jdbc 用的包, spring-jdbc ,另一个就是 spring整合mybatis 需要用到的jar包。问题:spring跟很多技术整合,那么需要的包是spirng做还是其他技术做呢?(spirng开放出接口标准,你和我整合,你只需要按标准做就行了,等到新技术出现了,它想和spirng整合,按照标准开发即可。)
这里的version不能乱写,要对应好相应的mybatis版本,
5.2.2 选用注解开发(准备工作)
1.创建config.SpringConfig类,做一下数据源,
第三方bean管理,上面引用的变量值从jdbc.properties中来。
@import手动导入,到下面这里就把所有准备工作做完了。
5.2.3 开始mybatis整合
这里则需要重新建一个类放mybatis的内容。
这里的SqlSessionFactory要全部初始化好,既然这些大量的工作都要做,干脆我给你来一个快速创建SqlSessionFactory的东西,叫做SqlSessionFactoryBean,这是个全新的类。
这个SqlSessionFactoryBean来自于这个org.mybatis.spring包。这是mybatis整合spring的包,也是前面导坐标导的这个东西。
我们之前说过但凡是FactoryBean的东西都是造对象,看清楚,它这里实现接口,专门造SqlSessionFactory。这里的getObject()就是返回SqlSessionFactory对象,欧啦。
那么这个SqlSessionFactoryBean该怎么做呢?往里面set东西。
到这里是不是已经整合完了呢???还没有!!!
打开你的配置,来看一下这个,这个 mappers 当我们去 扫描 我们的那个配置最终使用自动代理的形式,帮我们造dao的实现类的。
MapperScannerConfigurer类对象跟上面一样,直接new一个即可,然后返回这个对象。setBasePackage问你映射在哪个包下。
到这里mybatis整合就做好了。以后就是把这几行一复制,改两个package路径,然后就做完了。
原来的这种类就肯定不能要了,写一个全新的运行方式。
解读:
这里getBean注意,不需要拿那个dao,因为我们的dao已经注入到service中了,所以这个直接getBean(AccountService.class)。下面就直接调用findById(),传入一个2,运行完发现OK。到这里其实我们就做完了。
小结
5.3 Spring整合JUnit
其实就是基于spring环境,我们把测试给搞出来。下面我们做的就是text模块下面的测试。
1.创建一个测试类AccountServiceText,测业务层接口(比较多,当然也可以测数据层接口),如果要想让它成为一个测试用例,那必须要到junit包,
导完坐标后刷新一下功能。
整合: @RunWith(),设定类运行器,这是Spring整合junit的专用运行器。
@ContexConfiguration 配置.
先定义一个业务层接口,要想保证这里能用它,@Autowired。
下面顺便写一个测试方法,顺便跳,这里写testFindId,
6. AOP
6.1 AOP简介
6.1.1 AOP核心概念
我们说过spring有两大特征,一个是ioc,应该是aop。
6.1.2 AOP作用
代码不变的基础下增强功能。
6.1 AOP入门案例
开发有两种模式:XML or 注解,这里是用注解的模式,效率 高。
导包这里,aop的坐标除了aop以外,还要导aspectj。
第四步:这里表明当执行到这个方法的时候,这就是一个切入点。
这里的关系就叫切面。绑定切入点与通知关系,@Before()。
第六步: 这里解读下面整篇代码
①@Component:告诉spring来加载我
②加个这@Aspect,告诉spring,这个东西是用来做AOP的。
③@Pointcut,定义好你的切入点。
④public void before(){} 定义好你的通知。
⑤@Before(),把切入点和通知绑定好,就OK了。
第七步:加入@EnableAsepctJAutoProxy,告诉spring我这里有用注解开发的AOP,换句话说,这句话启动了我们配置里面的@Aspect,而这句话则告诉你,你进去识别类里面的内容。
6.2 AOP工作流程
上面的代码:这里读取第二个切入点,因为它下面@Before配置了第二个切入点。
选的切入点是否能跟类中的某个方法配上。
spring的aop模式就是代理模式做的,AOP的整个工作,实际上就是用了代理模式。
6.3 AOP切入点表达式
这里的表达式是指写一句话来表达这个方法。
返回值,包,接口,方法.
这里的疑问,一个程序中要是有很多功能,然后你挨个写切入点表达式,不得把你写死?怎么办勒?往下看。一一>通配符,在AOP中,描述切入点可以使用通配符,加速配置,加速描述。
6.4 AOP通知类型
上一节,咱们研究的是切入点表达式,就是控制给谁加AOP,这一节我们研究的更详细一点,也就是AOP的控制类型。这一节中,我们要介绍几种不同的控制类型。
前置通知
环绕通知,这里我们想让两条语句加在原先的前后,但是这里增强不要紧,直接把我原始操作给隔离了,因为我们在这是做环绕通知,环绕的话肯定是在原始操作的前或后,这里必须有一句话表示对原始操作的调用,格式非常固定。这里pjp.proceed(); 这句话表示对原始操作的调用。
小总结:
不想用原始操作,可以用Around方法注解进行隔离。有什么用呢,比如说你可以做一些权限校验,你呢现在想要运行我的方法,你必须得是一个经理的权限,那好我拿过来看看你是不是经理,如果是,那好你执行,如果不是那这个操作不允许你执行。
这里的例子其实听着有点小萌比,等以后再过来看看这一块。
这里应该就能稍微想明白,怎样对原始操作做隔离,以及为什么出现隔离这种效果。
就是我不想让你调原始操作。
6.4 案例:测量业务层接口执行万次执行效率
这一节我们就要结合前面所学的AOP切入点怎么配,AOP切入类型怎么设来做一个案例。做的就是我们学习AOP做的第一个案例,叫做测量业务层接口执行万次执行效率。
这样的操作还是有点问题的,区分不了是谁。于是。
6.5 AOP通知获取数据
6.6 案例:百度网盘密码数据兼容处理
就是这里要求输入五位,然后这里四位,百度的服务器里面会不会在密码里面自动给你们加一个空格? 不会啊。。 所以在很多网站上面,当用户输入信息后,空格都要处理一下。
写个AOP数据处理类:
第一:获得参数, 第二:遍历参数以后,先去看看你这个是否要参与状况,如果转化的话,trim完了换回那个位置。最后的话调原始操作,不要忘了把原来那个参数加过来。
咱们就通过一个案例体会一下AOP在我们实际开发中的作用,说的简单点就是,如果你有一些相同的大量使用的数据, 需要在很多地方加的话,AOP一定是你的不二选择,使用AOP可以简化你的共性功能的开发。
6.7 AOP总结
AOP是一种编程范式,是指导我们软件如何开发设计的。
7. Spring事务
7.1 Spring事务是怎么做的
事务本身的作用就是为了保证我们数据库操作的一致性。(操作执行同时成功或失败)
spring给出了一个最基本的事务管理器实现,这是一个实现类DataSourceTransactionManager,就是你给我对应的dataSource后,我就能够帮你在业务层开事务,但是它的内部是用jdbc的事务,你现在用的技术是jdbc的技术,就可以用它这个事务管理器的实现对象,很巧合的是,我们Mybatis内部就是jdbc的事务,所以后面我们spring整合mybatis,如果要使用spring的事务,就用这个实现就行。
- 先看一下我们数据库的表,就这么一组数据。
程序中,首先,转账接口,把你要转账的两个账户给我,把金额给我,就可以进行转账。而数据层接口,是两个操作,一个是进钱,一个是出钱。最后我们通过测试用例,测试结果。
要想把spring的事务开了,怎么做呢,
第一步:加注解@Transaction,这注解通常不写实现类上,大部分情况写在接口上。
第二步是到我们的配置中,配置一个spring事务管理器, 如下图:
第三步:你在接口上开了这个东西,但是spring还不知道以事务注解的形式做事务,所以第三步要到spirng配置文件中告诉spring我们现在是用注解形式做事务了。
如下图: 加入@EnableTransactionManagement
7.2 Spring事务角色
这两个操作分别对应的数据层操作。
而在transfer类前加个**@Transactional代表着开启事务**。一旦开启后,是不是意味着一共有三个事务,那现在三个谁都不挨谁阿,于是spirng就做了一件事,你们两个事务既然都在我的控制范围内,你们这两个事务都改成和我一样的事务,全都加到我的事务中。
现在我们的整体操作就只有一个事务了,正因为只有一个事务,所以在它的范围内,一旦出现了异常,它就会将事务回滚,就可以做到所有操作同时执行或同时不执行。
进行一下划分,我们将spring开启的这个事务叫做事务管理员,我们将加入到spring事务中的这个成员叫做事务协调员,
7.3 Spring事务属性
要在数据库进行留痕。
这里就要改一下了,不仅要调用out,inMoney这两个操作,这里边要调用我们两个事务,
到这呢,这段程序算是写完了。
事务传播行为的所有情况。
四、总结:🍓🍓🍓
碎碎念:
现在是2024.5.28凌晨0:36,终于把spirng这一块学完了,由于时间有点赶,这里就暂时不做什么多的总结了,先小结一下spring,刚开始对spring以为就是一种技术,很容易上手,但实则spring包含很多东西,它不仅仅是一个框架,它有Ioc控制反转(解决代码高耦合,不用new对象了,让外部提供对象)、DI 依赖注入 (这个也是学spring后才发现的一个重点内容),bean(对象)配置,到后面的纯注解开发(发现可以不用谢配置文件),原来一路学下来,有挺多技术都是不怎么用的,但是之所以要学它是因为新技术在学它的基础上更好理解和应用(个人想法以后可能会有些许变化)。大概就先概述这么多吧,晚安~
一一2024/5/28