Spring
八大核心模块

Bean
在Spring框架中,Bean 是一个由Spring容器(IoC容器)管理和控制的对象,它是Spring实现控制反转(IoC)和依赖注入(DI)的核心概念。以下是详细解释:
1. Bean 的定义
- Bean 是Spring容器实例化、配置和管理的对象,其生命周期和行为完全由Spring容器控制。
- 它可以是任何Java类(如Service、Repository、Controller等),但需要被Spring容器识别并注册为Bean。
- Bean的定义通常通过注解(如
@Component,@Service,@Repository,@Controller)、XML配置或Java配置类(@Configuration) 来实现。
2. Bean 是控制反转(IoC)的关键
控制反转(Inversion of Control)的核心思想是:对象的创建和管理权从应用代码转移到Spring容器。而Bean正是这一思想的载体,具体体现在以下方面:
(1) 对象的创建和管理由容器负责
- 在传统编程中,对象的创建和依赖关系由开发者自己处理(如通过
new关键字)。 - 在Spring中,开发者只需定义Bean,容器会自动实例化Bean,并管理其生命周期(初始化、销毁等)。
(2) 依赖注入(DI)
- Bean之间的依赖关系由Spring容器自动注入,而不是由对象自身创建或查找依赖。
- 例如,一个Service Bean需要依赖一个Repository Bean,Spring会自动将其注入,而无需手动
new或查找。
(3) 生命周期管理
- Spring容器负责Bean的初始化(如调用
@PostConstruct方法)和销毁(如调用@PreDestroy方法)。 - 容器还会管理Bean的作用域(Scope),例如单例(
@Scope("singleton"))或原型(@Scope("prototype"))。
3. Bean 的特性
(1) 由容器管理
- Bean的实例由Spring容器创建和销毁,而非手动创建(如
new MyClass())。 - 容器维护Bean的实例状态,例如单例Bean在应用中只有一个实例。
(2) 依赖注入
- Spring容器会自动将其他Bean的引用注入到当前Bean的属性中(通过构造函数、Setter方法或字段注入)。
(3) 生命周期方法
- 可以定义初始化方法(如
@PostConstruct)和销毁方法(如@PreDestroy),由容器在特定时机调用。
(4) 可配置性
- 可通过XML、注解或Java配置类定义Bean的属性、作用域、作用域、作用域等。
4. 示例:一个简单的Bean
// 定义一个Bean(使用@Service注解)
@Service
public class UserService {
private final UserRepository userRepository; // 依赖的另一个Bean
// 构造函数注入依赖
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
// 业务方法
public User getUserById(Long id) {
return userRepository.findById(id);
}
}
在Spring容器中:
UserService和UserRepository都会被注册为Bean。- 容器会自动实例化
UserRepository,并将其注入到UserService的构造函数中。 - 容器管理这两个Bean的生命周期(如初始化、销毁)。
5. Bean 与普通Java对象的区别
| 特性 | Bean | 普通Java对象 |
|---|---|---|
| 创建方式 | 由Spring容器实例化 | 由开发者手动创建(如new) |
| 依赖管理 | 依赖由容器注入 | 依赖需手动查找或创建 |
| 生命周期管理 | 容器管理初始化、销毁等 | 生命周期由开发者控制 |
| 作用域 | 可配置为单例、原型等 | 作用域由代码逻辑决定 |
IoC控制反转
IoC(Inversion of Control,控制反转)是Spring框架的核心特性之一。它的核心思想是将对象的创建和管理权交给Spring容器(IoC容器),而不是由程序代码直接创建对象并管理依赖关系。IoC容器通过依赖注入(DI)机制自动装配对象之间的依赖。
1. 核心组件
- BeanFactory:Spring的IoC容器的基础接口,负责实例化、配置和组装Bean。它以延迟加载(Lazy Loading)的方式管理Bean。
- ApplicationContext:BeanFactory的子接口,提供了更丰富的功能(如AOP、国际化、事件传播等),是Spring应用中最常用的IoC容器。
2. 实现步骤
- Bean的定义:通过XML配置、注解(如
@Component、@Service)或Java配置类(@Configuration)声明Bean。 - Bean的实例化:IoC容器通过反射机制(
Class.newInstance()或Constructor.newInstance())创建Bean的实例。 - 依赖注入:IoC容器根据配置或注解(如
@Autowired、@Inject)自动注入依赖的Bean。 - Bean的生命周期管理:
- 初始化:调用
@PostConstruct注解的方法或实现InitializingBean接口。 - 销毁:调用
@PreDestroy注解的方法或实现DisposableBean接口。
- 初始化:调用
3. 依赖注入的方式
- 构造方法注入(推荐):通过
@Autowired标注的构造方法注入依赖。 - Setter方法注入:通过
@Autowired标注的Setter方法注入依赖。 - 字段注入(不推荐):直接通过
@Autowired标注字段注入依赖。
示例1:XML配置
<!-- applicationContext.xml -->
<bean id="userDao" class="com.example.UserDao"/>
<bean id="userService" class="com.example.UserService">
<property name="userDao" ref="userDao"/> <!-- 通过Setter方法注入 -->
</bean>
// UserService.java
public class UserService {
private UserDao userDao;
// 通过Setter方法注入依赖
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
// 通过构造方法注入依赖
public void UserService(UserDao userDao) {
this.userDao = userDao;
}
}
示例2:注解配置
// UserDao.java
@Component
public class UserDao {
// ...
}
// UserService.java
@Service
public class UserService {
@Autowired // 通过字段注入
private UserDao userDao;
}
AOP面向切面编程
AOP(Aspect-Oriented Programming,面向切面编程)将横切关注点(如日志、权限验证、事务管理)从业务逻辑中分离出来,集中管理。Spring AOP通过动态代理实现这一功能。
1. 核心组件
- 切面(Aspect):包含通知和切点的模块,如日志记录模块。
- 通知(Advice):在特定连接点(Join Point)执行的代码,如方法调用前后执行日志。
- 切点(Pointcut):定义哪些连接点(方法)需要被通知。
- 目标对象(Target Object):被通知的对象。
- 代理(Proxy):由AOP框架创建的对象,负责将通知应用到目标对象。
2. 代理机制
Spring AOP通过以下两种方式生成代理对象:
- JDK动态代理:当目标对象实现了接口时,使用JDK动态代理。
- CGLIB代理:当目标对象没有实现接口时,使用CGLIB生成子类代理。
3. 通知类型
| 通知类型 | 作用时机 | 注解 |
|---|---|---|
| Before | 方法执行前 | @Before |
| After | 方法执行后(无论是否抛出异常) | @After |
| After Returning | 方法正常执行后(无异常) | @AfterReturning |
| After Throwing | 方法抛出异常后 | @AfterThrowing |
| Around | 包围方法执行(最常用) | @Around |
4. 切点表达式
通过execution表达式指定哪些方法需要被拦截:
@Pointcut("execution(* com.example.service.*.*(..))")
*:匹配任意返回类型。com.example.service.*:匹配包下的所有类。*:匹配类中的所有方法。(..):匹配任意数量和类型的参数。
示例:日志切面
// LogAspect.java
@Aspect
@Component
public class LogAspect {
@Before("execution(* com.example.service.*.*(..))") // 切点表达式
public void logBefore(JoinPoint joinPoint) {
System.out.println("Method: " + joinPoint.getSignature().getName() + " started.");
}
}
// UserService.java(目标对象)
@Service
public class UserService {
public void saveUser() {
// 业务逻辑
}
}
- 当调用
UserService.saveUser()时:- Spring容器返回一个代理对象(JDK/CGLIB代理)。
- 代理对象拦截方法调用,先执行
logBefore通知。 - 然后调用目标对象的
saveUser()方法。 - 最后根据通知类型(如
@After)执行后续逻辑。

浙公网安备 33010602011771号