本文内容:
- 单应用--服务化--微服务架构演变
- Spring
- Mybatis
单应用--服务化--微服务架构演变
J2EE--企业级应用开发平台
- 在信息时代,人们已经习惯了在电脑上进行办公,在各种企业信息管理系统中进行日常事宜,
- J2EE提供了一个良好的企业级应用开发平台,使得应用开发变得很容易
SSH--企业级应用开发范式
- 分层思想更加被人们接受,MVC(Modeling-View-Controller)模式被广泛使用,
- 在企业级应用开发中SSH即是贯彻这套设计模式的常用架构
服务化--面向服务的架构
- 随着互联网时代的到来,用户体量急剧扩增,2B向2C变化,2C的特点是用户访问量大、访问频繁,
- 在企业发展早期,单应用足以支撑业务发展,但是随着用户量增长,单应用的弊端逐渐暴露出来:可扩展性
- 于是模块化的思路开始流行,将应用按业务进行模块拆分,有了垂直拆分、水平拆分
- 垂直拆分是将应用按业务进行拆分,一个完整的业务是一个模块;
- 水平拆分则是使用服务器集群来应用请求
- 低耦合的垂直拆分即是服务化,将一个模块实现为一个服务,对外通过网络通信提供功能支持,服务间仅仅通过网络通信,而非传统架构中按API
微服务架构
- 微服务可以认为是服务化的自然演变,服务化存在着一些弊端,如WebService里(1.依赖于中心化的服务发现机制;2.使用基于xml的SAOP通信协议;3.没有良好的服务管理、治理体系),而微服务则在弥补这些问题
- 在微服务架构中,每个服务可以视为一个单独的应用,能独立开发、测试、部署上线、维护,服务有自己的数据存储、自己的小团队
- 微服务的好处:
- 服务间的耦合程度较低
- 服务的版本迭代、部署上线对其他服务的影响很小
- 专业的人做专业的事,一个小团队负责服务的研发、测试、部署、上线、维护
- 不同团队间的沟通成本较小,只要提供自己服务的RestFul API,内部细节不对外暴露
- 可使用不同语言实现服务
Spring
Spring的来历(虚构场景)
考虑这么一个场景,实现一个UserService类,里面包含对User表的增删查改操作,该类依赖于UserDao进行SQL操作
于是小孟同学在每个方法里 UserDao userDao = new UserDaoImpl();
很好,每个方法都有UserDaoImpl实例对象能进行SQL操作了,功能顺利完成
但是这么做好像有点浪费,因为UserDaoImpl对象没有属性只有方法,所以可以认为每个UserDaoImpl都是一样的,所以我们重复创建了对象
小孟挨P后,痛定思痛于是想到了可以把UserDaoImpl实现成为单例模式,伪代码如下
// 懒汉式单例 public class Singleton2 { // 指向自己实例的私有静态引用 private static Singleton2 singleton2; // 私有的构造方法 private Singleton2(){} // 以自己实例为返回值的静态的公有方法,静态工厂方法 public static Singleton2 getSingleton2(){ // 被动创建,在真正需要使用时才去创建 if (singleton2 == null) { singleton2 = new Singleton2(); } return singleton2; } }
这样看上去好像很完美,但是如果现在又有了TableDao,ScoreDao,或别的什么杀猪刀,那么我们需要每个都套用单例的代码,这就导致了项目中充斥着单例模式的模板代码
这里我们想要的是 一种【多个类,每个类都有一个单独实例】的优雅实现,怎么做呢
就是我们想控制类的实例对象的数目,避免过多的创建实例,降低创建、销毁的开销,这个任务自然而然让我们想到对象池
对象池可以限制一个类的实例的对象数目,用完还回来,复用对象
但是我们的需求又有点特殊,这个池里装的对象是不同类型的,混合型对象池,想象几个班的小朋友去游泳池游泳,不同班穿不同的班服,各班负责老师得时刻注意自己班里在游泳池里的学生和岸上的学生(地滑,学生也皮,追逐打闹)
Spring就是这个 池+老师们 的角色,它可以控制多个不同类的对象的创建数目
翻译自https://blog.csdn.net/bntx2jsqfehy7/article/details/78898595的笔记
什么是spring?
Spring可以视为管理对象生命周期的一个容器,可以解耦对象间的依赖关系,由容器负责在需要的时候才进行对象的创建,例如一个请求访问创建一个、一次方法调用创建一个、单例、一个会话期间创建一个对象;
Spring还提供J2EE的问题的一站式解决方案,它能将其他优秀的框架无缝集成到应用中
使用Spring框架的好处是什么?
- 解耦对象间的依赖
- 控制对象的创建,类似一种特殊的对象池
- 其他重要特性,如AOP支持、事务、国际化等
Spring由哪些模块组成?
Core Container(Beans, Core, Context),AOP,Web,Data,Secure
IOC
Inversion Of Control控制反转,是一种思想,区别于传统方式(由应用来负责对象的创建、依赖),让上下级对象依赖于抽象,配置
现在是外部的容器来负责,通过依赖注入,以及控制Bean的生命周期
好处:
- 可以根据使用场景来生成单例、Web会话、Web请求级的对象
- 解耦依赖关系
DI
依赖注入,需要使用Bean时,由IOC容器负责将其依赖的其他Bean创建并注入
AOP大白话概述
看这冗余的日志代码,安得倚天抽宝剑,把汝截为三截一截遗@After,一截赠@Before,一截还@Test
假设我有多个类的N个方法里都有相同的日志代码,现在我用倚天剑将它们全部裁出,
为了保持原有功能不变,
我需要记录下我在哪裁了,所以我在被剪方法那放一个裁剪标志--拦截规则
也需要记录下裁了哪几部分,每部分是什么
这个记录一切的地方就是被称为切面的异次元空间,在这个空间里,所有的日志代码合而为一,并在需要时在有裁剪标志的地方自动重新出现
AOP中的两种动态代理机制
jdk代理:
- 代理目标:只针对实现了接口的类
- 实现:通过动态生成一个实现公共接口的匿名代理类,将手动需要做的事情打包了
cglib代理:
- 代理目标:任何类
- 实现:通过加载class文件,修改字节码,生成类的子类来覆盖方法实现
Bean的类型:singleton, prototype, request, session
Bean的生命周期
- 创建对象
- 依赖注入
- 设置Bean名、Bean工厂、应用上下文
- 调用Bean拦截链上针对该Bean的初始化前方法
- 调用自定义初始化
- 调用Bean拦截链上针对该Bean的初始化后方法
- 使用
- 调用Bean的destory方法
声明类型:singleton,prototype,session,request
Spring Boot
- 自动配置:默认优于配置
- 条件化配置:允许配置类存在,但是满足条件前都被忽略,常见条件如(类路径是否包含某个类、是否配置了某个Bean等)
- 起步依赖:指定功能,Spring Boot负责引入相关依赖
Mybatis
互联网轻量级SSM框架解密:Spring、Spring MVC、MyBatis源码深度剖析一书中 第三章深入剖析MyBatis源码的笔记
1.介绍
Mybatis是一个ORM持久层框架,可以视作对JDBC的封装,能大幅降低使用JDBC的开发成本
JDBC的缺点
- 连接的构建与销毁
- 繁琐的使用流程(硬编码构建SQL语句,手动设置参数,结果集需要解析)
Mybatis如何解决这些
- 配置数据库连接池,节约连接创建、销毁的开销
- 将SQL语句写在XML配置文件中(更加灵活,在SQL需要变更时无需修改Java代码);通过SQL语句映射动态生成DAO的实现,实现中会进行参数的设置,结果集的解析
2.Mybatis架构
- 执行器:负责执行SQL语句
- 接口:对外暴露方法,供用户调用
- 配置:Mybatis运行时信息(数据源、SQL映射对象)
- 构建器模块:负责解析XML文件来生成配置对象
3.实现原理(构建阶段与执行阶段)
- 构建阶段:解析XML,生成配置、MapperStatement映射对象、SqlSessionFactory
- 执行阶段:SqlSession调用Executor来执行,
- 最后是StatementHandler封装了JDBC进行SQL操作,结果集的解析
构建
- 其中构建模块负责将XML文件解析成为Configuration对象(保护mybatis运行时的信息),其中的核心类时XMLConfigBuilder和XMLMapperBuilder,
- 顾名思义,一个是解析mybatis.xml的,一个是解析mapper.xml中的多条SQL语句,XMLConfigBuilder依赖于XMLMapperBuilder
- SqlSessionFactoryBuilder依赖于解析出的Configuration里构建SqlSessionFactory(其中包含SQL映射)
执行
- 核心类SqlSession包含Executor、Configuration(包含了所有的SQL映射语句,可进行DQL、DML、TPL),
- Executor(jdbc操作)从Configuration中拿到对应的StatementHandler对象,执行它
- StatementHandler:
- 预处理SQL
- 执行Statement
- 包装结果集为Java对象
4.使用步骤
- 写mybatis.xml文件,配置数据源、SQL语句映射文件
- 代码生成器从表中生成实体类
- 定义DAO接口中的各个方法
- 写SQL语句映射文件
- 加载mybatis.xml构建SqlSessionFactory
- 打开SqlSession
- 调用SqlSession的DQL,DML方法进行数据库操作
pojo中的类参数名字和xml文件的参数名字不对应怎么办?
- SQL别名:select id, name,pwd as password from mybatis.user where id = #{id}
- ResultMap结果集映射时对应上
<resultMap id="UserMap" type="User"> <!-- column 数据库中的字段 property 实体类中的属性--> <result column="pwd" property="password"/> </resultMap>
#{}和${}的区别,防止SQL注入
- #{}里面的东西会加上单引号
- SQL预编译,得到含占位符的SQL语句,到时替换占位符就好
- ${}是直接替换