ITPub博客

首页 > 数据库 > 数据库开发技术 > 深入Spring容器:从Bean工厂到包扫描的全流程剖析

深入Spring容器:从Bean工厂到包扫描的全流程剖析

原创 数据库开发技术 作者:IT枫斗者 时间:2024-12-02 19:22:42 0 删除 编辑


在Spring框架中,Bean的创建和管理是其核心功能之一。为了增强和定制Bean的创建过程,Spring提供了Bean工厂后处理器(BeanFactoryPostProcessor)和Bean后处理器(BeanPostProcessor)。

你提到的这句话涉及到Bean工厂后处理器的注册、实例化和调用,以及它们在包扫描过程中对类文件的处理。

  为了全面理解这句话,我们需要深入探讨以下几个关键概念:




一、Bean工厂后处理器(BeanFactoryPostProcessor)


二、Bean后处理器(BeanPostProcessor)


三、注册与实例化


四、调用处理器


五、包扫描与类文件处理





一、Bean工厂后处理器

(BeanFactoryPostProcessor)

BeanFactoryPostProcessor是Spring提供的一个扩展点,允许开发者在Spring容器初始化Bean定义后、实例化Bean之前对Bean定义进行修改。这在需要动态修改Bean配置或引入额外的配置信息时非常有用。


常见实现类:

PropertyPlaceholderConfigurer

ConfigurationPropertiesBindingPostProcessor

AutowiredAnnotationBeanPostProcessor

作用:

修改Bean定义(如属性值、依赖关系)

增加或移除Bean定义

动态调整Bean的配置信息




二、Bean后处理器

(BeanPostProcessor)

BeanPostProcessor是在Bean实例化之后、初始化之前对Bean进行额外处理的接口。它主要用于在Bean创建过程中添加自定义逻辑,例如代理对象的创建、注解的处理等。


常见实现类:

AutowiredAnnotationBeanPostProcessor

TransactionalAnnotationBeanPostProcessor

自定义的后处理器

作用:

修改Bean实例(如添加代理)

检查和处理自定义注解

执行特定的初始化逻辑




三、注册与实例化

在Spring的启动过程中,Bean工厂后处理器和Bean后处理器需要被注册到Spring容器中,并被实例化以便在适当的时机被调用。


步骤:
注册后处理器:

Spring在加载Bean定义的过程中,会扫描并注册所有实现了BeanFactoryPostProcessor和BeanPostProcessor接口的Bean。

这些后处理器通常通过注解(如@Component)或通过配置文件(如XML配置)进行声明。

实例化后处理器:

一旦后处理器被注册,Spring会创建它们的实例。

这些实例将在Bean定义加载和Bean实例化的不同阶段被调用。



四、调用处理器

Bean工厂后处理器和Bean后处理器在Spring容器的不同阶段被调用,以实现对Bean定义和Bean实例的定制处理。


调用时机:
BeanFactoryPostProcessor的调用时机:

在Spring容器加载所有Bean定义之后,但在实例化任何Bean之前。

主要用于修改Bean定义,比如调整Bean的属性值或改变Bean的依赖关系。

BeanPostProcessor的调用时机:

在Bean实例化之后,初始化之前。

主要用于对Bean实例进行进一步的加工,例如代理对象的创建或自定义初始化逻辑。

执行流程:
BeanFactoryPostProcessor:

Spring容器加载所有Bean定义。

调用所有注册的BeanFactoryPostProcessor的postProcessBeanFactory方法。

这些方法可以修改Bean定义,比如修改属性值或添加新的Bean定义。

BeanPostProcessor:

Spring容器实例化Bean。

在Bean的初始化方法(如@PostConstruct或InitializingBean的afterPropertiesSet)之前,调用所有注册的BeanPostProcessor的postProcessBeforeInitialization方法。

在Bean的初始化方法之后,调用所有注册的BeanPostProcessor的postProcessAfterInitialization方法。

这些方法可以修改Bean实例,比如替换为代理对象或进行额外的初始化。



五、包扫描与类文件处理

包扫描(Package Scanning)是Spring自动发现和注册Bean的机制。Spring通过扫描指定的包路径,查找符合条件的类(如带有@Component、@Service、@Repository等注解的类),并将其注册为Bean。


类文件处理:

在包扫描过程中,Spring会加载类文件并解析其元数据(如注解、接口实现等)。Bean工厂后处理器和Bean后处理器在这个过程中发挥关键作用:

