-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Affected files: docs/09后端(框架与中间件)/01后端框架/MyBatis/Mybatis层次结构.md docs/09后端(框架与中间件)/01后端框架/MyBatis/assets/Mybatis层次结构/mybatis层次结构.png docs/09后端(框架与中间件)/01后端框架/MyBatis/(问题)Mapper接口的工作原理是什么?Mapper接口里的方法,参数不同时,方法能重载吗?.md docs/09后端(框架与中间件)/01后端框架/MyBatis/(问题)Mybatis两种常用占位符的区别?.md docs/09后端(框架与中间件)/01后端框架/Spring全家桶/Spring生命周期.md
- Loading branch information
Showing
5 changed files
with
129 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
|
||
![](assets/Mybatis层次结构/mybatis层次结构.png) | ||
|
||
主要的核心部件解释如下: | ||
|
||
- `SqlSession` 作为MyBatis工作的主要顶层API,表示和数据库交互的会话,完成必要数据库增删改查功能 | ||
- `Executor` MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护 | ||
- `StatementHandler` 封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数、将Statement结果集转换成List集合。 | ||
- `ParameterHandler` 负责对用户传递的参数转换成JDBC Statement 所需要的参数, | ||
- `ResultSetHandler` 负责将JDBC返回的ResultSet结果集对象转换成List类型的集合; | ||
- `TypeHandler` 负责java数据类型和jdbc数据类型之间的映射和转换 | ||
- `MappedStatement` MappedStatement维护了一条`<select|update|delete|insert>`节点的封装, | ||
- `SqlSource` 负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回 | ||
- `BoundSql` 表示动态生成的SQL语句以及相应的参数信息 | ||
- `Configuration` MyBatis所有的配置信息都维持在Configuration对象之中。 | ||
|
||
参考:[MyBatis详解 - 总体框架设计](https://pdai.tech/md/framework/orm-mybatis/mybatis-y-arch.html) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions
16
.../09后端(框架与中间件)/01后端框架/MyBatis/(问题)Mapper接口的工作原理是什么?Mapper接口里的方法,参数不同时,方法能重载吗?.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
|
||
- Mapper 接口的全限名,就是映射文件中的 namespace 的值。 | ||
- Mapper 接口的方法名,就是映射文件中 MappedStatement的 id 值。 | ||
- Mapper 接口方法内的参数,就是传递给 sql 的参数。 | ||
|
||
Mapper 接口是没有实现类的,当调用接口方法时,`接口全限名+方法名`拼接字符串作为 key 值,可唯一定位一个 MappedStatement。 | ||
|
||
``` | ||
举例:com.mybatis3.mappers.StudentMapper.findStudentById,可以唯一找到 namespace 为com.mybatis3.mappers.StudentMapper下面id = findStudentById的MappedStatement。 | ||
``` | ||
|
||
在 Mybatis 中,每一个`<select>`、`<insert>`、`<update>`、`<delete>`标签,都会被解析为一个 MappedStatement 对象。 | ||
|
||
Mapper 接口里的方法,是不能重载的,因为是`接口全限名+方法名`的保存和寻找策略。并没有保存参数信息。 | ||
|
||
Mapper 接口的工作原理是 JDK 动态代理,Mybatis 运行时会使用 JDK 动态代理为 Mapper 接口生成代理 proxy 对象,代理对象 proxy 会拦截接口方法,转而执行 MappedStatement 所代表的 sql,然后将 sql 执行结果返回。 |
34 changes: 34 additions & 0 deletions
34
docs/09后端(框架与中间件)/01后端框架/MyBatis/(问题)Mybatis两种常用占位符的区别?.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
|
||
Mybatis两种常用的占位符是`#{}`和`${}`,他们之间的区别是: | ||
|
||
1、含义 | ||
|
||
`#{}`解析为一个JDBC预编译语句(prepared statement)的参数标记符,会替换为`?`。 | ||
|
||
```sql | ||
select * from user where name = #{name}; | ||
``` | ||
|
||
解析为: | ||
|
||
```sql | ||
select * from user where name = ?; | ||
``` | ||
|
||
`${}`仅仅为一个纯碎的 string 替换,在动态 SQL 解析阶段将会进行变量替换,所以如果使用,需要自己加引号 | ||
|
||
```sql | ||
select * from user where name = '${name}'; | ||
``` | ||
|
||
2、使用`#{}`可以有效的防止SQL注入,提高系统安全性。原因在于:预编译机制。预编译完成之后,SQL 的结构已经固定,即便用户输入非法参数,也不会对 SQL 的结构产生影响,从而避免了潜在的安全风险。 | ||
|
||
3、使用建议: 能使用`#{}`的地方就用`#{}`,但表名作为变量时,必须使用`${}`。 | ||
|
||
```sql | ||
select * from #{tableName} where name = #{name}; | ||
|
||
-- 用#{}:sql语句错误, select * from 'user' where name ='mary'; | ||
|
||
-- 用${}:sql语句正确, select * from user where name ='mary'; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
|
||
1、spring 容器初始化 | ||
|
||
- spring 容器实例化,扫描符合 Spring 规则的类(如 @Component、@Service 等注解或在 XML / Java Config 中配置的类),放入一个 list 集合中 | ||
- 遍历 list,继而把每个 class 封装为一个 beanDefinition 对象。每个 beanDefinition 对象都放入一个 map 中(beanFactory 中的 beanDefinitionMap) | ||
|
||
1.5、实现接口 BeanFactoryPostProcessor 进行后置处理 | ||
|
||
- 先执行内置的一些处理 | ||
- 可以在实例化前,调用BeanFactoryPostProcessor拿到beanFactory中的某个类的BeanDefinition对象,从而改变这个bean的定义规则 | ||
|
||
2、实例化对象(构造函数) | ||
|
||
- 从 beanDefinitionMap 依次取出 beanDefinition 进行验证(是否单例,是否非懒加载等) | ||
- 推断 class 使用哪个构造方法 | ||
- 通过反射实例化对象 | ||
- 缓存注解信息,合并 beanDefinition(在某些场景下,Spring 会将子类与父类的 BeanDefinition 进行合并) | ||
- 通过二级缓存暴露一个工厂 bean 对象或早期 bean | ||
|
||
3、依赖注入 | ||
|
||
- 完成属性注入(Setter 注入、构造函数注入、字段注入等) | ||
- 三级缓存(解决循环依赖) | ||
|
||
``` | ||
singletonObjects 一级缓存,完整的 bean | ||
singletonFactories 二级缓存,存的是代理 bean 工厂 | ||
earlySingletonObjects 三级缓存,一般是是半成品的 bean | ||
``` | ||
|
||
3.5、回调部分 Aware 接口 | ||
|
||
- BeanNameAware:注入 Bean 的名称 | ||
- BeanFactoryAware:注入当前使用的 BeanFactory | ||
- ApplicationContextAware:注入当前使用的 ApplicationContext 等 | ||
|
||
4、执行初始化函数 | ||
|
||
- 执行 BeanPostProcessor 前置处理 | ||
- 不同初始化方法的执行顺序:@postConstruct -> 实现 InitializingBean 初始化类 -> xml 中 init-method | ||
- 执行 BeanPostProcessor 后置处理 | ||
|
||
5、BeanPostProcessor 代理(AOP) | ||
|
||
- 如果实现了接口,则使用 jdk 动态代理实现,如果没有实现接口,则使用 cglib 实现代理,当然也可以指定都使用 cglib(jdk 动态代理使用反射实现;cglib 使用 asm 字节码操作库实现) | ||
- 事件分发、发布监听 | ||
|
||
6、放入 bean 池(单例池或 spring 容器,也即一级缓存) | ||
|
||
Spring自动完成 | ||
|
||
手动放入单例池: | ||
|
||
ApplicationContext上下文中调用getBeanFactory().registerSingleton(beanName,对象) | ||
|
||
7.销毁 | ||
|
||
@PreDestory | ||
|
||
DisposableBean接口 | ||
|
||
destroy-method |