Spring框架

Spring框架学习全笔记:从JDBC基础到IOC/AOP/事务管理

这篇笔记梳理了从原生JDBC、事务与连接池,到Spring框架核心IOC、DI、AOP、JdbcTemplate、声明式事务的全部核心知识点,配套配置与代码示例,适合入门复盘与面试速记。

一、JDBC 基础入门

1.1 JDBC 是什么

JDBC(Java DataBase Connectivity)是Java语言操作数据库的一套官方接口规范,本身不做具体实现,由各个数据库厂商提供实现类(即数据库驱动)。开发者只需要面向JDBC接口编程,无需关心不同数据库的底层差异。

1.2 四大核心对象

对象 作用 核心方法
DriverManager 管理驱动、获取数据库连接 Class.forName("com.mysql.jdbc.Driver") 加载驱动 getConnection(url, username, password) 获取连接
Connection 代表一次数据库连接 createStatement() / prepareStatement(sql) 获取执行对象 setAutoCommit() / commit() / rollback() 管理事务
Statement / PreparedStatement 执行SQL语句 executeQuery(sql) 执行查询,返回结果集 executeUpdate(sql) 执行增删改,返回影响行数
ResultSet 封装查询结果集 next() 移动游标 getXxx(列名/下标) 获取字段值

URL标准格式:jdbc:mysql://localhost:3306/数据库名,本地数据库可简写为 jdbc:mysql:///数据库名

1.3 JDBC 开发标准步骤

  1. 加载驱动类
  2. 通过DriverManager获取Connection连接
  3. 获取SQL执行对象Statement/PreparedStatement
  4. 执行SQL,处理返回结果
  5. 倒序释放资源(ResultSet → Statement → Connection),必须放在finally中保证执行

1.4 SQL注入漏洞与解决方案

  • 产生原因:通过字符串拼接SQL,用户输入的特殊字符会改变SQL语义,绕过校验。
  • 典型 payloadaaa' or '1=1aaa' --
  • 解决方案 :使用PreparedStatement预编译SQL,用?作为参数占位符。SQL语句会先发送给数据库编译固定结构,后续传入的参数只会被当作普通值处理,从根源避免注入。

二、事务与数据库连接池

2.1 事务基础

事务是数据库执行的最小逻辑单元,一组操作要么全部成功,要么全部失败,保证数据一致性。

四大特性(ACID)
  • 原子性(Atomicity):事务是不可分割的整体,所有操作全成功或全失败
  • 一致性(Consistency):事务执行前后,数据的完整性与业务规则保持一致
  • 隔离性(Isolation):并发执行的多个事务之间互不干扰
  • 持久性(Durability):事务一旦提交,数据就永久落盘,即使数据库崩溃也能恢复

2.2 事务隔离级别

不考虑隔离性会引发三类读问题:

  1. 脏读:一个事务读取到了另一个事务未提交的数据
  2. 不可重复读:同一事务内两次查询,因其他事务提交了修改,结果不一致(针对update)
  3. 幻读:同一事务内两次查询,因其他事务提交了新增,结果不一致(针对insert)

四大隔离级别对比:

隔离级别 脏读 不可重复读 幻读 特点
Read uncommitted 安全性最低,效率最高
Read committed Oracle默认级别
Repeatable read MySQL默认级别
Serializable 串行化执行,安全性最高,效率最低

2.3 数据库连接池

为什么需要连接池

传统模式每次操作都要创建、销毁连接,资源开销大、性能低。连接池会预先创建一批连接,程序直接从池中取用,用完归还,实现连接复用,大幅提升性能。

核心规范

所有连接池都实现了JDK提供的DataSource接口,通过getConnection()获取连接,调用close()时不是销毁连接,而是归还给连接池。

Druid 连接池

阿里巴巴开源的数据库连接池,性能、功能、扩展性都优于DBCP、C3P0,是目前主流选择。

