手把手带你写一个 MiniSpring
郭屹
前 Sun Microsystems Java 研发工程师,开源软件 MiniSpring、MiniTomcat 开发者
6170 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 26 讲
手把手带你写一个 MiniSpring
15
15
1.0x
00:00/00:00
登录|注册

14|增强模板:如何抽取专门的部件完成专门的任务?

你好,我是郭屹,今天我们继续手写 MiniSpring。
上节课,我们从 JDBC 这些套路性的程序流程中抽取出了一个通用模板。然后进行了拆解,将 SQL 语句当作参数传入,而 SQL 语句执行之后的结果处理逻辑也作为一个匿名类传入,又抽取出了数据源的概念。下面我们接着上节课的思路,继续拆解 JDBC 程序。
我们现在观察应用程序怎么使用的 JdbcTemplate,看这些代码,还是会发现几个问题。
SQL 语句参数的传入还是一个个写进去的,没有抽取出一个独立的部件进行统一处理。
返回的记录是单行的,不支持多行的数据集,所以能对上层应用程序提供的 API 非常有限。
另外每次执行 SQL 语句都会建立连接、关闭连接,性能会受到很大影响。
这些问题,我们都需要在这节课上一个个解决。

参数传入

先看 SQL 语句参数的传入问题,我们注意到现在往 PreparedStatement 中传入参数是这样实现的。
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
if (arg instanceof String) {
pstmt.setString(i+1, (String)arg);
}
else if (arg instanceof Integer) {
pstmt.setInt(i+1, (int)arg);
}
else if (arg instanceof java.util.Date) {
pstmt.setDate(i+1, new java.sql.Date(((java.util.Date)arg).getTime()));
}
}
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文介绍了如何使用增强模板来抽取专门的部件完成专门的任务。作者以手写MiniSpring为例,从JDBC程序中抽取出通用模板,并对其进行拆解和优化。首先,针对SQL语句参数传入问题,引入ArgumentPreparedStatementSetter来统一设置参数值,简化了参数传入的代码。其次,对返回结果的处理进行了优化,提供了多种便捷的方法,如通过RowMapper将ResultSet映射为对象列表。最终,MiniSpring的JdbcTemplate提供了三种query()方法,为用户提供了更多灵活的选择。整体而言,本文通过实际代码示例,展示了如何利用专门的部件来解决JDBC程序中的问题,提高了代码的可读性和灵活性。 文章还介绍了如何改造数据库连接池,以保证多线程安全。通过引入PooledConnection和PooledDataSource类,实现了数据库连接的池化技术,提高了性能。在整个拆解过程中,JdbcTemplate工具变得更加完整、便利。读者可以通过本文了解如何利用专门的部件来解决JDBC程序中的问题,提高代码的可读性和灵活性,以及如何改造数据库连接池以保证多线程安全。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《手把手带你写一个 MiniSpring》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(3)

  • 最新
  • 精选
  • 马儿
    1. initialPool在第一次getConnection的时候初始化,那么就会存在线程安全问题,可以在方法上粗暴的加一个synchronized并在方法中初始化前提前判断是否为空,这样就可以防止连接池中的connections被多次初始化。 2. 获取连接的时候在没有设置active为true之前两个获取连接的线程同时通过了isActive的判断导致两个线程获取到了同一个链接。这里也可以用synchronized来修饰isActive和setActive两个方法,保证一次只有一个线程访问其中的一个方法,不会有两个线程同时访问。并且,对于多核机器来说线程A可能更新完active字段就释放锁了,但是更新后的值还存在自己线程所在的cpu高速缓存中还没有写回到内存,导致线程B读到的还是内存中旧的active值,所以可以再用volatile保证active值修改后马上写回内存并且别的线程也只能从内存读取。 当然,也可以active字段换成线程安全的AtomicBoolean类。 以上是自己的一些思考,请老师指正一下~

    作者回复: 后面有再回首章节,里面给出了参考方案,你看一下。

    2023-04-13归属地:四川
    1
  • 风轻扬
    老师,请教一个问题。query方法中,实例化了一个RowMapperResultSetExtractor,直接用的实现类,没有用接口。而且,我想了一下,也不能用接口,因为Extractor接口里的方法extractData,返回值泛型是Object类型,没办法处理List类型。所以只能是返回list时,new出处理List的Extractor,返回object时,new出处理单对象的Extractor。有点不明白,定义Extractor接口的作用是什么?

    作者回复: 这是面向接口编程,可以有不同实现,在Spring中其实就不只有一个extractor,只是MiniSpring中仅仅实现了一种。Spring中用了一个内部类QueryStatementCallback,接收ResultSetExtractor接口,在里面回调rse.extractData(rs)。

    2023-05-16归属地:北京
  • peter
    请教老师几个问题: Q1:数据库连接池一般设置多大?连接池大小一般是怎么计算的? Q2:数据库连接池与特定的数据库绑定吗? 比如某个连接池可以连接mysql,能连接其他数据库吗? Q3:常见的数据库连接池有哪些? Q4:数据库连接池与高并发有什么关系?

    作者回复: pool size与具体场景有关,看并发中需要访问数据库的连接数。我看到几个中等规模的系统(10000人以内),并发量大约是1000-2000,设置的数据库连接池是100-200. 连接池不绑死数据库系统,数据库系统是由driver来支持的。使用Tomcat的话,里面就有很好的连接池。

    2023-04-13归属地:北京
收起评论
显示
设置
留言
3
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部