目录
在哪些地方用到过反射?
- 框架和工具
许多框架和工具使用反射来实现插件化架构,允许在运行时动态加载和执行类,从而实现更灵活的扩展和定制。
- 配置文件解析
反射可以用于解析配置文件中指定的类名,实例化对象并调用相应的方法,使得配置更加灵活且易于维护。
- 单元测试
在单元测试中,反射可以被用来调用私有方法、设置私有字段等,以便更好地进行测试,并确保代码的健壮性和可维护性。
- 动态代理
反射在动态代理中发挥着重要作用,例如Java中的Proxy类就是基于反射实现的,用于生成动态代理对象。AOP(面向切面编程)是通过动态代理实现的,因此AOP也用到了反射。
- 注解处理器
某些框架和库使用反射来处理注解,例如Spring框架通过反射实现了DI(依赖注入) 的功能。
- ORM(对象关系映射)
ORM框架通常使用反射来映射Java对象与数据库表之间的关系,实现数据的持久化和检索。
- IOC(控制反转)
IOC原理就是工厂模式+反射机制,在IOC容器中是通过反射创建bean对象的
过滤器和拦截器的区别?
过滤器可以简单的理解为“取你所想取”,过滤器关注的是web请求;拦截器可以简单的理解为“拒你所想拒”,拦截器关注的是方法调用,比如拦截敏感词汇。
相同点:
- 过滤器与拦截器都体现了
AOP的编程思想
,都可以实现例如日志、登录鉴权等功能。
不同点:
-
拦截器是基于
java的反射机制
(动态代理)的实现,而过滤器是基于函数的回调
。 -
拦截器
不依赖于servlet容器
,而过滤器依赖于servlet容器。 -
拦截器
只对Controller请求起作用
,而过滤器则可以对 几乎所有的请求起作用。 -
拦截器可以
访问Controller上下文、值、栈里面的对象
,而过滤器不可以。 -
在spring容器的生命周期中,
拦截器可以多次被调用
,而过滤器只能在容器初始化时被调用一次。 -
拦截器
可以获取IOC容器中的各个bean
,而过滤器不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
MyBatis四种拦截器
-
Executor(执行器拦截器):
- 作用:拦截MyBatis执行器方法的执行
- 使用场景: update、query、commit、rollback 等。可以用来实现缓存、事务、分页等功能。
-
StatementHandler(语句拦截器):
- 作用:拦截SQL语句的执行
- 使用场景:prepare、parameterize、batch、update、query 等。可以用来修改 SQL 语句、添加参数、记录日志等功能。
-
ParameterHandler(参数拦截器):
- 作用:拦截SQL语句的参数设置
- 使用场景:setParameters 等。可以用来转换或加密参数等功能。
-
ResultHandler(结果集拦截器):
- 作用:拦截从SQL语句返回的结果集的处理
- 使用场景:handleResultSets、handleOutputParameters 等。可以用来转换或过滤结果集等功能。
拦截器执行位置图示:
JDBC执行流程
JDBC执行流程大致可总结为以下六步:
- 第一步:注册驱动
- 第二步:获取连接
- 第三步:获取数据库操作对象
- 第四步:执行SQL语句
- 第五步:处理查询结果集
- 第六步:释放资源
详细流程可参考:JDBC执行流程
MyBatis执行流程
详细流程可参考:MyBatis执行流程
Mybatis的一级二级缓存
-
一级缓存默认开启,二级缓存默认关闭
-
为什么不用二级缓存?
因为开启二级缓会在内存中开辟一块空间,比如我们有多个应用的话,每个应用都会创建二级缓存会造成内存的大量占用。
-
生命周期:
-
一级缓存:同一个
SqlSession
,当提交或关闭时清空缓存 -
二级缓存:同一个
SqlSessionFactory
对象创建的多个SqlSession
共享其缓存
-
mybatis一对多,多对多
在MyBatis中,处理一对多和多对多关系通常使用association
和collection
标签。
- 一对多:使用
association
标签,指定javaType
属性指向实体类。 - 多对多:同样使用
collection
标签,但需要指定中间关联表
什么是ORM?ORM框架有哪些?
ORM, Object-Relationl Mapping,对象关系映射。它的作用是在关系型数据库 和 对象 之间作一个映射。
常用ORM框架:
-
Hibernate
-
MyBatis
MyBatis与Hibernate的区别
- MyBatis:
- ORM思想: 半自动ORM,需要手动编写SQL语句。
- 特点: 灵活性高,性能好,适合复杂的SQL查询。
- 适用场景: 对SQL有较高要求的场景。
- Hibernate:
- ORM思想: 全自动ORM,通过注解或XML配置映射关系。
- 特点: 自动化程度高,开发效率高,适合简单的CRUD操作。
- 适用场景: 快速开发,对SQL要求不高的场景。
常用动态sql?
-
if
:通过判断条件,动态地生成 SQL 语句。 -
choose
:类似于 Java 中的 switch 语句,根据条件选择生成哪一条 SQL 语句。 -
where
:用于在 SQL 语句的 WHERE 子句中动态拼接条件。 -
set
:用于在 SQL 语句的 SET 子句中动态拼接更新字段和值。 -
foreach
:用于遍历集合或数组,动态生成 SQL 语句。
mybatis接口的底层原理
- 先定义一些接口(称为 Mapper/Dao),并且通过 XML 文件或者注解的方式定义对应的 SQL
- 当我们注入这个Dao的实例时,注入的其实就是mybatis提供的代理实现类,它使用jdk动态代理通过我们的接口动态创建了代理类,并通过Aop进行了增强。
- 当调用 Dao中的方法时,动态代理会根据方法签名找到对应的 SQL 语句,并通过SqlSession 负责执行对应SQL。
- 执行完 SQL 后,根据 Mapper 文件中定义的映射规则,将结果集转换为 Java 对象返回给调用者。
PageHelper分页的原理是什么?
-
当我们在代码中使用
PageHelper.startPage(int pageNum, int pageSize)
设置分页参数之后,其实PageHelper会把他们存储到ThreadLocal
中。 -
PageHelper会在执行器的
query
方法执行之前,会从ThreadLocal中再获取分页参数信息,页码和页大小,然后执行分页算法,计算需要返回的数据块的起始位置和大小。 -
最后,PageHelper会通过修改SQL语句的方式,在SQL后面动态拼接上limit语句,限定查询的数据范围,从而实现物理分页的效果
MyBatis中接口绑定有几种实现方式?
- 通过注解绑定,在接口的方法上面加上 @Select@Update等注解里面包含Sql语句来绑定(SQL语句比较简单的时候,推荐注解绑定)
- 通过xml里面写SQL来绑定, 指定xml映射文件里面的namespace必须为接口的全路径名(SQL语句比较复杂的时候,推荐xml绑定
#{}和${}的区别是什么?
#{ }
被解析成预编译语句,预编译之后可以直接执行,不需要重新编译${ }
仅仅为一个字符串替换,每次执行sql之前需要进行编译,存在 sql 注入问题。