Spring源代码分析(11)---JDBC Dao(老树发新芽)

2024-04-27 11:18

本文主要是介绍Spring源代码分析(11)---JDBC Dao(老树发新芽),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在数据库访问技术中,我们有很多选择,诸如jpa,hibernate但是无论选择那种,其实,我们都无法拒绝使用JDBC,Spring为集成JDBC做个很多工作,让我们来看下,这最底层数据库访问技术在春天老树发新芽;

实现,我们来看先,我们如何使用SPRING JDBC的配置和使用:

ApplicationContext.xml:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans
  3.     xmlns="http://www.springframework.org/schema/beans"
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
  6. <!--数据源的配置-->   
  7. <bean id="dataSource"
  8.         class="org.apache.commons.dbcp.BasicDataSource">
  9.         <property name="driverClassName"
  10.             value="com.mysql.jdbc.Driver">
  11.         </property>
  12.         <property name="url" value="jdbc:mysql://127.0.0.1:3306/test"></property>
  13.         <property name="username" value="root"></property>
  14.     </bean>
  15.     <bean id="sessionFactory"
  16.         class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  17.         <property name="dataSource">
  18.             <ref bean="dataSource"></ref>
  19.         </property>
  20.         <property name="hibernateProperties">
  21.             <props>
  22.                 <prop key="hibernate.dialect">
  23.                     org.hibernate.dialect.MySQLDialect
  24.                 </prop>
  25.             </props>
  26.         </property>
  27.     </bean>
  28.    <!--Dao的配置-->
  29.     <bean id="dao" name="dao" class="org.corey.dao.CoreyDao"
  30.         dependency-check="default">
  31.         <property name="dataSource">
  32.             <ref bean="dataSource"></ref>
  33.         </property>
  34.     </bean></beans>
测试:
  1. package org.corey.demo;
  2. import org.corey.dao.CoreyDao;
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;
  5. import org.springframework.jdbc.core.JdbcTemplate;
  6. public class Demo {
  7.     public static void main(String[] args) {
  8.         ApplicationContext context = new ClassPathXmlApplicationContext(
  9.                 "applicationContext.xml");
  10.         CoreyDao dao = (CoreyDao)context.getBean("dao");
  11.         JdbcTemplate template=dao.getJdbcTemplate();
  12.         template.execute("insert into customer(name) values('corey')");
  13.         
  14.     }
  15. }
下面,我们来详细的分析一下Spring Dao的代码结构:


其实,在这里,有很大的感觉让我们有桥接模式的影子,但是这里我们首先要注意,在JDbcDaoSupport并没有依赖于一个抽象的Template接口,一方面是因为在Sprin构建过程中,DaoSupport与Template之间是一对一的关系,JdbcDaoSupport就只能对应JdbcTemplate,所以,不会出现Template的动态切换,所以这里并没有依赖抽象编程;
在程序中,任何功能方法,都是由接口定义实现的,所以我们可以看见,简单的JdbcTemplate的数据库访问功能的实现是由JdbcAccessor定义实现,与数据库的交互动作是由JdbcOperations定义的;

而JdbcTemplate与DataSource的依赖是基于抽象和接口的,这是因为系统所采用的连接池本身就是一个变化点,在这里,我们是而已实现用户选择定制的,所以,这里,我们更多的是采用了把组合聚合原则实现;

分析完基本结构以后,我们再来看一下功能代码的实现:

Dao:
  1. public abstract class DaoSupport implements InitializingBean {
  2.     /** Logger available to subclasses */
  3.     protected final Log logger = LogFactory.getLog(getClass());
  4.         
  5.         //在访问器注入以后执行的初始化方法,运用了模板模式;
  6.     public final void afterPropertiesSet() throws IllegalArgumentException, BeanInitializationException {
  7.         themselves.
  8.         try {
  9.             initDao();
  10.         }
  11.         catch (Exception ex) {
  12.             throw new BeanInitializationException("Initialization of DAO failed: " + ex.getMessage(), ex);
  13.         }
  14.     }
  15.     //模板模式的一个抽象方法;
  16.     protected abstract void checkDaoConfig() throws IllegalArgumentException;
  17.     //初始化Dao,这是模板模式的一个钩子;
  18.     protected void initDao() throws Exception {
  19.     }
  20. }

  1. package org.springframework.jdbc.core.support;
  2. import java.sql.Connection;
  3. import javax.sql.DataSource;
  4. import org.springframework.dao.support.DaoSupport;
  5. import org.springframework.jdbc.CannotGetJdbcConnectionException;
  6. import org.springframework.jdbc.core.JdbcTemplate;
  7. import org.springframework.jdbc.datasource.DataSourceUtils;
  8. import org.springframework.jdbc.support.SQLExceptionTranslator;

  9. public abstract class JdbcDaoSupport extends DaoSupport {
  10.     private JdbcTemplate jdbcTemplate;
  11.     //让注入数据源的时候,自动构造出一个模板属性;
  12.         //在此方法之后,会Dao的检查和自定义初始化;
  13.     public final void setDataSource(DataSource dataSource) {
  14.       this.jdbcTemplate = createJdbcTemplate(dataSource);
  15.        initTemplateConfig();//扩展点;
  16.     }
  17.     //通过注入的数据源,构造出模板
  18.     protected JdbcTemplate createJdbcTemplate(DataSource dataSource) {
  19.         return new JdbcTemplate(dataSource);
  20.     }
  21.     /**
  22.      * Return the JDBC DataSource used by this DAO.
  23.      */
  24.     public final DataSource getDataSource() {
  25.         return (this.jdbcTemplate != null ? this.jdbcTemplate.getDataSource() : null);
  26.     }
  27.     //注入模板
  28.     public final void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
  29.         this.jdbcTemplate = jdbcTemplate;
  30.        initTemplateConfig();//扩展点;
  31.     }
  32.     //得到模板;
  33.     public final JdbcTemplate getJdbcTemplate() {
  34.       return jdbcTemplate;
  35.     }
  36.         
  37.         //判断你时候注入了一个模板或者数据源,如果没有,那么抛出异常
  38.     protected final void checkDaoConfig() {
  39.         if (this.jdbcTemplate == null) {
  40.             throw new IllegalArgumentException("dataSource or jdbcTemplate is required");
  41.         }
  42.     }
  43.     //获取连接;
  44.     protected final Connection getConnection() throws CannotGetJdbcConnectionException {
  45.         return DataSourceUtils.getConnection(getDataSource());
  46.     }
  47.         
  48.         //异常转换;
  49.     protected final SQLExceptionTranslator getExceptionTranslator() {
  50.         return this.jdbcTemplate.getExceptionTranslator();
  51.     }
  52.     //关闭连接;
  53.     protected final void closeConnectionIfNecessary(Connection con) {
  54.         releaseConnection(con);
  55.     }
  56.           
  57.         //释放连接;
  58.     protected final void releaseConnection(Connection con) {
  59.         DataSourceUtils.releaseConnection(con, getDataSource());
  60.     }
  61. }
通过这个方式,我们可见系统给我们保留一个扩展的接口,我们在 initDao()方法中能够自定义的进行扩展,在后面,我们会看到具体的实例;

接下来,我们来分析一下JdbcTemplate:
JdbcAccessor利用DataSource来实现数据库的访问,通过DataSource出取得连接,用Spring对连接进行管理,然后,利用这个连接实现curd功能;


我们来看下一个扩展好的功能更强大的NamedParameterJdbcDaoSupport;

  1. public class NamedParameterJdbcDaoSupport extends JdbcDaoSupport {
  2.     
  3.     private NamedParameterJdbcTemplate namedParameterJdbcTemplate;


  4.     //自定义扩展代码
  5.         //将一个普通的模板包装成为一个可命名参数的模板
  6.     protected void initTemplateConfig() {
  7.         this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(getJdbcTemplate());
  8.     }

  9.     //获得改良后的模板;
  10.     public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() {
  11.       return namedParameterJdbcTemplate;
  12.     }

  13. }
