Spring框架作为Java开发的主流框架,以其IOC(控制反转)和AOP(面向切面编程)为核心思想,极大简化了企业级应用开发。本文将系统讲解Spring的核心概念及实战用法,包括IOC容器、依赖注入、AOP、事务管理和定时任务等,并对示例代码进行通用化处理,方便开发者直接参考使用。
一、Spring框架简介
1.1 什么是Spring
Spring是一个开源框架,旨在简化企业级应用开发。它以IOC(控制反转) 和AOP(面向切面编程) 为思想内核,提供了从控制层到数据层的完整解决方案,并支持整合众多第三方框架(如MyBatis、Hibernate等)。
Spring的优势在于:
- 简化代码,降低耦合度
- 提供事务管理、日志等通用功能
- 支持模块化开发,按需选择组件
- 良好的兼容性和扩展性
1.2 Spring 6版本特性
Spring 6是一次跨越式升级,主要变化包括:
- 最低支持JDK 17及以上版本
- 从
javax
命名空间迁移到jakarta
- 兼容Jakarta EE 9/10
- 支持AOT( Ahead-of-Time)编译技术
二、IOC容器:控制反转思想
2.1 IOC核心思想
IOC(Inversion of Control)即控制反转,指将对象的创建权交给框架,而非由开发者手动创建。这一思想解决了传统开发中对象管理混乱、耦合度高的问题。
传统方式vs IOC方式:
- 传统方式:调用者主动创建依赖对象(如
new UserDaoImpl()
) - IOC方式:框架根据配置自动创建并管理对象,开发者只需从容器中获取
2.2 Spring容器类型
Spring提供了多种容器实现,核心接口为BeanFactory
和ApplicationContext
:
容器类型 | 特点 |
---|---|
BeanFactory |
顶层接口,提供基本的Bean管理功能 |
ApplicationContext |
继承BeanFactory ,增加国际化、事件传播等功能,是开发的首选 |
ClassPathXmlApplicationContext |
从类路径加载XML配置文件 |
FileSystemXmlApplicationContext |
从磁盘路径加载XML配置文件 |
AnnotationConfigApplicationContext |
基于注解配置的容器,无需XML |
示例:创建ApplicationContext容器
// 从类路径加载XML配置
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 从注解配置类加载
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
三、依赖注入(DI)详解
依赖注入(Dependency Injection)是IOC思想的具体实现,指框架自动为对象的属性赋值,无需手动set
或构造方法初始化。
3.1 注入方式
(1)Setter注入
通过setter
方法注入属性,XML配置如下:
<bean id="userService" class="com.example.service.UserService">
<!-- name:属性名,ref:引用的Bean ID -->
<property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" class="com.example.dao.UserDaoImpl"/>
对应的Service类需提供setter
方法:
public class UserService {
private UserDao userDao;
// 必须提供setter方法
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
(2)构造方法注入
通过构造方法注入属性,XML配置如下:
<bean id="userService" class="com.example.service.UserService">
<constructor-arg name="userDao" ref="userDao"/>
</bean>
对应的Service类需包含带参构造:
public class UserService {
private UserDao userDao;
// 带参构造方法
public UserService(UserDao userDao) {
this.userDao = userDao;
}
}
(3)自动注入
通过autowire
属性自动匹配注入,无需手动指定依赖:
<!-- byName:按属性名匹配Bean ID;byType:按类型匹配 -->
<bean id="userService" class="com.example.service.UserService" autowire="byType"/>
3.2 注入不同类型属性
Spring支持注入多种类型的属性,包括基本类型、集合、对象等:
<bean id="student" class="com.example.domain.Student">
<!-- 基本类型 -->
<property name="id" value="1"/>
<property name="name" value="张三"/>
<!-- List集合 -->
<property name="hobbies">
<list>
<value>读书</value>
<value>运动</value>
</list>
</property>
<!-- Map集合 -->
<property name="scores">
<map>
<entry key="数学" value="90"/>
<entry key="英语" value="85"/>
</map>
</property>
<!-- 引用对象 -->
<property name="address" ref="address"/>
</bean>
<bean id="address" class="com.example.domain.Address">
<property name="city" value="北京"/>
</bean>
四、基于注解的配置
注解配置可替代XML,简化开发流程,常用注解如下:
4.1 组件扫描
通过@ComponentScan
指定扫描包路径,自动注册标注了@Component
及其衍生注解的类:
@Configuration
@ComponentScan("com.example") // 扫描com.example包下的所有组件
public class SpringConfig {
}
4.2 常用组件注解
注解 | 作用 | 适用场景 |
---|---|---|
@Component |
标识组件,放入Spring容器 | 通用组件 |
@Service |
标识服务层组件 | Service类 |
@Repository |
标识数据访问层组件 | Dao接口实现类 |
@Controller |
标识控制层组件 | Controller类 |
@Scope |
指定Bean的作用域 | 单例/多例控制 |
示例:Service层组件
@Service // 标识为服务层组件
@Scope("singleton") // 单例模式(默认)
public class UserService {
// 业务逻辑...
}
4.3 依赖注入注解
@Autowired
:按类型自动注入@Qualifier
:配合@Autowired
按名称注入@Value
:注入基本类型和字符串
@Service
public class UserService {
// 按类型注入Dao
@Autowired
@Qualifier("userDaoImpl") // 指定Bean名称(当存在多个实现类时)
private UserDao userDao;
// 注入配置文件中的属性
@Value("${app.name}")
private String appName;
}
五、AOP(面向切面编程)
AOP(Aspect Oriented Programming)是Spring的另一核心思想,用于在不修改源码的情况下增强方法功能(如日志、权限校验等)。
5.1 AOP核心术语
- 连接点(Joinpoint):可被增强的方法(Spring中仅支持方法)
- 切点(Pointcut):需要增强的具体方法(通过表达式指定)
- 通知(Advice):增强的逻辑(如前置通知、后置通知等)
- 切面(Aspect):切点 + 通知的组合
- 织入(Weaving):将通知应用到切点的过程
5.2 通知类型
Spring AOP支持5种通知类型:
通知类型 | 作用 |
---|---|
前置通知 | 方法执行前执行 |
后置通知 | 方法正常执行后执行 |
异常通知 | 方法抛出异常时执行 |
最终通知 | 无论是否异常,方法执行后必执行 |
环绕通知 | 方法执行前后均可增强 |
5.3 AOP实战示例
(1)基于注解的AOP配置
// 1. 定义切面类
@Aspect // 标识为切面
@Component
public class LogAspect {
// 2. 定义切点(匹配com.example.service包下的所有方法)
@Pointcut("execution(* com.example.service.*.*(..))")
public void servicePointcut() {}
// 3. 定义通知
@Before("servicePointcut()") // 前置通知
public void beforeAdvice(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("方法" + methodName + "开始执行...");
}
@AfterReturning("servicePointcut()") // 后置通知
public void afterReturningAdvice() {
System.out.println("方法执行成功");
}
}
// 4. 开启AOP支持(在配置类中)
@Configuration
@ComponentScan("com.example")
@EnableAspectJAutoProxy // 开启AOP注解支持
public class SpringConfig {
}
(2)切点表达式
切点表达式用于精确匹配需要增强的方法,语法如下:
execution(访问修饰符 返回值 包名.类名.方法名(参数列表))
常用通配符:
*
:匹配任意字符(如任意返回值、任意方法名)..
:匹配任意层级的包或任意个数的参数
示例:
// 匹配com.example.service包下所有类的public方法
execution(public * com.example.service.*.*(..))
// 匹配com.example.dao包及其子包中所有类的save开头的方法
execution(* com.example.dao..* .save*(..))
六、事务管理
事务管理是企业级应用的核心需求,Spring提供了声明式事务管理,基于AOP实现,无需手动编写事务代码。
6.1 事务的ACID特性
- 原子性(Atomicity):事务是不可分割的单位
- 一致性(Consistency):事务前后数据状态一致
- 隔离性(Isolation):并发事务互不干扰
- 持久性(Durability):事务提交后数据永久生效
6.2 声明式事务配置
(1)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="*" propagation="REQUIRED" isolation="DEFAULT"/>
<!-- 查询方法设置为只读 -->
<tx:method name="get*" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- 3. 配置切面(将事务应用到Service层) -->
<aop:config>
<aop:pointcut id="servicePointcut" expression="execution(* com.example.service.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="servicePointcut"/>
</aop:config>
(2)注解配置方式
// 1. 开启事务注解支持
@Configuration
@EnableTransactionManagement
public class SpringConfig {
// 配置事务管理器...
}
// 2. 在Service类或方法上添加事务注解
@Service
@Transactional // 类级别事务配置
public class OrderService {
// 方法级别事务(覆盖类配置)
@Transactional(propagation = Propagation.REQUIRED)
public void createOrder() {
// 业务逻辑...
}
}
6.3 事务传播行为
事务传播行为定义了多事务方法间的调用规则,常用类型:
REQUIRED
:默认值,若当前有事务则加入,否则新建REQUIRES_NEW
:无论当前是否有事务,均新建事务SUPPORTS
:支持当前事务,若无则以非事务方式执行MANDATORY
:必须在事务中执行,否则抛异常
七、Spring Task定时任务
Spring Task是轻量级的定时任务框架,可替代Quartz实现定时调度功能。
7.1 定时任务配置
(1)XML配置方式
<!-- 1. 扫描组件 -->
<context:component-scan base-package="com.example.task"/>
<!-- 2. 配置定时任务 -->
<task:scheduled-tasks>
<!-- 每5秒执行一次 -->
<task:scheduled ref="myTask" method="execute" cron="0/5 * * * * ?"/>
</task:scheduled-tasks>
<!-- 任务类 -->
@Component
public class MyTask {
public void execute() {
System.out.println("定时任务执行:" + new Date());
}
}
(2)注解配置方式
// 1. 开启定时任务支持
@Configuration
@ComponentScan("com.example.task")
@EnableScheduling
public class TaskConfig {
}
// 2. 定义定时任务
@Component
public class MyTask {
// 每5秒执行一次
@Scheduled(cron = "0/5 * * * * ?")
public void execute() {
System.out.println("定时任务执行:" + new Date());
}
}
7.2 Cron表达式
Cron表达式用于定义定时规则,格式为:秒 分 时 日 月 周 [年]
,常用通配符:
*
:匹配任意值?
:不指定值(用于日和周)/
:递增触发(如0/5
表示每5秒)-
:范围(如10-12
表示10到12点),
:枚举(如MON,FRI
表示周一和周五)
示例:
0 0 8 * * ?
:每天8点执行0 0/30 9-18 * * ?
:9点到18点每30分钟执行0 0 12 ? * SAT
:每周六12点执行
八、总结
本文涵盖了Spring框架的核心知识点,从IOC容器到定时任务,通过通用化的代码示例展示了Spring的实战用法。Spring的优势在于其松耦合的设计理念,通过IOC和AOP大幅简化了开发流程,同时提供了丰富的企业级特性(如事务管理、定时任务等)。
在实际开发中,建议根据项目需求选择XML或注解配置,合理运用AOP和事务管理,提高代码的可维护性和扩展性。