核心配置参数:

  • 基础四要素:driverClassNameurlusernamepassword
  • 池参数:initialSize初始连接数、maxActive最大活跃数、maxWait最大等待时间

两种使用方式:

  1. 硬编码:直接new DruidDataSource,set方法设置参数
  2. 配置文件:编写druid.properties,通过DruidDataSourceFactory加载配置创建连接池

三、Spring 核心:IOC 与 DI

3.1 Spring 框架概述

Spring是2003年兴起的轻量级一站式JavaEE开源框架,由Rod Johnson创建,核心思想是控制反转(IOC)面向切面编程(AOP)

核心优势:

  1. 解耦简化:对象的创建与依赖关系全部交给Spring容器管理
  2. AOP支持:方便实现权限、日志、事务等横切逻辑
  3. 声明式事务:通过配置/注解管理事务,无需手动编码
  4. 便于测试:原生整合JUnit
  5. 框架集成:无缝兼容MyBatis、Hibernate、Quartz等主流框架
  6. API封装:简化JDBC、远程调用等难用的JavaEE API

3.2 IOC 控制反转

IOC(Inverse of Control,控制反转)是一种设计思想:把对象的创建权从业务代码中反转交给Spring容器,从根源降低代码耦合度。

核心容器接口
  • ApplicationContext:IOC容器的顶级接口,创建时就加载实例化所有单例Bean
    • ClassPathXmlApplicationContext:加载类路径下的XML配置文件
    • FileSystemXmlApplicationContext:加载磁盘路径的XML配置文件
    • AnnotationConfigApplicationContext:加载纯注解配置类

3.3 Bean 的 XML 配置

基础属性
  • id:Bean的唯一标识,以字母开头,不能包含特殊字符
  • class:Bean的全限定类名
作用范围 scope
  • singleton:单例(默认值),容器启动时创建,容器销毁时销毁
  • prototype:多例,每次获取Bean时才创建
  • request / session:Web环境下,对应请求/会话级别
生命周期方法
  • init-method:Bean实例化、属性注入完成后执行初始化
  • destroy-method:Bean从容器中销毁前执行
Bean的三种实例化方式
  1. 无参构造 (默认,最常用)

    xml 复制代码
    <bean id="userService" class="com.qcbyjy.service.UserServiceImpl" />
  2. 静态工厂 :调用类的静态方法创建对象

    xml 复制代码
    <bean id="us" class="com.qcbyjy.demo1.StaticFactory" factory-method="createUs" />
  3. 实例工厂 :先实例化工厂对象,再调用工厂方法创建Bean

    xml 复制代码
    <bean id="dfactory" class="com.qcbyjy.demo1.Dfactory" />
    <bean id="us" factory-bean="dfactory" factory-method="createUs" />

3.4 DI 依赖注入

DI(Dependency Injection,依赖注入)是IOC的具体实现:Spring创建Bean时,动态将其依赖的对象、属性值注入进去。

三种注入方式
  1. set方法注入(最常用)

    xml 复制代码
    <bean id="os" class="com.qcbyjy.service.OrderServiceImpl">
        <property name="orderDao" ref="od" />
        <property name="msg" value="你好" />
        <property name="age" value="30" />
    </bean>
    • value:注入普通类型值
    • ref:注入其他Bean的引用
  2. 构造方法注入

    xml 复制代码
    <bean id="car" class="com.qcbyjy.demo2.Car">
        <constructor-arg name="cname" value="大奔" />
        <constructor-arg name="money" value="400000" />
    </bean>
  3. 复杂集合类型注入

    数组、List、Map、Properties分别对应<array><list><map><props>标签。

3.5 多配置文件加载

  • 方式一:主配置文件中引入

    xml 复制代码
    <import resource="applicationContext2.xml"/>
  • 方式二:创建容器时传入多个文件名

    java 复制代码
    new ClassPathXmlApplicationContext("applicationContext.xml", "applicationContext2.xml");

3.6 IOC 注解开发

