一、Spring容器架构分层详解
1.1 核心接口继承体系
关键接口说明:
- BeanFactory:基础容器接口,定义
getBean()、containsBean()等核心方法 - ListableBeanFactory:扩展查询能力,支持
getBeanNamesForType() - HierarchicalBeanFactory:支持父子容器层级结构
- ApplicationContext:企业级容器,继承自
ListableBeanFactory和MessageSource
二、BeanFactory实现原理深度剖析
2.1 单例缓存管理机制
通过反射获取DefaultSingletonBeanRegistry的singletonObjects字段:
Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
singletonObjects.setAccessible(true);
ConcurrentHashMap<String, Object> singletonMap = (ConcurrentHashMap) singletonObjects.get(beanFactory);
缓存结构源码分析:
// DefaultSingletonBeanRegistry.java
protected final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isFactoryBean(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
2.2 BeanDefinition加载流程
完整加载时序图:
[BeanFactoryPostProcessor]
→ [BeanDefinitionLoader]
→ [XmlBeanDefinitionReader]
→ [DefaultBeanDefinitionDocumentReader]
→ [BeanDefinitionParserDelegate]
关键处理步骤:
- 资源定位:通过
ResourceLoader加载配置文件 - 文档解析:使用
BeanDefinitionParser解析XML/YAML - 定义注册:将解析结果存入
BeanDefinitionRegistry
三、ApplicationContext高级特性详解
3.1 事件驱动模型全流程
事件传播时序图:
[ApplicationEventPublisher]
→ [ApplicationEventMulticaster]
→ [SimpleApplicationEventMulticaster]
→ [ApplicationListener]
异步事件处理配置:
package com.dwl.application_context_case.config;
import com.dwl.application_context_case.event.MyMonitor;
import com.dwl.application_context_case.processor.MyBeanFactoryPostProcessor;
import com.dwl.application_context_case.service.ProdAuditService;
import com.dwl.log.Logger;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import javax.sql.DataSource;
import java.util.Map;
import java.util.concurrent.Executor;
/**
* @ClassName MyBean
* @Description <h2>应用配置中心</h2>
* <p>
* <b>核心功能:</b>
* <ul>
* <li>数据源配置</li>
* <li>异步线程池管理</li>
* <li>环境感知的Bean注册</li>
* <li>多租户数据源路由</li>
* </ul>
* </p>
*
* <p>
* <b>配置加载顺序:</b>
* <ol>
* <li>通过 {@link #dataSource()} 加载数据源配置</li>
* <li>通过 {@link #asyncExecutor()} 初始化线程池</li>
* <li>根据 Profile 注册条件化 Bean</li>
* <li>通过 {@link #beanFactoryPostProcessor()} 动态注册生产环境 Bean</li>
* </ol>
* </p>
* @Version 1.0.0
* @Date 2025
* @Author By Dwl
*/
@Configuration
@ComponentScan(basePackages = "com.dwl.application_context_case.service")
@EnableAsync
@Data
@NoArgsConstructor // 添加无参构造器供CGLIB代理使用
public class AppConfig {
/**
* Spring环境对象(必须通过构造器注入)
*/
private Environment env;
/**
* <h3>构造器注入 Environment</h3>
* <p>
* 使用构造器注入确保 Spring 在创建代理时能正确完成依赖注入<br>
* 注意:Lombok 的 {@code @NoArgsConstructor} 已移除以避免代理问题
* </p>
*
* @param env Spring 环境对象(通过 {@link org.springframework.context.annotation.Configuration} 自动注入)
*/
@Autowired
public AppConfig(Environment env) {
this.env = env;
Logger.infoF("AppConfig initialized with environment: {}", env.getProperty("spring.profiles.active"));
}
/**
* <h3>数据源配置</h3>
* <p>
* 使用 HikariCP 连接池,参数从环境变量读取<br>
* 示例配置(application-prod.properties):
* <pre>
* spring.datasource.url=jdbc:mysql://prod-db:3306/mdb
* spring.datasource.username=prod_user
* spring.datasource.password=prod_password
* </pre>
* </p>
*/
@Bean
public DataSource dataSource() {
Logger.debug("Initializing DataSource...");
// HikariDataSource dataSource = new HikariDataSource();
// dataSource.setJdbcUrl(env.getProperty("spring.datasource.url"));
// dataSource.setUsername(env.getProperty("spring.datasource.username"));
// dataSource.setPassword(env.getProperty("spring.datasource.password"));
//
// // 连接池配置
// dataSource.setMaximumPoolSize(20);
// dataSource.setMinimumIdle(5);
// dataSource.setIdleTimeout(30000);
Logger.info("DataSource configured successfully");
return null;
}
/**
* <h3>异步线程池配置</h3>
* <p>
* 核心参数:
* <ul>
* <li>corePoolSize: 5(最小工作线程数)</li>
* <li>maxPoolSize: 20(最大并发线程数)</li>
* <li>queueCapacity: 100(任务队列容量)</li>
* </ul>
* </p>
*/
@Bean(name = "asyncExecutor")
public Executor asyncExecutor() {
Logger.debug("Configuring async executor...");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("Async-");
executor.initialize();
Logger.infoF("Async executor [{}] initialized", executor.getThreadNamePrefix());
return executor;
}
/**
* <h3>环境感知的监听器注册</h3>
* <p>
* 仅在开发环境 ({@code dev} Profile) 注册调试监听器<br>
* 使用 {@link Profile} 注解实现条件化 Bean 注册
* </p>
*/
@Bean
@Profile("dev")
public MyMonitor devEventMonitor() {
Logger.info("Registering dev environment monitor");
return new MyMonitor(true); // 启用调试模式
}
/**
* <h3>Bean工厂后处理器</h3>
* <p>
* 动态注册生产环境专用 Bean<br>
* 通过实现 {@link EnvironmentAware} 直接获取环境变量
* </p>
*/
@Bean
public MyBeanFactoryPostProcessor beanFactoryPostProcessor() {
return new MyBeanFactoryPostProcessorImpl();
}
/**
* <h4>Bean工厂后处理器实现</h4>
* <p>
* 通过 {@link EnvironmentAware} 获取环境变量,避免构造器注入问题<br>
* 仅在激活 {@code prod} Profile 时注册审计服务
* </p>
*/
private static class MyBeanFactoryPostProcessorImpl extends MyBeanFactoryPostProcessor implements EnvironmentAware {
private Environment env;
@Override
public void setEnvironment(@NonNull Environment environment) {
this.env = environment;
Logger.debug("Environment set in MyBeanFactoryPostProcessorImpl");
}
@Override
public void postProcessBeanFactory(@NonNull ConfigurableListableBeanFactory factory) {
super.postProcessBeanFactory(factory);
if (env.acceptsProfiles(Profiles.of("prod"))) {
Logger.info("Activating production profile - registering ProdAuditService");
registerProductionBeans(factory);
}
}
private void registerProductionBeans(ConfigurableListableBeanFactory factory) {
GenericBeanDefinition auditDef = new GenericBeanDefinition();
auditDef.setBeanClass(ProdAuditService.class);
((BeanDefinitionRegistry) factory).registerBeanDefinition("auditService", auditDef);
Logger.info("ProdAuditService registered successfully");
}
}
/**
* <h3>多租户数据源配置</h3>
* <p>
* 通过 {@link ConfigurationProperties} 绑定配置前缀<br>
* 示例配置(application.yml):
* <pre>
* spring:
* tenant:
* defaultSchema: public
* schemaMappings:
* tenant1: schema1
* tenant2: schema2
* </pre>
* </p>
*/
@Bean
@ConfigurationProperties(prefix = "spring.tenant")
public TenantConfig tenantConfig() {
return new TenantConfig();
}
@Data
public static class TenantConfig {
/**
* 默认数据库 Schema
*/
private String defaultSchema;
/**
* 租户ID到Schema的映射关系
*/
private Map<String, String> schemaMappings;
}
}
package com.dwl.application_context_case.config;
import com.dwl.application_context_case.event.MyRegisteredEvent;
import com.dwl.log.Logger;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
/**
* 异步事件监听器组件
* <p>
* 该类用于异步处理应用程序中发布的特定事件,通过Spring的事件监听机制与异步执行结合,
* 实现非阻塞的业务逻辑处理。适用于需要解耦且耗时较长的操作场景(如发送通知、日志记录等)。
* </p>
*
* <p>
* 主要功能:
* 1. 监听 {@link MyRegisteredEvent} 用户注册成功事件
* 2. 使用异步线程池处理事件回调
* 3. 实现业务逻辑的解耦和非阻塞执行
* 4. 记录完整的事件处理日志(包括正常流程和异常情况)
* </p>
*
* @author By Dwl
* @version 1.0.0
* @see org.springframework.context.event.EventListener
* @see org.springframework.scheduling.annotation.Async
* @since 2025
*/
@Component
public class AsyncEventListener {
private static final String EVENT_SUCCESS = "Event processed successfully";
private static final String EVENT_FAIL = "Event processing failed";
/**
* 异步处理用户注册成功事件
* <p>
* 当系统中发布{@link MyRegisteredEvent}事件时,此方法会被触发执行。
* 方法使用指定的异步线程池执行,避免阻塞主线程。
* </p>
*
* <p>
* 日志记录策略:
* 1. 方法入口:记录事件接收信息(INFO级别)
* 2. 业务处理:记录关键业务参数(DEBUG级别)
* 3. 成功退出:记录处理结果(INFO级别)
* 4. 异常捕获:记录完整错误堆栈(ERROR级别)
* </p>
*
* @param event 用户注册事件对象,包含注册相关的业务数据
* <ul>
* <li>userId: 新注册用户的唯一标识</li>
* <li>userName: 用户名称</li>
* <li>registerTime: 注册时间戳</li>
* </ul>
* @see MyRegisteredEvent 事件对象定义
* @see org.springframework.scheduling.annotation.Async 异步执行注解
* @see org.springframework.context.event.EventListener 事件监听注解
*/
@Async("asyncExecutor") // 使用名为"eventExecutor"的自定义线程池
@EventListener // 标记为事件监听方法
public void handleAsyncEvent(MyRegisteredEvent event) {
// 记录事件接收日志(包含事件关键信息)
Logger.infoF("Received async event - User Registration: {}", event);
try {
// 业务参数记录(DEBUG级别,生产环境可关闭)
// Logger.debug("Processing event with parameters - userId: {}, userName: {}, registerTime: {}",
// event.getUserId(), event.getUserName(), event.getRegisterTime());
// 1. 获取事件携带的业务数据
// Long userId = event.getUserId();
// String userName = event.getUserName();
// 2. 执行实际业务操作(示例伪代码)
// sendWelcomeEmail(userId, userName);
// logRegistrationEvent(event);
// 模拟业务处理
Thread.sleep(1000); // 模拟耗时操作
// 记录成功日志(带业务标识)
// Logger.infoF("{} - User {} registration processed successfully", EVENT_SUCCESS, userId);
} catch (InterruptedException e) {
// 记录中断异常(保留原始堆栈)
Thread.currentThread().interrupt(); // 重置中断状态
// Logger.errorF("{} failed for event [{}] - Error: {}", EVENT_FAIL, event.getId(), e.getMessage(), e);
} catch (Exception e) {
// 记录业务处理异常(带事件标识)
Logger.errorF("{} failed for event - Error: {}",
EVENT_FAIL, e.getMessage());
// 可根据需要在此处添加:
// 1. 异常分类处理
// 2. 重试机制
// 3. 死信队列投递
}
}
}
3.2 资源加载策略对比
| 加载方式 | 语法示例 | 适用场景 | 特点 |
|---|---|---|---|
| 精确加载 | classpath:app.yml | 明确知道资源位置 | 严格匹配单个文件 |
| 通配符加载 | classpath*:*.xml | 加载所有匹配资源 | 支持Ant风格路径匹配 |
| 文件系统加载 | file:/data/config.xml | 加载绝对路径资源 | 需要文件系统访问权限 |
| 类路径资源加载 | classpath:META-INF/*.xml | 加载类路径下所有匹配资源 | 自动识别打包方式 |
四、容器生命周期完整流程
4.1 启动阶段时序图
SpringApplication.run()
→ refreshContext()
→ AbstractApplicationContext.refresh()
→ AbstractApplicationContext.invokeBeanFactoryPostProcessors()
→ postProcessBeanFactory()
→ MyBeanFactoryPostProcessor.postProcessBeanFactory()
→ 修改Bean定义
→ finishBeanFactoryInitialization()
→ getBean()
→ doGetBean()
→ doGetBeanFromSingletons()
→ getSingleton()
→ createBean()
→ doCreateBean()
→ populateBean()
→ initializeBean()
→ @PostConstruct
→ InitializingBean.afterPropertiesSet()
4.2 Bean生命周期扩展点
package com.dwl.application_context_case.service;
import com.dwl.log.Logger;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.NonNull;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.stereotype.Component;
/**
* 生命周期管理示例Bean
* <p>
* 该类演示Spring容器的完整Bean生命周期管理,包含:
* 1. Bean元数据感知能力(名称/工厂)
* 2. JSR-250标准生命周期方法
* 3. Spring原生生命周期接口
* 4. 初始化/销毁回调组合使用
* </p>
*
* <p>
* 生命周期执行顺序(简化版):
* 1. setBeanName()
* 2. setBeanFactory()
* 3. @PostConstruct
* 4. afterPropertiesSet()
* 5. 自定义init-method
* 6. @PreDestroy
* 7. destroy()
* </p>
*
* <p>
* 日志策略:
* - INFO级别:记录关键生命周期节点
* - DEBUG级别:记录调试信息
* - WARN级别:记录潜在问题
* - ERROR级别:记录初始化失败
* </p>
*
* @author By Dwl
* @version 1.0.0
* @see BeanNameAware
* @see BeanFactoryAware
* @see InitializingBean
* @see DisposableBean
* @since 2025
*/
@Component
public class LifecycleBean implements BeanNameAware, BeanFactoryAware,
InitializingBean, DisposableBean {
private String beanName;
/**
* 设置Bean名称
* <p>
* 生命周期阶段:实例化后立即执行
* 执行顺序:优先于其他初始化方法
* </p>
*
* @param name Spring容器分配的Bean名称
*/
@Override
public void setBeanName(@NonNull String name) {
this.beanName = name;
Logger.infoF("Bean名称已设置 - Name: {}, Class: {}", name, this.getClass().getSimpleName());
}
/**
* 设置BeanFactory引用
* <p>
* 生命周期阶段:实例化后立即执行
* 执行顺序:紧随setBeanName()
* </p>
*
* @param factory 当前Bean所属的BeanFactory实例
* @throws BeansException 如果设置失败
*/
@Override
public void setBeanFactory(BeanFactory factory) {
Logger.debugF("BeanFactory引用已设置 - Factory ID: {}", factory.toString());
}
/**
* JSR-250标准初始化方法
* <p>
* 生命周期阶段:属性设置完成后执行
* 执行顺序:在afterPropertiesSet()之后
* </p>
*
* @throws Exception 初始化失败时抛出异常
* @see PostConstruct
*/
@PostConstruct
public void init() throws Exception {
Logger.info("JSR-250初始化方法执行 - 开始");
// 模拟初始化操作
validateRequiredProperties();
Logger.info("JSR-250初始化方法执行 - 完成");
}
/**
* Spring原生初始化方法
* <p>
* 生命周期阶段:所有属性设置完成后执行
* 执行顺序:在@PostConstruct之后
* </p>
*/
@Override
public void afterPropertiesSet() {
Logger.info("Spring初始化方法执行 - 开始");
// 执行自定义初始化逻辑
initializeResources();
Logger.info("Spring初始化方法执行 - 完成");
}
/**
* JSR-250标准销毁方法
* <p>
* 生命周期阶段:容器销毁前执行
* 执行顺序:在destroy()之前
* </p>
*
* @see PreDestroy
*/
@PreDestroy
public void destroyJsr250() {
Logger.warn("JSR-250销毁方法执行 - 开始");
cleanupResources();
Logger.warn("JSR-250销毁方法执行 - 完成");
}
/**
* Spring原生销毁方法
* <p>
* 生命周期阶段:容器销毁时最后执行
* 执行顺序:在@PreDestroy之后
* </p>
*/
@Override
public void destroy() {
// 实际应选择一种实现方式,此处保留错误提示
Logger.error("检测到重复的destroy方法定义!请保留其中一个实现");
}
// ----------------------
// 内部辅助方法
// ----------------------
private void validateRequiredProperties() {
// 实际应验证必要属性是否已设置
if (beanName == null) {
throw new IllegalStateException("Bean名称未正确设置");
}
}
private void initializeResources() {
// 实际应执行资源初始化操作
Logger.debugF("正在初始化资源 - Bean名称: {}", beanName);
}
private void cleanupResources() {
// 实际应执行资源清理操作
Logger.debugF("正在清理资源 - Bean名称: {}", beanName);
}
}
五、高级调试技巧与最佳实践
5.1 容器状态诊断
package com.dwl.application_context_case;
import com.dwl.application_context_case.event.MyRegisteredEvent;
import com.dwl.application_context_case.service.MyBean;
import com.dwl.log.Logger;
import com.dwl.util.ObjectUtil;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.Resource;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Locale;
import java.util.Map;
/**
* @ClassName BeanFactoryAndApplicationContext
* @Description 深入探究Spring框架中BeanFactory与ApplicationContext的核心差异及协作关系
* 通过实例演示Spring容器核心接口的使用方法,包括Bean生命周期管理、资源加载、事件发布等特性
* @Version 1.0.0
* @Date 2025
* @Author By Dwl
*/
@SpringBootApplication
public class BeanFactoryAndApplicationContext {
/**
* 应用程序入口方法,演示Spring容器核心功能
*
* @param args 启动参数
* @throws NoSuchFieldException 当访问不存在的字段时抛出
* @throws IllegalAccessException 当字段访问权限不足时抛出
* @throws IOException 当资源加载失败时抛出
*/
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException {
// 1. 初始化Spring应用上下文(ConfigurableApplicationContext是ApplicationContext的子接口)
// 提供配置管理能力,支持运行时修改Bean定义和刷新上下文
ConfigurableApplicationContext context = SpringApplication.run(BeanFactoryAndApplicationContext.class, args);
/*
* 2. BeanFactory核心机制演示
* BeanFactory是Spring IoC容器的核心接口,定义了IoC容器的基础功能
*/
// 2.1 获取BeanFactory中注册的Bean(演示BeanFactory的getBean方法)
// myBeanFactoryPostProcessor是一个BeanFactory后置处理器,用于定制Bean定义
context.getBean("myBeanFactoryPostProcessor");
// 记录容器标识信息(演示ApplicationContext的toString实现)
Logger.info(context);
/*
* 3. 深入BeanFactory内部实现(通过反射访问私有字段)
* DefaultSingletonBeanRegistry是DefaultSingletonBeanRegistry的核心实现类
* 该类维护了单例Bean的缓存池singletonObjects
*/
// 通过反射获取DefaultSingletonBeanRegistry的singletonObjects字段
Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
singletonObjects.setAccessible(true); // 突破私有权限限制
// 获取BeanFactory实例(ConfigurableListableBeanFactory是可配置的Bean工厂接口)
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 获取单例Bean缓存对象(实际类型为ConcurrentHashMap)
Object obj = singletonObjects.get(beanFactory);
Map<String, Object> map = ObjectUtil.cast(obj); // 类型转换
// 遍历并记录所有以"myBean"开头的单例Bean
map.forEach((k, v) -> {
if (k.startsWith("myBean")) {
String s = k + "=" + v.toString(); // 构造日志信息
Logger.info(s); // 输出Bean名称及实例信息
}
// 打印所有单例Bean
// Logger.info("Singleton Bean: {} = {}", k, v.getClass().getName()));
});
/*
* 4. ApplicationContext扩展功能演示
* 相比BeanFactory,ApplicationContext提供更丰富的企业级功能:
* - 国际化消息处理(MessageSource)
* - 资源模式解析(ResourcePatternResolver)
* - 事件发布机制(ApplicationEventPublisher)
* - 环境变量访问(EnvironmentCapable)
*/
// 4.1 国际化消息处理(Locale.CHINA指定中文环境)
Logger.infoF(context.getMessage("welcome", null, Locale.CHINA));
// 4.2 资源加载演示
// 4.2.1 加载类路径下的application.yaml(精确匹配单个文件)
Resource[] resourceClasspath = context.getResources("classpath:application.yaml");
for (Resource resource : resourceClasspath) {
Logger.infoF("classpath资源路径: {}", resource.toString()); // 输出资源定位信息
}
// 4.2.2 使用通配符加载所有META-INF/spring.factories(匹配jar包内资源)
Resource[] resourceClasspathArray = context.getResources("classpath*:META-INF/spring.factories");
for (Resource resource : resourceClasspathArray) {
Logger.infoF("classpath*通配符资源: {}", resource.toString()); // 输出匹配的多个资源
}
// 4.2.3 磁盘绝对路径加载(演示文件系统资源访问)
Resource[] resourceFile = context.getResources("file:application.yaml");
for (Resource resource : resourceFile) {
Logger.infoF("磁盘文件资源: {}", resource.toString()); // 输出文件系统资源详情
}
// 4.3 环境变量访问(演示配置属性获取)
Logger.infoF("Java环境路径: {}", context.getEnvironment().getProperty("java_home"));
Logger.infoF("服务器端口: {}", context.getEnvironment().getProperty("server.port"));
/*
* 5. 事件发布与监听机制演示
* 展示ApplicationContext的事件驱动编程模型
*/
// 5.1 发布自定义注册事件
context.publishEvent(new MyRegisteredEvent(context)); // 触发事件传播
// 5.2 调用Bean的自定义注册方法(演示Bean与上下文的交互)
context.getBean(MyBean.class).register();
// 查看Bean定义
String[] beanNames = context.getBeanDefinitionNames();
Arrays.stream(beanNames).forEach(name -> {
try {
// 通过 BeanFactory 获取 BeanDefinition
BeanDefinition beanDefinition = context.getBeanFactory().getBeanDefinition(name);
Logger.debugF("Bean Definition: {}", beanDefinition);
} catch (Exception e) {
Logger.errorF("Failed to get bean definition for: {}", name, e);
}
});
}
}
5.2 动态注册Bean示例
package com.dwl.application_context_case.config;
import com.dwl.application_context_case.service.DynamicService;
import com.dwl.log.Logger;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
/**
* <h2>动态Bean注册配置类</h2>
* <p>
* <b>核心功能:</b>
* <ul>
* <li>通过编程方式动态注册Bean到Spring容器</li>
* <li>实现条件化Bean注册(基于Profile)</li>
* <li>演示BeanDefinitionRegistry的使用</li>
* </ul>
* </p>
*
* <p>
* <b>执行原理:</b>
* <ol>
* <li>应用启动时Spring容器刷新</li>
* <li>触发BeanFactoryPostProcessor执行阶段</li>
* <li>当激活{@code dynamic} Profile时,调用此注册方法</li>
* <li>通过BeanDefinitionRegistry动态注册Bean定义</li>
* <li>后续Bean实例化阶段创建动态Bean实例</li>
* </ol>
* </p>
*
* <p>
* <b>使用场景:</b>
* <ul>
* <li>需要根据运行时条件动态注册Bean</li>
* <li>实现插件化架构</li>
* <li>多租户场景下的差异化Bean注册</li>
* </ul>
* </p>
*
* @author Dwl
* @version 1.1.0
*/
@Configuration
public class DynamicBeanRegistrar {
/**
* 动态注册Bean的核心方法
* <p>
* <b>技术要点:</b>
* <ul>
* <li>使用 {@link BeanDefinitionRegistry} 直接操作Spring容器</li>
* <li>通过 {@link GenericBeanDefinition} 定义Bean元数据</li>
* <li>{@link Profile} 注解实现条件化注册</li>
* </ul>
* </p>
*
* @param registry Spring容器Bean定义注册接口
* <p>
* <b>生命周期:</b>
* <ul>
* <li>在容器刷新阶段被调用</li>
* <li>早于Bean实例化阶段</li>
* </ul>
* </p>
* @throws IllegalStateException 如果尝试在非dynamic Profile下注册
*/
@Profile("prod") // 仅当激活dynamic Profile时生效
public void registerDynamicBean(BeanDefinitionRegistry registry) {
// 1. 创建Bean定义对象
GenericBeanDefinition beanDef = new GenericBeanDefinition();
// 2. 设置Bean实现类
beanDef.setBeanClass(DynamicService.class);
// 3. 配置作用域为原型(每次请求创建新实例)
beanDef.setScope(BeanDefinition.SCOPE_PROTOTYPE);
// 4. 注册Bean定义到容器
String beanName = "dynamicService"; // 注册后的Bean名称
registry.registerBeanDefinition(beanName, beanDef);
// 5. 验证注册结果(调试用)
if (registry.containsBeanDefinition(beanName)) {
Logger.info("[DEBUG] Dynamic bean registered: " + beanName);
}
}
}
5.3 性能优化建议
- 懒加载配置:
@Bean(lazyInit = true)
public HeavyBean heavyBean() {
return new HeavyBean();
}
- 原型作用域管理:
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE,
proxyMode = ScopedProxyMode.TARGET_CLASS)
public PrototypeBean prototypeBean() {
return new PrototypeBean();
}
六、常见疑难问题解析
6.1 循环依赖解决方案
问题现象:
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| serviceA defined in file [...ServiceA.class]
↑ ↓
| serviceB defined in file [...ServiceB.class]
└─────┘
解决方案:
- 使用
@Lazy延迟加载:
@Service
public class ServiceA {
private final ServiceB serviceB;
public ServiceA(@Lazy ServiceB serviceB) {
this.serviceB = serviceB;
}
}
- 构造器注入改属性注入:
@Service
public class ServiceA {
@Autowired
private ServiceB serviceB;
}
七、企业级应用实践
7.1 配置加密解密实现
@Component
public class DecryptingBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) {
String[] beanNames = factory.getBeanDefinitionNames();
for (String beanName : beanNames) {
BeanDefinition beanDef = factory.getBeanDefinition(beanName);
if (beanDef.getPropertyValues().contains("password")) {
PropertyValue value = beanDef.getPropertyValues().getPropertyValue("password");
String encryptedPwd = (String) value.getValue();
String decryptedPwd = AESUtil.decrypt(encryptedPwd);
value.setValue(decryptedPwd);
}
}
}
}
7.2 多环境配置切换
# application-prod.yml
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://prod-db:3306/app
# application-dev.yml
server:
port: 8081
spring:
datasource:
url: jdbc:h2:mem:devdb
启动命令:
java -jar app.jar --spring.profiles.active=prod
八、Spring 6新特性展望
- GraalVM原生镜像支持:
native-image -jar app.jar --no-fallback
- 函数式Bean注册:
@Configuration
public class FunctionalConfig {
@Bean
public Function<String, String> upperCaseConverter() {
return s -> s.toUpperCase();
}
}
- 响应式WebFlux增强:
@Bean
public RouterFunction<ServerResponse> routes() {
return RouterFunctions.route()
.GET("/users", request ->
ServerResponse.ok().body(userService.getUsers(), User.class))
.build();
}
九、全部完整的代码
BeanFactoryAndApplicationContext
package com.dwl.application_context_case;
import com.dwl.application_context_case.event.MyRegisteredEvent;
import com.dwl.application_context_case.service.MyBean;
import com.dwl.log.Logger;
import com.dwl.util.ObjectUtil;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.Resource;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Locale;
import java.util.Map;
/**
* @ClassName BeanFactoryAndApplicationContext
* @Description 深入探究Spring框架中BeanFactory与ApplicationContext的核心差异及协作关系
* 通过实例演示Spring容器核心接口的使用方法,包括Bean生命周期管理、资源加载、事件发布等特性
* @Version 1.0.0
* @Date 2025
* @Author By Dwl
*/
@SpringBootApplication
public class BeanFactoryAndApplicationContext {
/**
* 应用程序入口方法,演示Spring容器核心功能
*
* @param args 启动参数
* @throws NoSuchFieldException 当访问不存在的字段时抛出
* @throws IllegalAccessException 当字段访问权限不足时抛出
* @throws IOException 当资源加载失败时抛出
*/
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException {
// 1. 初始化Spring应用上下文(ConfigurableApplicationContext是ApplicationContext的子接口)
// 提供配置管理能力,支持运行时修改Bean定义和刷新上下文
ConfigurableApplicationContext context = SpringApplication.run(BeanFactoryAndApplicationContext.class, args);
/*
* 2. BeanFactory核心机制演示
* BeanFactory是Spring IoC容器的核心接口,定义了IoC容器的基础功能
*/
// 2.1 获取BeanFactory中注册的Bean(演示BeanFactory的getBean方法)
// myBeanFactoryPostProcessor是一个BeanFactory后置处理器,用于定制Bean定义
context.getBean("myBeanFactoryPostProcessor");
// 记录容器标识信息(演示ApplicationContext的toString实现)
Logger.info(context);
/*
* 3. 深入BeanFactory内部实现(通过反射访问私有字段)
* DefaultSingletonBeanRegistry是DefaultSingletonBeanRegistry的核心实现类
* 该类维护了单例Bean的缓存池singletonObjects
*/
// 通过反射获取DefaultSingletonBeanRegistry的singletonObjects字段
Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
singletonObjects.setAccessible(true); // 突破私有权限限制
// 获取BeanFactory实例(ConfigurableListableBeanFactory是可配置的Bean工厂接口)
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 获取单例Bean缓存对象(实际类型为ConcurrentHashMap)
Object obj = singletonObjects.get(beanFactory);
Map<String, Object> map = ObjectUtil.cast(obj); // 类型转换
// 遍历并记录所有以"myBean"开头的单例Bean
map.forEach((k, v) -> {
if (k.startsWith("myBean")) {
String s = k + "=" + v.toString(); // 构造日志信息
Logger.info(s); // 输出Bean名称及实例信息
}
// 打印所有单例Bean
// Logger.info("Singleton Bean: {} = {}", k, v.getClass().getName()));
});
/*
* 4. ApplicationContext扩展功能演示
* 相比BeanFactory,ApplicationContext提供更丰富的企业级功能:
* - 国际化消息处理(MessageSource)
* - 资源模式解析(ResourcePatternResolver)
* - 事件发布机制(ApplicationEventPublisher)
* - 环境变量访问(EnvironmentCapable)
*/
// 4.1 国际化消息处理(Locale.CHINA指定中文环境)
Logger.infoF(context.getMessage("welcome", null, Locale.CHINA));
// 4.2 资源加载演示
// 4.2.1 加载类路径下的application.yaml(精确匹配单个文件)
Resource[] resourceClasspath = context.getResources("classpath:application.yaml");
for (Resource resource : resourceClasspath) {
Logger.infoF("classpath资源路径: {}", resource.toString()); // 输出资源定位信息
}
// 4.2.2 使用通配符加载所有META-INF/spring.factories(匹配jar包内资源)
Resource[] resourceClasspathArray = context.getResources("classpath*:META-INF/spring.factories");
for (Resource resource : resourceClasspathArray) {
Logger.infoF("classpath*通配符资源: {}", resource.toString()); // 输出匹配的多个资源
}
// 4.2.3 磁盘绝对路径加载(演示文件系统资源访问)
Resource[] resourceFile = context.getResources("file:application.yaml");
for (Resource resource : resourceFile) {
Logger.infoF("磁盘文件资源: {}", resource.toString()); // 输出文件系统资源详情
}
// 4.3 环境变量访问(演示配置属性获取)
Logger.infoF("Java环境路径: {}", context.getEnvironment().getProperty("java_home"));
Logger.infoF("服务器端口: {}", context.getEnvironment().getProperty("server.port"));
/*
* 5. 事件发布与监听机制演示
* 展示ApplicationContext的事件驱动编程模型
*/
// 5.1 发布自定义注册事件
context.publishEvent(new MyRegisteredEvent(context)); // 触发事件传播
// 5.2 调用Bean的自定义注册方法(演示Bean与上下文的交互)
context.getBean(MyBean.class).register();
// 查看Bean定义
String[] beanNames = context.getBeanDefinitionNames();
Arrays.stream(beanNames).forEach(name -> {
try {
// 通过 BeanFactory 获取 BeanDefinition
BeanDefinition beanDefinition = context.getBeanFactory().getBeanDefinition(name);
Logger.debugF("Bean Definition: {}", beanDefinition);
} catch (Exception e) {
Logger.errorF("Failed to get bean definition for: {}", name, e);
}
});
}
}
AppConfig
package com.dwl.application_context_case.config;
import com.dwl.application_context_case.event.MyMonitor;
import com.dwl.application_context_case.processor.MyBeanFactoryPostProcessor;
import com.dwl.application_context_case.service.ProdAuditService;
import com.dwl.log.Logger;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import javax.sql.DataSource;
import java.util.Map;
import java.util.concurrent.Executor;
/**
* @ClassName MyBean
* @Description <h2>应用配置中心</h2>
* <p>
* <b>核心功能:</b>
* <ul>
* <li>数据源配置</li>
* <li>异步线程池管理</li>
* <li>环境感知的Bean注册</li>
* <li>多租户数据源路由</li>
* </ul>
* </p>
*
* <p>
* <b>配置加载顺序:</b>
* <ol>
* <li>通过 {@link #dataSource()} 加载数据源配置</li>
* <li>通过 {@link #asyncExecutor()} 初始化线程池</li>
* <li>根据 Profile 注册条件化 Bean</li>
* <li>通过 {@link #beanFactoryPostProcessor()} 动态注册生产环境 Bean</li>
* </ol>
* </p>
* @Version 1.0.0
* @Date 2025
* @Author By Dwl
*/
@Configuration
@ComponentScan(basePackages = "com.dwl.application_context_case.service")
@EnableAsync
@Data
@NoArgsConstructor // 添加无参构造器供CGLIB代理使用
public class AppConfig {
/**
* Spring环境对象(必须通过构造器注入)
*/
private Environment env;
/**
* <h3>构造器注入 Environment</h3>
* <p>
* 使用构造器注入确保 Spring 在创建代理时能正确完成依赖注入<br>
* 注意:Lombok 的 {@code @NoArgsConstructor} 已移除以避免代理问题
* </p>
*
* @param env Spring 环境对象(通过 {@link org.springframework.context.annotation.Configuration} 自动注入)
*/
@Autowired
public AppConfig(Environment env) {
this.env = env;
Logger.infoF("AppConfig initialized with environment: {}", env.getProperty("spring.profiles.active"));
}
/**
* <h3>数据源配置</h3>
* <p>
* 使用 HikariCP 连接池,参数从环境变量读取<br>
* 示例配置(application-prod.properties):
* <pre>
* spring.datasource.url=jdbc:mysql://prod-db:3306/mdb
* spring.datasource.username=prod_user
* spring.datasource.password=prod_password
* </pre>
* </p>
*/
@Bean
public DataSource dataSource() {
Logger.debug("Initializing DataSource...");
// HikariDataSource dataSource = new HikariDataSource();
// dataSource.setJdbcUrl(env.getProperty("spring.datasource.url"));
// dataSource.setUsername(env.getProperty("spring.datasource.username"));
// dataSource.setPassword(env.getProperty("spring.datasource.password"));
//
// // 连接池配置
// dataSource.setMaximumPoolSize(20);
// dataSource.setMinimumIdle(5);
// dataSource.setIdleTimeout(30000);
Logger.info("DataSource configured successfully");
return null;
}
/**
* <h3>异步线程池配置</h3>
* <p>
* 核心参数:
* <ul>
* <li>corePoolSize: 5(最小工作线程数)</li>
* <li>maxPoolSize: 20(最大并发线程数)</li>
* <li>queueCapacity: 100(任务队列容量)</li>
* </ul>
* </p>
*/
@Bean(name = "asyncExecutor")
public Executor asyncExecutor() {
Logger.debug("Configuring async executor...");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("Async-");
executor.initialize();
Logger.infoF("Async executor [{}] initialized", executor.getThreadNamePrefix());
return executor;
}
/**
* <h3>环境感知的监听器注册</h3>
* <p>
* 仅在开发环境 ({@code dev} Profile) 注册调试监听器<br>
* 使用 {@link Profile} 注解实现条件化 Bean 注册
* </p>
*/
@Bean
@Profile("dev")
public MyMonitor devEventMonitor() {
Logger.info("Registering dev environment monitor");
return new MyMonitor(true); // 启用调试模式
}
/**
* <h3>Bean工厂后处理器</h3>
* <p>
* 动态注册生产环境专用 Bean<br>
* 通过实现 {@link EnvironmentAware} 直接获取环境变量
* </p>
*/
@Bean
public MyBeanFactoryPostProcessor beanFactoryPostProcessor() {
return new MyBeanFactoryPostProcessorImpl();
}
/**
* <h4>Bean工厂后处理器实现</h4>
* <p>
* 通过 {@link EnvironmentAware} 获取环境变量,避免构造器注入问题<br>
* 仅在激活 {@code prod} Profile 时注册审计服务
* </p>
*/
private static class MyBeanFactoryPostProcessorImpl extends MyBeanFactoryPostProcessor implements EnvironmentAware {
private Environment env;
@Override
public void setEnvironment(@NonNull Environment environment) {
this.env = environment;
Logger.debug("Environment set in MyBeanFactoryPostProcessorImpl");
}
@Override
public void postProcessBeanFactory(@NonNull ConfigurableListableBeanFactory factory) {
super.postProcessBeanFactory(factory);
if (env.acceptsProfiles(Profiles.of("prod"))) {
Logger.info("Activating production profile - registering ProdAuditService");
registerProductionBeans(factory);
}
}
private void registerProductionBeans(ConfigurableListableBeanFactory factory) {
GenericBeanDefinition auditDef = new GenericBeanDefinition();
auditDef.setBeanClass(ProdAuditService.class);
((BeanDefinitionRegistry) factory).registerBeanDefinition("auditService", auditDef);
Logger.info("ProdAuditService registered successfully");
}
}
/**
* <h3>多租户数据源配置</h3>
* <p>
* 通过 {@link ConfigurationProperties} 绑定配置前缀<br>
* 示例配置(application.yml):
* <pre>
* spring:
* tenant:
* defaultSchema: public
* schemaMappings:
* tenant1: schema1
* tenant2: schema2
* </pre>
* </p>
*/
@Bean
@ConfigurationProperties(prefix = "spring.tenant")
public TenantConfig tenantConfig() {
return new TenantConfig();
}
@Data
public static class TenantConfig {
/**
* 默认数据库 Schema
*/
private String defaultSchema;
/**
* 租户ID到Schema的映射关系
*/
private Map<String, String> schemaMappings;
}
}
AsyncEventListener
package com.dwl.application_context_case.config;
import com.dwl.application_context_case.event.MyRegisteredEvent;
import com.dwl.log.Logger;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
/**
* 异步事件监听器组件
* <p>
* 该类用于异步处理应用程序中发布的特定事件,通过Spring的事件监听机制与异步执行结合,
* 实现非阻塞的业务逻辑处理。适用于需要解耦且耗时较长的操作场景(如发送通知、日志记录等)。
* </p>
*
* <p>
* 主要功能:
* 1. 监听 {@link MyRegisteredEvent} 用户注册成功事件
* 2. 使用异步线程池处理事件回调
* 3. 实现业务逻辑的解耦和非阻塞执行
* 4. 记录完整的事件处理日志(包括正常流程和异常情况)
* </p>
*
* @author By Dwl
* @version 1.0.0
* @see org.springframework.context.event.EventListener
* @see org.springframework.scheduling.annotation.Async
* @since 2025
*/
@Component
public class AsyncEventListener {
private static final String EVENT_SUCCESS = "Event processed successfully";
private static final String EVENT_FAIL = "Event processing failed";
/**
* 异步处理用户注册成功事件
* <p>
* 当系统中发布{@link MyRegisteredEvent}事件时,此方法会被触发执行。
* 方法使用指定的异步线程池执行,避免阻塞主线程。
* </p>
*
* <p>
* 日志记录策略:
* 1. 方法入口:记录事件接收信息(INFO级别)
* 2. 业务处理:记录关键业务参数(DEBUG级别)
* 3. 成功退出:记录处理结果(INFO级别)
* 4. 异常捕获:记录完整错误堆栈(ERROR级别)
* </p>
*
* @param event 用户注册事件对象,包含注册相关的业务数据
* <ul>
* <li>userId: 新注册用户的唯一标识</li>
* <li>userName: 用户名称</li>
* <li>registerTime: 注册时间戳</li>
* </ul>
* @see MyRegisteredEvent 事件对象定义
* @see org.springframework.scheduling.annotation.Async 异步执行注解
* @see org.springframework.context.event.EventListener 事件监听注解
*/
@Async("asyncExecutor") // 使用名为"eventExecutor"的自定义线程池
@EventListener // 标记为事件监听方法
public void handleAsyncEvent(MyRegisteredEvent event) {
// 记录事件接收日志(包含事件关键信息)
Logger.infoF("Received async event - User Registration: {}", event);
try {
// 业务参数记录(DEBUG级别,生产环境可关闭)
// Logger.debug("Processing event with parameters - userId: {}, userName: {}, registerTime: {}",
// event.getUserId(), event.getUserName(), event.getRegisterTime());
// 1. 获取事件携带的业务数据
// Long userId = event.getUserId();
// String userName = event.getUserName();
// 2. 执行实际业务操作(示例伪代码)
// sendWelcomeEmail(userId, userName);
// logRegistrationEvent(event);
// 模拟业务处理
Thread.sleep(1000); // 模拟耗时操作
// 记录成功日志(带业务标识)
// Logger.infoF("{} - User {} registration processed successfully", EVENT_SUCCESS, userId);
} catch (InterruptedException e) {
// 记录中断异常(保留原始堆栈)
Thread.currentThread().interrupt(); // 重置中断状态
// Logger.errorF("{} failed for event [{}] - Error: {}", EVENT_FAIL, event.getId(), e.getMessage(), e);
} catch (Exception e) {
// 记录业务处理异常(带事件标识)
Logger.errorF("{} failed for event - Error: {}",
EVENT_FAIL, e.getMessage());
// 可根据需要在此处添加:
// 1. 异常分类处理
// 2. 重试机制
// 3. 死信队列投递
}
}
}
DynamicBeanRegistrar
package com.dwl.application_context_case.config;
import com.dwl.application_context_case.service.DynamicService;
import com.dwl.log.Logger;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
/**
* <h2>动态Bean注册配置类</h2>
* <p>
* <b>核心功能:</b>
* <ul>
* <li>通过编程方式动态注册Bean到Spring容器</li>
* <li>实现条件化Bean注册(基于Profile)</li>
* <li>演示BeanDefinitionRegistry的使用</li>
* </ul>
* </p>
*
* <p>
* <b>执行原理:</b>
* <ol>
* <li>应用启动时Spring容器刷新</li>
* <li>触发BeanFactoryPostProcessor执行阶段</li>
* <li>当激活{@code dynamic} Profile时,调用此注册方法</li>
* <li>通过BeanDefinitionRegistry动态注册Bean定义</li>
* <li>后续Bean实例化阶段创建动态Bean实例</li>
* </ol>
* </p>
*
* <p>
* <b>使用场景:</b>
* <ul>
* <li>需要根据运行时条件动态注册Bean</li>
* <li>实现插件化架构</li>
* <li>多租户场景下的差异化Bean注册</li>
* </ul>
* </p>
*
* @author Dwl
* @version 1.1.0
*/
@Configuration
public class DynamicBeanRegistrar {
/**
* 动态注册Bean的核心方法
* <p>
* <b>技术要点:</b>
* <ul>
* <li>使用 {@link BeanDefinitionRegistry} 直接操作Spring容器</li>
* <li>通过 {@link GenericBeanDefinition} 定义Bean元数据</li>
* <li>{@link Profile} 注解实现条件化注册</li>
* </ul>
* </p>
*
* @param registry Spring容器Bean定义注册接口
* <p>
* <b>生命周期:</b>
* <ul>
* <li>在容器刷新阶段被调用</li>
* <li>早于Bean实例化阶段</li>
* </ul>
* </p>
* @throws IllegalStateException 如果尝试在非dynamic Profile下注册
*/
@Profile("prod") // 仅当激活dynamic Profile时生效
public void registerDynamicBean(BeanDefinitionRegistry registry) {
// 1. 创建Bean定义对象
GenericBeanDefinition beanDef = new GenericBeanDefinition();
// 2. 设置Bean实现类
beanDef.setBeanClass(DynamicService.class);
// 3. 配置作用域为原型(每次请求创建新实例)
beanDef.setScope(BeanDefinition.SCOPE_PROTOTYPE);
// 4. 注册Bean定义到容器
String beanName = "dynamicService"; // 注册后的Bean名称
registry.registerBeanDefinition(beanName, beanDef);
// 5. 验证注册结果(调试用)
if (registry.containsBeanDefinition(beanName)) {
Logger.info("[DEBUG] Dynamic bean registered: " + beanName);
}
}
}
MyMonitor
package com.dwl.application_context_case.event;
import com.dwl.application_context_case.service.MyBean;
import com.dwl.log.Logger;
import lombok.Data;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.context.ApplicationEvent;
/**
* <h2>事件监听器组件</h2>
* <p>
* <b>功能定位:</b>实现 Spring 事件驱动模型的监听器组件,用于响应自定义事件
* <br>
* <b>设计模式:</b>观察者模式(发布-订阅模式)
* <br>
* <b>应用场景:</b>
* <ul>
* <li>系统监控指标采集</li>
* <li>业务流程状态跟踪</li>
* <li>跨组件异步通知</li>
* <li>审计日志记录</li>
* </ul>
* </p>
*
* <p>
* <b>与 ApplicationListener 的对比:</b>
* <table border="1">
* <tr><th></th><th>@EventListener</th><th>ApplicationListener</th></tr>
* <tr><td>实现方式</td><td>基于注解的声明式监听</td><td>接口实现式监听</td></tr>
* <tr><td>事件过滤</td><td>支持 SpEL 表达式过滤</td><td>需手动实现过滤逻辑</td></tr>
* <tr><td>方法签名</td><td>灵活(支持任意参数)</td><td>固定 EventListener 接口</td></tr>
* <tr><td>异步支持</td><td>需配合 @Async</td><td>需配置 TaskExecutor</td></tr>
* </table>
* </p>
*
* @Version 1.0.0
* @Date 2025
* @Author By Dwl
*/
@Component
@Data
public class MyMonitor {
private boolean debugMode;
public MyMonitor(boolean debugMode) {
this.debugMode = debugMode;
}
public MyMonitor() {
}
/**
* <h3>事件处理方法</h3>
* <p>
* <b>触发条件:</b>当容器中发布 MyRegisteredEvent 事件时自动触发
* <br>
* <b>执行线程:</b>默认与事件发布线程同步执行(可通过 @Async 异步化)
* <br>
* <b>事件生命周期:</b>
* <ol>
* <li>事件发布(context.publishEvent())</li>
* <li>事件多播(通过 ApplicationEventMulticaster)</li>
* <li>事件监听器执行</li>
* </ol>
* </p>
*
* <p>
* <b>参数解析:</b>
* <ul>
* <li>{@code event} - 事件对象,包含以下关键信息:
* <ul>
* <li>事件源对象(通过 getSource() 获取)</li>
* <li>时间戳(通过 getTimestamp() 获取)</li>
* <li>自定义业务数据(需在事件类中定义)</li>
* </ul>
* </li>
* </ul>
* </p>
*
* <p>
* <b>扩展能力:</b>
* <ul>
* <li>支持事件过滤(通过 condition 属性)</li>
* <li>支持异步处理(通过 @Async 注解)</li>
* <li>支持事件响应链(多个监听器顺序执行)</li>
* </ul>
* </p>
*
* @param event 事件对象(必须非空)
* @see MyRegisteredEvent 事件定义类
* @see ApplicationEvent 发布事件的基类
*/
@EventListener
public void monitor(MyRegisteredEvent event) {
if (debugMode) {
Logger.debug("调试模式启用");
}
// 1. 记录事件基本信息
Logger.infoF("【事件监听】收到事件 - 类型={} | 来源={}",
event.getClass().getSimpleName(), event.getSource());
// 2. 提取事件携带的业务数据(示例)
// Object data = event.getData();
// 3. 异常处理(建议捕获特定异常)
try {
// 业务处理逻辑
processEventData(event);
} catch (Exception e) {
Logger.error("事件处理异常", e);
}
}
/**
* <h4>事件数据处理方法</h4>
* <p>
* <b>设计要点:</b>
* <ul>
* <li>解耦事件处理逻辑</li>
* <li>支持业务数据校验</li>
* <li>可扩展为责任链模式</li>
* </ul>
* </p>
*
* @param event 事件对象
*/
private void processEventData(MyRegisteredEvent event) {
// 示例:提取事件源对象
Object source = event.getSource();
if (source instanceof MyBean) {
Logger.debugF("处理来自 MyBean 的事件");
}
}
}
MyRegisteredEvent
package com.dwl.application_context_case.event;
import com.dwl.application_context_case.service.MyBean;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
/**
* <h2>自定义应用事件类</h2>
* <p>
* <b>功能定位:</b>实现 Spring 事件驱动模型的核心事件载体,用于封装组件注册状态变更通知
* <br>
* <b>设计模式:</b>观察者模式(发布-订阅模式)
* <br>
* <b>继承体系:</b>
* <ul>
* <li>{@link ApplicationEvent} - Spring 事件基类</li>
* <li>{@code MyRegisteredEvent} - 业务层自定义事件</li>
* </ul>
* </p>
*
* <p>
* <b>典型应用场景:</b>
* <ul>
* <li>组件注册状态变更通知</li>
* <li>跨模块业务状态同步</li>
* <li>异步审计日志记录</li>
* <li>微服务间事件总线通信</li>
* </ul>
* </p>
*
* <p>
* <b>事件传播机制:</b>
* <ol>
* <li>同步传播:默认通过当前线程传递(通过 {@link ApplicationEventPublisher#publishEvent})</li>
* <li>异步传播:需配合 {@link org.springframework.scheduling.annotation.Async} 注解</li>
* </ol>
* </p>
*
* @Version 1.0.0
* @Date 2025
* @Author By Dwl
*/
public class MyRegisteredEvent extends ApplicationEvent {
/**
* <h3>事件构造方法</h3>
* <p>
* <b>核心功能:</b>创建包含事件源信息的事件对象
* <br>
* <b>设计要点:</b>
* <ul>
* <li>事件源对象必须实现 {@link java.io.Serializable} 接口(序列化要求)</li>
* <li>建议事件源对象包含唯一标识符(用于事件追踪)</li>
* <li>构造方法参数需满足线程安全要求</li>
* </ul>
* </p>
*
* @param source 事件源对象(通常为事件发布者)
* <ul>
* <li>类型约束:建议使用具体业务对象(如 MyBean 实例)</li>
* <li>null 值限制:Spring 框架禁止 source=null 的情况</li>
* </ul>
*
* @throws IllegalArgumentException 当 source 参数不符合要求时抛出
* @see MyBean#register() 事件发布示例
*/
public MyRegisteredEvent(Object source) {
super(source);
// 防御性编程:验证事件源有效性
if (source == null) {
throw new IllegalArgumentException("Event source cannot be null");
}
}
/**
* <h4>获取事件源对象</h4>
* <p>
* <b>访问方法:</b>通过 {@link #getSource()} 方法获取
* <br>
* <b>数据契约:</b>
* <ul>
* <li>返回值类型:Object(建议强制转换为具体业务类型)</li>
* <li>空值保证:Spring 框架保证非空</li>
* </ul>
* </p>
*
* @return 事件源对象(通常是事件发布者实例)
* @see MyBean#register() 典型事件源对象类型
*/
@Override
public Object getSource() {
return super.getSource();
}
/**
* <h4>事件唯一标识生成</h4>
* <p>
* <b>设计目标:</b>提供事件追踪能力
* <br>
* <b>实现方式:</b>组合事件类名和时间戳生成唯一标识
* </p>
*
* @return 格式:{@code MyRegisteredEvent@timestamp}
* @example "MyRegisteredEvent@1625097600000"
*/
public String getEventId() {
return this.getClass().getSimpleName() + "@" + super.getTimestamp();
}
/**
* <h4>事件数据校验方法</h4>
* <p>
* <b>校验策略:</b>确保事件数据的完整性
* <br>
* <b>扩展建议:</b>可添加业务字段校验逻辑
* </p>
*
* @throws IllegalStateException 当检测到无效事件数据时抛出
*/
public void validate() {
if (getSource() == null) {
throw new IllegalStateException("Invalid event state: source is null");
}
}
}
MyBeanFactoryPostProcessor
package com.dwl.application_context_case.processor;
import com.dwl.log.Logger;
import lombok.NonNull;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.stereotype.Component;
/**
* <h2>BeanFactory 后置处理器</h2>
* <p>
* <b>功能定位:</b>实现 Spring 容器的核心扩展点,允许在 Bean 实例化前修改 Bean 定义
* <br>
* <b>执行时机:</b>在以下阶段执行:
* <ol>
* <li>容器初始化完成(BeanFactory 标准初始化)</li>
* <li>所有 BeanDefinition 加载完成后</li>
* <li>在 Bean 实例化、属性填充、初始化方法执行之前</li>
* </ol>
* </p>
*
* <p>
* <b>核心能力:</b>
* <ul>
* <li>动态修改 Bean 定义属性(scope/lazy-init/data-type 等)</li>
* <li>注册新的 BeanDefinition(支持动态扩展 Bean)</li>
* <li>执行占位符替换(如数据库密码解密)</li>
* <li>覆盖已存在的 Bean 定义(需注意优先级问题)</li>
* </ul>
* </p>
*
* <p>
* <b>与 BeanPostProcessor 的区别:</b>
* <table border="1">
* <tr><th></th><th>BeanFactoryPostProcessor</th><th>BeanPostProcessor</th></tr>
* <tr><td>作用阶段</td><td>Bean 实例化前</td><td>Bean 实例化后</td></tr>
* <tr><td>操作对象</td><td>BeanDefinition</td><td>Bean 实例</td></tr>
* <tr><td>执行顺序</td><td>优先执行</td><td>后续执行</td></tr>
* </table>
* </p>
*
* <p>
* <b>典型应用场景:</b>
* <ul>
* <li>加密配置解密(如数据库密码动态解密)</li>
* <li>多环境配置切换(根据 Profile 修改 Bean 定义)</li>
* <li>自动装配第三方库的 Bean(无源码类库的 Bean 注册)</li>
* <li>动态补全默认配置(自动设置缺省属性值)</li>
* </ul>
* </p>
*
* @Version 1.0.0
* @Date 2025
* @Author By Dwl
*/
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
/**
* <h3>BeanFactory 后置处理方法</h3>
* <p>
* <b>参数解析:</b>
* <ul>
* <li>{@code factory} - 可配置的 BeanFactory 实例,提供以下关键能力:
* <ul>
* <li>{@link ConfigurableListableBeanFactory#getBeanDefinition(String)} - 获取 Bean 定义</li>
* <li>{@link BeanDefinitionRegistry#registerBeanDefinition(String, BeanDefinition)} - 注册新定义</li>
* <li>{@link BeanDefinitionRegistry#removeBeanDefinition(String)} - 移除定义</li>
* <li>{@link ConfigurableListableBeanFactory#resolveEmbeddedValue(String)} - 占位符解析</li>
* </ul>
* </li>
* </ul>
* </p>
*
* <p>
* <b>执行流程示例:</b>
* <pre>
* 1. 获取所有 BeanDefinition 名称
* String[] beanNames = factory.getBeanDefinitionNames();
*
* 2. 遍历处理特定 Bean
* for (String name : beanNames) {
* if (name.startsWith("thirdParty")) {
* BeanDefinition def = factory.getBeanDefinition(name);
* def.setScope(BeanDefinition.SCOPE_PROTOTYPE);
* def.setLazyInit(true);
* }
* }
*
* 3. 动态注册新 Bean
* GenericBeanDefinition newDef = new GenericBeanDefinition();
* newDef.setBeanClassName("com.example.DynamicBean");
* ((BeanDefinitionRegistry) factory).registerBeanDefinition("dynamicBean", newDef);
* </pre>
* </p>
*
* <p>
* <b>注意事项:</b>
* <ul>
* <li>执行时机仅一次(容器刷新时触发)</li>
* <li>不能修改已实例化的 Bean</li>
* <li>需避免循环依赖问题</li>
* <li>修改操作需线程安全</li>
* </ul>
* </p>
*
* @param factory 可配置的 BeanFactory 实例(必须非空)
*/
@Override
public void postProcessBeanFactory(@NonNull ConfigurableListableBeanFactory factory) {
// 1. 记录处理器启动(可用于调试时确认执行顺序)
Logger.info("【BeanFactory 后置处理器】开始执行");
// 2. 获取所有已注册的 BeanDefinition 名称
String[] beanNames = factory.getBeanDefinitionNames();
Logger.debugF("发现 {} 个 BeanDefinition", beanNames.length);
// 3. 遍历处理 Bean 定义(示例:修改特定前缀的 Bean)
for (String beanName : beanNames) {
// 3.1 获取 Bean 定义对象
BeanDefinition beanDefinition = factory.getBeanDefinition(beanName);
// 3.2 示例:为所有 Service 层 Bean 添加缓存代理
if (beanName.endsWith("Service")) {
// 3.2.1 修改作用域为原型(如果需要)
if (BeanDefinition.SCOPE_SINGLETON.equals(beanDefinition.getScope())) {
beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
Logger.infoF("修改 Bean 【%s】 作用域为 PROTOTYPE", beanName);
}
// 3.2.2 添加自定义属性(需配合 @Value 使用)
// MutablePropertyValues values = beanDefinition.getPropertyValues();
// values.add("cacheEnabled", true);
}
// 3.3 示例:解析加密的数据库密码(需实现具体解密逻辑)
// String encryptedPwd = beanDefinition.getPropertyValues().getProperty("password");
// String decryptedPwd = decrypt(encryptedPwd);
// beanDefinition.getPropertyValues().add("password", decryptedPwd);
}
// 4. 动态注册新 Bean(示例:注册监控切面)
// GenericBeanDefinition aspectDef = new GenericBeanDefinition();
// aspectDef.setBeanClass(MonitorAspect.class);
// ((BeanDefinitionRegistry) factory).registerBeanDefinition("monitorAspect", aspectDef);
// 5. 执行完成记录
Logger.info("【BeanFactory 后置处理器】执行完成");
}
}
MyBeanPostProcessor
package com.dwl.application_context_case.processor;
import com.dwl.log.Logger;
import lombok.NonNull;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
/**
* @ClassName MyBeanPostProcessor
* @Description <p>
* Spring 容器核心扩展点:BeanFactory 后置处理器
* <br>
* 实现 BeanFactory 初始化完成后、Bean 实例化前的 BeanDefinition 修改能力
* </p>
*
* <p>
* 典型应用场景:
* <ul>
* <li>动态修改 Bean 定义属性(如数据源密码解密)</li>
* <li>占位符替换(PropertyPlaceholderConfigurer)</li>
* <li>Bean 定义重写(覆盖默认配置)</li>
* <li>注册自定义 BeanDefinition(动态注册 Bean)</li>
* </ul>
* </p>
*
* <p>
* 执行时机:
* <ol>
* <li>在 BeanFactory 标准初始化完成后</li>
* <li>在所有 Bean 实例化之前</li>
* <li>优先于 BeanPostProcessor 执行</li>
* </ol>
* </p>
* @Version 1.0.0
* @Date 2025
* @Author By Dwl
*/
@Component
public class MyBeanPostProcessor implements BeanFactoryPostProcessor {
/**
* BeanFactory 初始化后置处理方法
* <p>
* 核心能力:
* 1. 获取所有 BeanDefinition 进行修改
* 2. 动态注册新的 BeanDefinition
* 3. 修改 Bean 定义的元数据信息
* </p>
*
* <p>
* 参数说明:
* <ul>
* <li>{@code factory} - 可配置的 BeanFactory 实例
* <ul>
* <li>提供访问 BeanDefinition 的 API</li>
* <li>支持修改 Bean 定义属性</li>
* <li>可以注册新的 BeanDefinition</li>
* </ul>
* </li>
* </ul>
* </p>
*
* <p>
* 扩展说明:
* <ul>
* <li>该方法在整个容器生命周期中只执行一次</li>
* <li>典型的实现类:PropertyPlaceholderConfigurer</li>
* <li>与 BeanPostProcessor 的区别:
* <ul>
* <li>作用阶段:BeanFactoryPostProcessor 在 Bean 实例化前执行</li>
* <li>作用对象:操作 BeanDefinition 而非 Bean 实例</li>
* </ul>
* </li>
* </ul>
* </p>
*/
@Override
public void postProcessBeanFactory(@NonNull ConfigurableListableBeanFactory factory) {
Logger.info("【BeanFactory 后置处理器】开始修改 Bean 定义");
// 1. 获取所有 BeanDefinition 的名称
String[] beanNames = factory.getBeanDefinitionNames();
// 2. 遍历所有 BeanDefinition(示例仅处理特定 Bean)
for (String beanName : beanNames) {
BeanDefinition beanDefinition = factory.getBeanDefinition(beanName);
// 3. 修改特定 Bean 的属性(示例:设置懒加载)
if (beanName.startsWith("myBean")) {
// 修改作用域为原型(prototype)
beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
// 设置懒加载(需配合 @Lazy 注解使用)
// beanDefinition.setLazyInit(true);
// 示例:修改构造函数参数
// ConstructorArgumentValues args = new ConstructorArgumentValues();
// args.addGenericArgumentValue("customValue");
// beanDefinition.setConstructorArgumentValues(args);
Logger.infoF("已修改 BeanDefinition 【{}】:作用域={}",
beanName, beanDefinition.getScope());
}
}
// 4. 动态注册新的 BeanDefinition(示例)
// GenericBeanDefinition newBeanDef = new GenericBeanDefinition();
// newBeanDef.setBeanClass(SomeClass.class);
// ((BeanDefinitionRegistry) factory).registerBeanDefinition("newBean", newBeanDef);
Logger.info("【BeanFactory 后置处理器】Bean 定义修改完成");
}
}
DynamicService
package com.dwl.application_context_case.service;
import com.dwl.application_context_case.config.DynamicBeanRegistrar;
import com.dwl.log.Logger;
/**
* @ClassName DynamicService
* @Description <h2>动态服务示例</h2>
* <p>
* <b>核心功能:</b>
* <ul>
* <li>演示通过编程方式动态注册Bean</li>
* <li>验证BeanFactoryPostProcessor的使用</li>
* <li>展示原型作用域(Prototype Scope)行为</li>
* </ul>
* </p>
*
* <p>
* <b>关键约束:</b>
* <ul>
* <li>必须移除 {@code @Service} 注解(否则会与动态注册冲突)</li>
* <li>只能通过 {@link DynamicBeanRegistrar} 注册到容器</li>
* <li>需激活 {@code dynamic} Profile 才能生效</li>
* </ul>
* </p>
*
* <p>
* <b>使用示例:</b>
* <pre>
* {@code
* // 在需要使用的位置注入(需确保Profile激活)
* @Autowired(required = false)
* private DynamicService dynamicService;
*
* if (dynamicService != null) {
* dynamicService.performDynamicAction();
* }
* }
* </pre>
* </p>
* @Version 1.0.0
* @Date 2025
* @Author By Dwl
*/
public class DynamicService {
/**
* 执行动态操作
* <p>
* <b>行为特征:</b>
* <ul>
* <li>每次调用都会记录独立日志(因原型作用域每次创建新实例)</li>
* <li>无状态服务(不依赖成员变量)</li>
* </ul>
*/
public void performDynamicAction() {
Logger.info("[DynamicService] 执行动态操作 - 实例ID: " + this.hashCode());
}
/**
* 验证动态注册是否成功的辅助方法
* <p>
* <b>使用场景:</b>
* <ul>
* <li>单元测试中验证Bean注册</li>
* <li>调试时检查动态Bean是否存在</li>
* </ul>
*/
public static boolean isRegistered() {
// 实际实现需通过ApplicationContext获取Bean定义
// 此处仅为示例,需配合测试框架使用
return false;
}
}
DynamicServiceConsumer
package com.dwl.application_context_case.service;
import com.dwl.log.Logger;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
/**
* @ClassName DynamicServiceConsumer
* @Description <h2>动态服务消费者示例</h2>
* <p>
* <b>核心功能:</b>
* <ul>
* <li>演示如何安全注入动态注册的Bean</li>
* <li>处理原型作用域Bean的延迟获取</li>
* <li>验证动态注册与依赖注入的协同工作</li>
* </ul>
* </p>
*
* <p>
* <b>关键约束:</b>
* <ul>
* <li>必须通过 {@link ObjectFactory} 延迟获取动态Bean</li>
* <li>需激活 {@code dynamic} Profile 才能生效</li>
* <li>禁止直接通过构造器注入动态Bean(因原型作用域特性)</li>
* </ul>
* </p>
* @Version 1.0.0
* @Date 2025
* @Author By Dwl
*/
@Component
public class DynamicServiceConsumer {
private final ObjectFactory<DynamicService> dynamicServiceFactory;
/**
* <h3>安全注入动态Bean</h3>
* <p>
* 使用 Spring 的 {@link ObjectFactory} 实现延迟获取:<br>
* 1. 避免启动时强制初始化(兼容原型作用域)<br>
* 2. 支持按需创建新实例<br>
* 3. 自动处理依赖注入
* </p>
*
* @param factory 动态Bean工厂(由Spring自动装配)
*/
@Autowired
public DynamicServiceConsumer(@Lazy ObjectFactory<DynamicService> factory) {
this.dynamicServiceFactory = factory;
Logger.debugF("DynamicServiceConsumer initialized with factory: {}", factory.hashCode());
}
/**
* <h3>执行动态操作</h3>
* <p>
* <b>行为特征:</b>
* <ul>
* <li>每次调用都会获取新实例(原型作用域)</li>
* <li>自动处理Bean不存在的情况</li>
* </ul>
* </p>
*/
public void execute() {
try {
DynamicService service = dynamicServiceFactory.getObject();
service.performDynamicAction();
Logger.info("Dynamic action executed successfully");
} catch (IllegalStateException e) {
Logger.errorF("DynamicService registration failed: {}", e.getMessage());
}
}
/**
* <h3>验证动态注册状态</h3>
* <p>
* 调试方法:检查工厂是否包含有效Bean定义
* </p>
*/
public void validateRegistration() {
dynamicServiceFactory.getObject();
Logger.debug("DynamicService registration verified");
}
}
LifecycleBean
package com.dwl.application_context_case.service;
import com.dwl.log.Logger;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.NonNull;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.stereotype.Component;
/**
* 生命周期管理示例Bean
* <p>
* 该类演示Spring容器的完整Bean生命周期管理,包含:
* 1. Bean元数据感知能力(名称/工厂)
* 2. JSR-250标准生命周期方法
* 3. Spring原生生命周期接口
* 4. 初始化/销毁回调组合使用
* </p>
*
* <p>
* 生命周期执行顺序(简化版):
* 1. setBeanName()
* 2. setBeanFactory()
* 3. @PostConstruct
* 4. afterPropertiesSet()
* 5. 自定义init-method
* 6. @PreDestroy
* 7. destroy()
* </p>
*
* <p>
* 日志策略:
* - INFO级别:记录关键生命周期节点
* - DEBUG级别:记录调试信息
* - WARN级别:记录潜在问题
* - ERROR级别:记录初始化失败
* </p>
*
* @author By Dwl
* @version 1.0.0
* @see BeanNameAware
* @see BeanFactoryAware
* @see InitializingBean
* @see DisposableBean
* @since 2025
*/
@Component
public class LifecycleBean implements BeanNameAware, BeanFactoryAware,
InitializingBean, DisposableBean {
private String beanName;
/**
* 设置Bean名称
* <p>
* 生命周期阶段:实例化后立即执行
* 执行顺序:优先于其他初始化方法
* </p>
*
* @param name Spring容器分配的Bean名称
*/
@Override
public void setBeanName(@NonNull String name) {
this.beanName = name;
Logger.infoF("Bean名称已设置 - Name: {}, Class: {}", name, this.getClass().getSimpleName());
}
/**
* 设置BeanFactory引用
* <p>
* 生命周期阶段:实例化后立即执行
* 执行顺序:紧随setBeanName()
* </p>
*
* @param factory 当前Bean所属的BeanFactory实例
* @throws BeansException 如果设置失败
*/
@Override
public void setBeanFactory(BeanFactory factory) {
Logger.debugF("BeanFactory引用已设置 - Factory ID: {}", factory.toString());
}
/**
* JSR-250标准初始化方法
* <p>
* 生命周期阶段:属性设置完成后执行
* 执行顺序:在afterPropertiesSet()之后
* </p>
*
* @throws Exception 初始化失败时抛出异常
* @see PostConstruct
*/
@PostConstruct
public void init() throws Exception {
Logger.info("JSR-250初始化方法执行 - 开始");
// 模拟初始化操作
validateRequiredProperties();
Logger.info("JSR-250初始化方法执行 - 完成");
}
/**
* Spring原生初始化方法
* <p>
* 生命周期阶段:所有属性设置完成后执行
* 执行顺序:在@PostConstruct之后
* </p>
*/
@Override
public void afterPropertiesSet() {
Logger.info("Spring初始化方法执行 - 开始");
// 执行自定义初始化逻辑
initializeResources();
Logger.info("Spring初始化方法执行 - 完成");
}
/**
* JSR-250标准销毁方法
* <p>
* 生命周期阶段:容器销毁前执行
* 执行顺序:在destroy()之前
* </p>
*
* @see PreDestroy
*/
@PreDestroy
public void destroyJsr250() {
Logger.warn("JSR-250销毁方法执行 - 开始");
cleanupResources();
Logger.warn("JSR-250销毁方法执行 - 完成");
}
/**
* Spring原生销毁方法
* <p>
* 生命周期阶段:容器销毁时最后执行
* 执行顺序:在@PreDestroy之后
* </p>
*/
@Override
public void destroy() {
// 实际应选择一种实现方式,此处保留错误提示
Logger.error("检测到重复的destroy方法定义!请保留其中一个实现");
}
// ----------------------
// 内部辅助方法
// ----------------------
private void validateRequiredProperties() {
// 实际应验证必要属性是否已设置
if (beanName == null) {
throw new IllegalStateException("Bean名称未正确设置");
}
}
private void initializeResources() {
// 实际应执行资源初始化操作
Logger.debugF("正在初始化资源 - Bean名称: {}", beanName);
}
private void cleanupResources() {
// 实际应执行资源清理操作
Logger.debugF("正在清理资源 - Bean名称: {}", beanName);
}
}
MyBean
package com.dwl.application_context_case.service;
import com.dwl.log.Logger;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;
/**
* @ClassName MyBean
* @Description <p>
* 本类演示 Spring Bean 的初始化回调机制与事件发布能力,包含以下核心特性:
* </p>
* <ul>
* <li>通过 {@link InitializingBean} 接口实现属性初始化后的回调</li>
* <li>使用 {@link ApplicationEventPublisher} 实现自定义事件发布</li>
* <li>展示 Bean 生命周期中初始化阶段与业务逻辑的结合方式</li>
* </ul>
*
* <p>
* 典型应用场景:当 Bean 完成依赖注入后需要立即执行初始化逻辑,
* 或需要与其他组件进行解耦的事件通信时使用
* </p>
* @Version 1.0.0
* @Date 2025
* @Author By Dwl
*/
@Component
public class MyBean implements InitializingBean {
/**
* Spring 事件发布器,用于发布自定义事件
* <p>
* 特性说明:
* - 由 Spring 容器自动注入
* - 实现 ApplicationEvent 发布的统一接口
* - 支持发布任意类型的 ApplicationEvent 子类事件
* </p>
* <p>
* 替代方案:可通过实现 {@link ApplicationEventPublisherAware} 接口获取
* </p>
*/
@Autowired
private ApplicationEventPublisher publisher;
/**
* Spring Bean 初始化完成后的标准回调方法
* <p>
* 执行时机:
* 1. 所有 @Autowired 依赖注入完成
* 2. Bean 定义的所有属性设置完成
* 3. 在 Bean 初始化流程的早期阶段执行(早于自定义 init-method)
* </p>
* <p>
* 与 @PostConstruct 的区别:
* - 本方法属于 Spring 框架接口回调
* - @PostConstruct 属于 JSR-250 规范,优先级更高
* - 两者执行顺序:@PostConstruct -> afterPropertiesSet
* </p>
*/
@Override
public void afterPropertiesSet() {
// 执行初始化完成后的业务逻辑
Logger.info("【生命周期回调】MyBean 所有属性已初始化完成");
// 示例:初始化完成后自动触发业务注册
register(); // 根据实际需求决定是否在此处直接触发
}
/**
* 自定义业务注册方法
* <p>
* 功能说明:
* 1. 演示如何通过事件机制实现业务解耦
* 2. 发布自定义的 MyRegisteredEvent 事件
* 3. 事件携带当前 Bean 的引用作为事件源
* </p>
* <p>
* 典型调用场景:
* - 初始化完成后自动触发(通过 afterPropertiesSet 调用)
* - 通过其他事件监听器间接触发
* - 手动调用(需确保此时 Bean 已完成初始化)
* </p>
*/
public void register() {
// 构造并发布自定义事件
publisher.publishEvent(new MyRegisteredEvent(this));
// 事件发布后执行的其他业务逻辑(如果有)
Logger.info("【事件发布】已触发 MyRegisteredEvent 事件");
}
/**
* 自定义事件类(需继承 ApplicationEvent)
* <p>
* 设计要点:
* 1. 必须继承 ApplicationEvent 基类
* 2. 通过构造函数传递事件源对象(即发布事件的 Bean)
* 3. 包含事件相关的数据(可根据需求添加字段)
* </p>
* <p>
* source 事件源对象(通常是发布事件的 Bean)
*/
public static class MyRegisteredEvent extends ApplicationEvent {
public MyRegisteredEvent(Object source) {
super(source);
}
}
}
ProdAuditService
package com.dwl.application_context_case.service;
import com.dwl.application_context_case.config.DynamicBeanRegistrar;
import com.dwl.log.Logger;
/**
* @ClassName ProdAuditService
* @Description <h2>动态服务示例</h2>
* <p>
* <b>核心功能:</b>
* <ul>
* <li>演示通过编程方式动态注册Bean</li>
* <li>验证BeanFactoryPostProcessor的使用</li>
* <li>展示原型作用域(Prototype Scope)行为</li>
* </ul>
* </p>
*
* <p>
* <b>关键约束:</b>
* <ul>
* <li>必须移除 {@code @Service} 注解(否则会与动态注册冲突)</li>
* <li>只能通过 {@link DynamicBeanRegistrar} 注册到容器</li>
* <li>需激活 {@code dynamic} Profile 才能生效</li>
* </ul>
* </p>
*
* <p>
* <b>使用示例:</b>
* <pre>
* {@code
* // 在需要使用的位置注入(需确保Profile激活)
* @Autowired(required = false)
* private DynamicService dynamicService;
*
* if (dynamicService != null) {
* dynamicService.performDynamicAction();
* }
* }
* </pre>
* </p>
* @Version 1.0.0
* @Date 2025
* @Author By Dwl
*/
public class ProdAuditService {
/**
* 执行动态操作
* <p>
* <b>行为特征:</b>
* <ul>
<li>每次调用都会记录独立日志(因原型作用域每次创建新实例)</li>
<li>无状态服务(不依赖成员变量)</li>
</ul>
*/
public void performDynamicAction() {
Logger.info("[DynamicService] 执行动态操作 - 实例ID: " + this.hashCode());
}
}