1.BeanFactoryPostProcessor的作用:

在包扫描后,Spring已经加载了所有Bean定义,但尚未实例化任何Bean。

通过BeanFactoryPostProcessor,Spring可以修改这些Bean定义,例如更改属性值、添加依赖关系或动态生成新的Bean定义。

2.BeanPostProcessor的作用:

在包扫描并实例化Bean之后,BeanPostProcessor可以对这些Bean实例进行进一步的处理。

例如,@Autowired注解的处理器会在BeanPostProcessor中注入依赖,或者事务管理器会为标记了@Transactional的Bean创建代理。

具体解释这句话:

“注册并实例化Bean工厂发布处理器,并且调用这些处理器,对包扫描(主要是class)文件进行处理”

1.注册并实例化Bean工厂后处理器:

Spring首先通过包扫描发现所有符合条件的BeanFactoryPostProcessor实现类,并将其注册到容器中。

Spring随后实例化这些后处理器,准备在适当的时机调用它们的方法。

2.调用这些处理器:

在加载完所有Bean定义后,Spring调用已注册的BeanFactoryPostProcessor的postProcessBeanFactory方法。

这些处理器可以修改Bean定义,为后续的Bean实例化和初始化做好准备。

3.对包扫描(主要是class)文件进行处理:

包扫描过程中,Spring加载并解析类文件,识别Bean定义。

BeanFactoryPostProcessor可以在这个阶段对这些Bean定义进行修改,如调整属性值、添加新的依赖关系等。

这些修改确保了在Bean实例化和初始化过程中,Bean的配置符合预期。


例子说明


假设我们有一个简单的Spring Boot应用,并希望在Bean实例化之前修改某个Bean的属性。


创建Bean工厂后处理器:


import org.springframework.beans.factory.config.BeanFactoryPostProcessor;import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;import org.springframework.stereotype.Component;
@Componentpublic class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { // 修改某个Bean的属性值 if (beanFactory.containsBeanDefinition("myBean")) { beanFactory.getBeanDefinition("myBean").getPropertyValues().add("property", "newValue"); } }}


创建一个普通Bean:

import org.springframework.stereotype.Component;
@Componentpublic class MyBean { private String property = "default";
public String getProperty() { return property; }
public void setProperty(String property) { this.property = property; }}


创建控制器查看效果:


import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;
@RestControllerpublic class MyController {
@Autowired private MyBean myBean;
@GetMapping("/property") public String getProperty() { return myBean.getProperty(); }}


运行效果:


默认情况下,MyBean的property属性为"default"。


由于CustomBeanFactoryPostProcessor修改了MyBean的property属性为"newValue",当访问/property端点时,将返回"newValue"。

流程总结

包扫描: 

Spring扫描指定的包,发现CustomBeanFactoryPostProcessor和MyBean。

注册后处理器: 

Spring注册CustomBeanFactoryPostProcessor并实例化它。

调用后处理器: 

Spring调用CustomBeanFactoryPostProcessor.postProcessBeanFactory方法,修改MyBean的属性值。


实例化Bean:

Spring实例化MyBean,其property属性已经被后处理器修改为"newValue"。

使用Bean: 

控制器获取MyBean并返回修改后的property值。







👋 大家好,我是枫哥,一名Java后端开发者!我热衷于探索新技术,并在我的微信公众号上分享关于Java 生态和后端开发的知识。欢迎关注我的公众号,期待与你一起探讨技术的无穷可能!” 目前专注于Java技术分享,覆盖春招、秋招、社招和跳槽相关内容,并提供一对一带徒学习服务。加入 学徒计划,即可享受内推机会和优质资源,签订协议确保就业无忧。此外,我们还推出了‘Java跳槽网’, 为你的求职之路提供全方位支持,助你快速找到理想工作


END



原文作者:IT枫斗者;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论
大家好,我是枫哥,🌟阿里云技术专家、📝资深面试官、🌹Java跳蚤网课堂创始人。技术交流vx:itfdz666,拥有多年一线研发经验,曾就职过科大讯飞、美团网、平安等公司。看面试实战视频可以关注b站号:IT枫斗者–Java面试。需要看技术文章,可以关注CSDN:IT枫斗者。

注册时间:2020-05-13

  • 博文量
    183
  • 访问量
    81363