半注解模式(XML + 注解)

先在XML中开启注解扫描:

xml 复制代码
<context:component-scan base-package="com.qcbyjy" />
创建Bean的注解(功能一致,按分层使用)
  • @Component:通用组件,任意类
  • @Controller:表现层
  • @Service:业务层
  • @Repository:持久层
依赖注入注解
  • @Value:注入普通类型(String、int等)
  • @Autowired:默认按类型自动注入引用类型
  • @Qualifier:配合@Autowired使用,强制按名称注入
  • @Resource:Java原生注解,直接按名称注入
生命周期与作用范围
  • @Scope("singleton/prototype"):指定Bean作用范围
  • @PostConstruct:初始化方法,等价于init-method
  • @PreDestroy:销毁方法,等价于destroy-method
纯注解模式

用配置类完全替代XML配置文件:

  • @Configuration:声明当前类是Spring配置类
  • @ComponentScan:指定要扫描的包路径
  • @Bean:写在方法上,将方法返回值存入IOC容器
  • @Import:导入其他子配置类

启动方式:

java 复制代码
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);

3.7 Spring 整合 JUnit

解决单元测试中反复创建容器的繁琐问题:

  1. 引入spring-test依赖

  2. 测试类添加注解

    java 复制代码
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext.xml")
    // 纯注解版:@ContextConfiguration(classes = SpringConfig.class)
    public class DemoTest {
        @Autowired
        private UserService userService;
        
        @Test
        public void test(){
            userService.hello();
        }
    }

四、Spring 核心:AOP 面向切面编程

4.1 AOP 概述

AOP(Aspect Oriented Programming,面向切面编程)采用横向抽取机制,在不修改业务源码的前提下,对方法进行统一增强。

解决的问题

将日志、事务、权限、监控等横切公共逻辑与业务逻辑解耦,减少重复代码,提升开发效率与可维护性。

底层原理

基于动态代理实现:

  • JDK动态代理:基于接口,为目标接口生成代理实现类
  • CGLIB动态代理:基于继承,为目标类生成子类代理对象

4.2 AOP 核心术语

  • Joinpoint(连接点):可以被拦截的方法
  • Pointcut(切入点):实际被拦截增强的方法
  • Advice(通知/增强):拦截后执行的增强逻辑
  • Target(目标对象):被代理的原始对象
  • Weaving(织入):将增强应用到目标对象、生成代理对象的过程
  • Proxy(代理):织入增强后生成的代理对象
  • Aspect(切面):切入点 + 通知的组合

4.3 XML 配置实现 AOP

  1. 引入依赖:spring-aspectsaspectjweaveraopalliance

  2. 配置目标类和切面类的Bean

  3. 配置AOP规则

    xml 复制代码
    <aop:config>
        <aop:aspect ref="myXmlAspect">
            <!-- 前置通知 -->
            <aop:before method="log" pointcut="execution(* com.qcbyjy.*.*ServiceImpl.save*(..))" />
        </aop:aspect>
    </aop:config>
切入点表达式

格式:execution([修饰符] 返回值类型 包名.类名.方法名(参数))

  • 返回值不能省略,可用*代表任意返回值
  • 包名中间可用*代替,..代表任意子包
  • 方法名可用*通配
  • 参数..代表任意类型、任意个数的参数
五种通知类型
通知类型 标签 执行时机
前置通知 <aop:before> 目标方法执行前
后置通知 <aop:after-returning> 目标方法正常返回后
异常通知 <aop:after-throwing> 目标方法抛出异常后
最终通知 <aop:after> 目标方法无论成功失败都执行
环绕通知 <aop:around> 方法执行前后都可增强,需手动调用目标方法

4.4 注解方式实现 AOP

  1. 切面类添加注解

    java 复制代码
    @Component
    @Aspect // 声明为切面类
    public class MyAnnoAspect {
        @Before("execution(* com.qcbyjy.demo3.OrderServiceImpl.save(..))")
        public void log(){
            System.out.println("前置增强执行");
        }
    }
  2. 开启自动代理

    • XML方式:<aop:aspectj-autoproxy/>
    • 纯注解:配置类上加@EnableAspectJAutoProxy

