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 开发标准步骤
- 加载驱动类
- 通过DriverManager获取Connection连接
- 获取SQL执行对象Statement/PreparedStatement
- 执行SQL,处理返回结果
- 倒序释放资源(ResultSet → Statement → Connection),必须放在
finally中保证执行
1.4 SQL注入漏洞与解决方案
- 产生原因:通过字符串拼接SQL,用户输入的特殊字符会改变SQL语义,绕过校验。
- 典型 payload :
aaa' or '1=1、aaa' -- - 解决方案 :使用
PreparedStatement预编译SQL,用?作为参数占位符。SQL语句会先发送给数据库编译固定结构,后续传入的参数只会被当作普通值处理,从根源避免注入。
二、事务与数据库连接池
2.1 事务基础
事务是数据库执行的最小逻辑单元,一组操作要么全部成功,要么全部失败,保证数据一致性。
四大特性(ACID)
- 原子性(Atomicity):事务是不可分割的整体,所有操作全成功或全失败
- 一致性(Consistency):事务执行前后,数据的完整性与业务规则保持一致
- 隔离性(Isolation):并发执行的多个事务之间互不干扰
- 持久性(Durability):事务一旦提交,数据就永久落盘,即使数据库崩溃也能恢复
2.2 事务隔离级别
不考虑隔离性会引发三类读问题:
- 脏读:一个事务读取到了另一个事务未提交的数据
- 不可重复读:同一事务内两次查询,因其他事务提交了修改,结果不一致(针对update)
- 幻读:同一事务内两次查询,因其他事务提交了新增,结果不一致(针对insert)
四大隔离级别对比:
| 隔离级别 | 脏读 | 不可重复读 | 幻读 | 特点 |
|---|---|---|---|---|
| Read uncommitted | ❌ | ❌ | ❌ | 安全性最低,效率最高 |
| Read committed | ✅ | ❌ | ❌ | Oracle默认级别 |
| Repeatable read | ✅ | ✅ | ❌ | MySQL默认级别 |
| Serializable | ✅ | ✅ | ✅ | 串行化执行,安全性最高,效率最低 |
2.3 数据库连接池
为什么需要连接池
传统模式每次操作都要创建、销毁连接,资源开销大、性能低。连接池会预先创建一批连接,程序直接从池中取用,用完归还,实现连接复用,大幅提升性能。
核心规范
所有连接池都实现了JDK提供的DataSource接口,通过getConnection()获取连接,调用close()时不是销毁连接,而是归还给连接池。
Druid 连接池
阿里巴巴开源的数据库连接池,性能、功能、扩展性都优于DBCP、C3P0,是目前主流选择。
核心配置参数:
- 基础四要素:
driverClassName、url、username、password - 池参数:
initialSize初始连接数、maxActive最大活跃数、maxWait最大等待时间
两种使用方式:
- 硬编码:直接new DruidDataSource,set方法设置参数
- 配置文件:编写
druid.properties,通过DruidDataSourceFactory加载配置创建连接池
三、Spring 核心:IOC 与 DI
3.1 Spring 框架概述
Spring是2003年兴起的轻量级一站式JavaEE开源框架,由Rod Johnson创建,核心思想是控制反转(IOC)和面向切面编程(AOP)。
核心优势:
- 解耦简化:对象的创建与依赖关系全部交给Spring容器管理
- AOP支持:方便实现权限、日志、事务等横切逻辑
- 声明式事务:通过配置/注解管理事务,无需手动编码
- 便于测试:原生整合JUnit
- 框架集成:无缝兼容MyBatis、Hibernate、Quartz等主流框架
- API封装:简化JDBC、远程调用等难用的JavaEE API
3.2 IOC 控制反转
IOC(Inverse of Control,控制反转)是一种设计思想:把对象的创建权从业务代码中反转交给Spring容器,从根源降低代码耦合度。
核心容器接口
ApplicationContext:IOC容器的顶级接口,创建时就加载实例化所有单例BeanClassPathXmlApplicationContext:加载类路径下的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的三种实例化方式
-
无参构造 (默认,最常用)
xml<bean id="userService" class="com.qcbyjy.service.UserServiceImpl" /> -
静态工厂 :调用类的静态方法创建对象
xml<bean id="us" class="com.qcbyjy.demo1.StaticFactory" factory-method="createUs" /> -
实例工厂 :先实例化工厂对象,再调用工厂方法创建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时,动态将其依赖的对象、属性值注入进去。
三种注入方式
-
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的引用
-
构造方法注入
xml<bean id="car" class="com.qcbyjy.demo2.Car"> <constructor-arg name="cname" value="大奔" /> <constructor-arg name="money" value="400000" /> </bean> -
复杂集合类型注入
数组、List、Map、Properties分别对应
<array>、<list>、<map>、<props>标签。
3.5 多配置文件加载
-
方式一:主配置文件中引入
xml<import resource="applicationContext2.xml"/> -
方式二:创建容器时传入多个文件名
javanew 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
解决单元测试中反复创建容器的繁琐问题:
-
引入
spring-test依赖 -
测试类添加注解
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
-
引入依赖:
spring-aspects、aspectjweaver、aopalliance -
配置目标类和切面类的Bean
-
配置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
-
切面类添加注解
java@Component @Aspect // 声明为切面类 public class MyAnnoAspect { @Before("execution(* com.qcbyjy.demo3.OrderServiceImpl.save(..))") public void log(){ System.out.println("前置增强执行"); } } -
开启自动代理
- XML方式:
<aop:aspectj-autoproxy/> - 纯注解:配置类上加
@EnableAspectJAutoProxy
- XML方式:
五、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层两种编写方式
- 直接注入JdbcTemplate:Dao中声明JdbcTemplate属性,提供set方法注入
- 继承JdbcDaoSupport :父类内置JdbcTemplate,只需注入DataSource,通过
getJdbcTemplate()获取模板对象
六、Spring 声明式事务管理
6.1 核心API
- PlatformTransactionManager :平台事务管理器接口
DataSourceTransactionManager:适用于JDBC、MyBatisHibernateTransactionManager:适用于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 注解方式声明式事务
-
开启事务注解驱动
xml<tx:annotation-driven transaction-manager="transactionManager" /> -
业务类/方法上加
@Transactionaljava@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等生态就会非常顺畅。