Spring

八大核心模块

image

Bean

在Spring框架中,Bean 是一个由Spring容器(IoC容器)管理和控制的对象,它是Spring实现控制反转(IoC)和依赖注入(DI)的核心概念。以下是详细解释:


1. Bean 的定义

  • Bean 是Spring容器实例化、配置和管理的对象,其生命周期和行为完全由Spring容器控制。
  • 它可以是任何Java类(如Service、Repository、Controller等),但需要被Spring容器识别并注册为Bean。
  • Bean的定义通常通过注解(如@Component, @Service, @Repository, @ControllerXML配置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容器中:

  1. UserServiceUserRepository 都会被注册为Bean。
  2. 容器会自动实例化UserRepository,并将其注入到UserService的构造函数中。
  3. 容器管理这两个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. 实现步骤

  1. Bean的定义:通过XML配置、注解(如@Component@Service)或Java配置类(@Configuration)声明Bean。
  2. Bean的实例化:IoC容器通过反射机制(Class.newInstance()Constructor.newInstance())创建Bean的实例。
  3. 依赖注入:IoC容器根据配置或注解(如@Autowired@Inject)自动注入依赖的Bean。
  4. 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() {
        // 业务逻辑
    }
}
  1. 当调用UserService.saveUser()时:
    • Spring容器返回一个代理对象(JDK/CGLIB代理)。
    • 代理对象拦截方法调用,先执行logBefore通知。
    • 然后调用目标对象的saveUser()方法。
    • 最后根据通知类型(如@After)执行后续逻辑。
posted @ 2025-07-29 20:16  cwp0  阅读(30)  评论(0)    收藏  举报