五、Spring 持久层:JdbcTemplate

5.1 概述

JdbcTemplate是Spring封装的JDBC模板工具类,屏蔽了原生JDBC获取连接、处理异常、释放资源等繁琐步骤,简化持久层开发。

5.2 基础配置与使用

xml 复制代码
<!-- 配置数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
</bean>

<!-- 配置JdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource" />
</bean>

核心API:

  • update(sql, 参数...):执行增、删、改,返回影响行数
  • query(sql, RowMapper, 参数...):查询列表,需自定义RowMapper封装结果
  • queryForObject(sql, RowMapper, 参数...):查询单个对象

5.3 Dao层两种编写方式

  1. 直接注入JdbcTemplate:Dao中声明JdbcTemplate属性,提供set方法注入
  2. 继承JdbcDaoSupport :父类内置JdbcTemplate,只需注入DataSource,通过getJdbcTemplate()获取模板对象

六、Spring 声明式事务管理

6.1 核心API

  • PlatformTransactionManager :平台事务管理器接口
    • DataSourceTransactionManager:适用于JDBC、MyBatis
    • HibernateTransactionManager:适用于Hibernate框架
  • TransactionDefinition:事务定义信息,包含隔离级别、传播行为、超时时间、只读属性

6.2 XML 配置声明式事务

xml 复制代码
<!-- 1. 配置平台事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

<!-- 2. 配置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="pay" propagation="REQUIRED" isolation="DEFAULT"/>
        <tx:method name="find*" read-only="true"/>
    </tx:attributes>
</tx:advice>

<!-- 3. 配置AOP织入事务 -->
<aop:config>
    <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.qcbyjy.*.*ServiceImpl.*(..))" />
</aop:config>

6.3 注解方式声明式事务

  1. 开启事务注解驱动

    xml 复制代码
    <tx:annotation-driven transaction-manager="transactionManager" />
  2. 业务类/方法上加@Transactional

    java 复制代码
    @Service
    @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED)
    public class AccountServiceImpl implements AccountService {
        // ...
    }
    • 注解加在类上:类中所有方法都应用事务
    • 注解加在方法上:仅该方法应用事务,优先级更高

6.4 纯注解事务配置

配置类中添加:

  • @EnableTransactionManagement:开启事务注解支持
  • @Bean注册DataSource、JdbcTemplate、PlatformTransactionManager三个组件

总结

Spring的核心本质就是解耦:IOC把对象创建权交给容器,解决业务对象之间的耦合;AOP把横切逻辑抽离出来,解决公共功能与业务逻辑的耦合;声明式事务则是AOP最典型的落地应用。掌握这套核心思想,再去扩展Spring MVC、Spring Boot等生态就会非常顺畅。

相关推荐
Rabitebla1 小时前
C++ 内存管理全面复习:从内存分布到 operator new/delete
java·c语言·开发语言·c++·算法·leetcode
xcLeigh1 小时前
Go入门:main包与main函数的特殊地位
开发语言·后端·golang
Darren2452 小时前
JWT、OAuth 2.0 与 SSO 详解
后端
我是人✓2 小时前
SQL主键与外键
java·数据库
SelectDB2 小时前
Apache Doris / SelectDB 实时分析三大范式:技术能力、选型对比与企业实践
后端
圣光SG2 小时前
Java操作题练习(二)
java·开发语言·python
蜡台2 小时前
Android WebView 设计指南
android·java·kotlin
SelectDB2 小时前
Apache Doris 向量化执行与 CPU 性能优化:技术能力、选型对比与实践
后端
CoderLiu2 小时前
Agent 工程的下一层:为什么「把流程写成图」还不够,还需要 Graph Engineering
前端·人工智能·后端