Spring框架详解(一)
Spring框架详解
-
- 一、控制反转(IoC)与依赖注入(DI)
-
- 概念
- 目的
- 底层原理
- 容器类型
- Bean管理
- 依赖注入(DI)
- 使用方式
- 二、面向切面编程(AOP)
-
- AOP的核心思想
- AOP的关键概念
- AOP的实现机制
- AOP的应用场景
- 样例
-
- 1. 日志记录
- 2. 安全检查
- 3. 异常处理
- 三、Spring Bean的生命周期阶段
- 四、Spring Bean初始化过程概述
- 五、事务
-
- Spring的事务传播机制有哪些?
- Spring中如何开启事务?
- Spring事务失效可能是哪些原因?
一、控制反转(IoC)与依赖注入(DI)
概念
IoC是一种设计模式,也称为依赖注入(Dependency Injection,DI)。在传统的程序设计中,对象之间的依赖关系通常由程序员在类内部直接创建和管理。而在IoC容器中,对象的创建和管理由容器来负责,程序员只需要定义对象的依赖关系,由容器来实现对象的创建和组装。简而言之,IoC把对象的控制权交给了容器,实现了控制反转。
目的
IoC的主要目的是降低模块之间的耦合度,使得对象之间的依赖关系更加灵活、可维护和易于测试。通过IoC容器,程序员可以更加轻松地管理对象之间的依赖关系,而无需在类内部进行复杂的对象创建和管理操作。
底层原理
Spring IoC的底层原理主要包括xml解析、工厂模式和反射等技术。IoC容器通过解析xml配置文件或注解信息,根据这些信息来实例化对象,并将这些对象之间的依赖关系注入到对象中。
容器类型
Spring提供了两种主要的IOC容器实现方式:
- BeanFactory:这是IOC容器的基本实现,是Spring内部使用的接口,通常不提供给开发人员进行直接使用。在加载配置文件时,BeanFactory不会立即创建对象,而是在获取对象时才进行创建。
- ApplicationContext:这是BeanFactory接口的子接口,提供了更多更强大的功能,通常由开发人员进行使用。ApplicationContext能够在服务器启动时完成资源的加载和对象的创建。
Bean管理
在Spring IoC中,Bean是容器管理的主要对象。Bean管理包括两个主要操作:创建对象和注入属性。
- 创建对象:Spring IoC容器可以根据配置文件或注解信息来创建对象。创建对象时,容器会调用类的无参数构造方法或指定的构造方法来实例化对象。
- 注入属性:Spring IoC容器可以将一个对象的依赖关系注入到该对象中。注入属性的方式主要有两种:属性注入和构造注入。属性注入是通过setter方法将依赖对象注入到被依赖对象中;构造注入是在创建对象时通过构造方法将依赖对象传递给被依赖对象。
依赖注入(DI)
DI是IoC思想的一种具体实现方式。在DI中,程序员不需要在类内部创建或查找依赖的对象,而是将依赖对象的引用注入到类中。这样做的好处是降低了类之间的耦合度,提高了代码的可维护性和可扩展性。
使用方式
Spring IoC的使用方式主要有基于xml配置文件的实现和基于注解的实现两种。
- 基于xml配置文件的实现:程序员需要在xml配置文件中声明要创建的Bean和它们之间的依赖关系。然后,通过ApplicationContext接口的实现类(如ClassPathXmlApplicationContext)来加载配置文件并创建IOC容器。最后,从容器中获取需要的Bean并调用它们的方法。
- 基于注解的实现:程序员可以使用Spring提供的注解(如@Component、@Autowired等)来声明Bean和它们之间的依赖关系。然后,通过配置类(使用@Configuration注解)和注解驱动(使用@EnableAnnotationDriven注解)来启用注解支持。最后,通过AnnotationConfigApplicationContext类来创建IOC容器并从容器中获取需要的Bean。
二、面向切面编程(AOP)
面向切面编程(AOP,Aspect-Oriented Programming)是一种通过分离应用中的横切关注点(Cross-Cutting Concerns)来实现模块化的软件开发范式。以下是对AOP的详细解释:
AOP的核心思想
AOP的核心思想是将某些通用功能(如日志、事务管理、异常处理等)从业务逻辑代码中剥离出来,形成独立的切面模块。这样做的好处是,开发者可以在不修改原始代码的情况下为程序添加额外的功能,从而实现代码的解耦和复用。AOP允许开发者以声明式的方式将横切关注点织入到程序中,从而提高代码的可维护性和可扩展性。
AOP的关键概念
- 切面(Aspect):
- 切面是AOP的核心模块,指的是封装横切关注点的模块化单元。
- 切面通常是一个类,其中包含特定的逻辑,如日志记录、事务管理等功能。
- 切面定义了在何时、何地、以何种方式“切入”到业务代码中。
- 连接点(Join Point):
- 连接点是程序执行的某个特定点,比如方法的调用、异常的抛出、字段的访问等。
- 在AOP中,连接点是潜在的切入位置,表示横切关注点可以在何处插入到应用代码中。
- 通知(Advice):
- 通知定义了切面在连接点上的具体行为。
- 常见的通知类型有:Before(方法执行前)、After Returning(方法成功返回后)、After Throwing(方法抛出异常后)、After(无论方法是否抛出异常都会执行)、Around(环绕方法执行,可以在方法调用前后添加自定义逻辑)。
- 切入点(Pointcut):
- 切入点定义了哪些连接点会被通知拦截。
- 通常使用表达式语言来指定切入点,以便匹配特定的方法或类。
AOP的实现机制
AOP的实现机制主要通过“织入”来将切面逻辑集成到目标对象中。织入是将切面逻辑与目标对象结合的过程,也就是将切面应用到目标对象上,使得增强的代码在目标对象的方法中生效。织入的方式决定了切面是如何“切入”到业务代码中的。
AOP的应用场景
AOP在许多场景下都非常有用,包括但不限于:
- 日志记录:在方法执行前后记录日志,以便跟踪和调试。
- 事务管理:管理数据库事务的开启、提交和回滚。
- 安全检查:在方法执行前进行权限验证。
- 异常处理:统一捕获和处理异常。
- 公共参数处理:如为方法添加统一的参数校验或参数填充。
样例
1. 日志记录
// 自定义一个日志记录切面
@Aspect
@Component
public class LoggingAspect {
// 定义切点,匹配com.example.service包及其子包下的所有方法
@Pointcut("execution(* com.example.service..*(..))")
public void serviceLayer() {
}
// 前置通知,在目标方法执行之前执行
@Before("serviceLayer()")
public void logBefore(JoinPoint joinPoint) {
System.out.println("Executing method: " + joinPoint.getSignature());
// ... 记录方法参数等其他信息
}