之所以没有抽象出Template接口,在这里也有了良好的体现,我们并不是在JdbcDaoSupport中动态的切换了JdbcTemplate类,而是先生成了一个NamedParameterJdbcDaoSupport类,因为JdbcTemplate无法和NamedParameterJdbcTemplate无法用的方法没有办法共享一个接口来定义(参数和功能不同);
在由JdbcTemplate到NamedParameterJdbcTemplate的过程中间,我们发现功能在其基础上强大了,但是功能还是采用委托的机制实现,我们知道在设计模式中间,动态改变方法的模式有大名鼎鼎的三种
1):装饰模式;
2) :代理模式;
3):适配器模式;
由于前两种模式暴露出的接口都是不变的,而适配器模式就正式现在所急需的;




该模板提供参数映射,能够从Bean属性或者Map中得到相应的参数的名字:

这篇关于Spring源代码分析(11)---JDBC Dao(老树发新芽)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/940356

相关文章

Spring Boot 实现 IP 限流的原理、实践与利弊解析

《SpringBoot实现IP限流的原理、实践与利弊解析》在SpringBoot中实现IP限流是一种简单而有效的方式来保障系统的稳定性和可用性,本文给大家介绍SpringBoot实现IP限... 目录一、引言二、IP 限流原理2.1 令牌桶算法2.2 漏桶算法三、使用场景3.1 防止恶意攻击3.2 控制资源

Mac系统下卸载JAVA和JDK的步骤

《Mac系统下卸载JAVA和JDK的步骤》JDK是Java语言的软件开发工具包,它提供了开发和运行Java应用程序所需的工具、库和资源,:本文主要介绍Mac系统下卸载JAVA和JDK的相关资料,需... 目录1. 卸载系统自带的 Java 版本检查当前 Java 版本通过命令卸载系统 Java2. 卸载自定

springboot下载接口限速功能实现

《springboot下载接口限速功能实现》通过Redis统计并发数动态调整每个用户带宽,核心逻辑为每秒读取并发送限定数据量,防止单用户占用过多资源,确保整体下载均衡且高效,本文给大家介绍spring... 目录 一、整体目标 二、涉及的主要类/方法✅ 三、核心流程图解(简化) 四、关键代码详解1️⃣ 设置

Java Spring ApplicationEvent 代码示例解析

《JavaSpringApplicationEvent代码示例解析》本文解析了Spring事件机制,涵盖核心概念(发布-订阅/观察者模式)、代码实现(事件定义、发布、监听)及高级应用(异步处理、... 目录一、Spring 事件机制核心概念1. 事件驱动架构模型2. 核心组件二、代码示例解析1. 事件定义

SpringMVC高效获取JavaBean对象指南

《SpringMVC高效获取JavaBean对象指南》SpringMVC通过数据绑定自动将请求参数映射到JavaBean,支持表单、URL及JSON数据,需用@ModelAttribute、@Requ... 目录Spring MVC 获取 JavaBean 对象指南核心机制:数据绑定实现步骤1. 定义 Ja

javax.net.ssl.SSLHandshakeException:异常原因及解决方案

《javax.net.ssl.SSLHandshakeException:异常原因及解决方案》javax.net.ssl.SSLHandshakeException是一个SSL握手异常,通常在建立SS... 目录报错原因在程序中绕过服务器的安全验证注意点最后多说一句报错原因一般出现这种问题是因为目标服务器

Java实现删除文件中的指定内容

《Java实现删除文件中的指定内容》在日常开发中,经常需要对文本文件进行批量处理,其中,删除文件中指定内容是最常见的需求之一,下面我们就来看看如何使用java实现删除文件中的指定内容吧... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细介绍3.1 Ja

springboot项目中整合高德地图的实践

《springboot项目中整合高德地图的实践》:本文主要介绍springboot项目中整合高德地图的实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一:高德开放平台的使用二:创建数据库(我是用的是mysql)三:Springboot所需的依赖(根据你的需求再

spring中的ImportSelector接口示例详解

《spring中的ImportSelector接口示例详解》Spring的ImportSelector接口用于动态选择配置类,实现条件化和模块化配置,关键方法selectImports根据注解信息返回... 目录一、核心作用二、关键方法三、扩展功能四、使用示例五、工作原理六、应用场景七、自定义实现Impor

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项