Java——Spring框架全面解析
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和事务管理,提高代码的可维护性和扩展性。