Spring IOC 扩展原理之BeanFactoryPostProcessor和事件监听ApplicationListener

本文深入探讨了Spring IOC的扩展机制,主要讲解了BeanFactoryPostProcessor和事件监听ApplicationListener的工作原理。首先,介绍了BeanFactoryPostProcessor在bean实例化前对beanFactory的定制和修改。接着,阐述了BeanDefinitionRegistryPostProcessor的执行过程,它在BeanFactoryPostProcessor之前执行,用于在bean定义加载前添加组件。最后,详细分析了事件监听机制,包括ApplicationListener的创建步骤、事件的发布和派发过程,以及@EventListener注解的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring IOC 扩展原理之BeanFactoryPostProcessor和事件监听ApplicationListener

BeanPostProcessor:bean后置处理器,bean创建对象初始化前后进行拦截工作的

1、BeanFactoryPostProcessor:beanFactory的后置处理器;

  • 在BeanFactory标准初始化之后调用,来定制和修改BeanFactory的内容;

  • 所有的bean定义已经保存加载到beanFactory,但是bean的实例还未创建

一、BeanFactoryPostProcessor原理:

创建自定义的BeanFactoryPostProcessor,断点到方法上,查看执行的流程

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("MyBeanFactoryPostProcessor.....");
        String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
        for (int i = 0; i <beanDefinitionNames.length ; i++) {
            System.out.println("bean:"+beanDefinitionNames[i]);
        }
    }
}

1)、ioc容器创建对象

2)、invokeBeanFactoryPostProcessors(beanFactory);

如何找到所有的BeanFactoryPostProcessor并执行他们的方法;

1)、直接在BeanFactory中找到所有类型是BeanFactoryPostProcessor的组件,并执行他们的方法

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

2)、在初始化创建其他组件前面执行

二、 BeanDefinitionRegistryPostProcessor 原理

BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor postProcessBeanDefinitionRegistry();

​ 在所有bean定义信息将要被加载,bean实例还未创建的;在BeanFactoryPostProcessor接口方法之前执行

创建自定义的BeanDefinitionRegistryPostProcessor 查看执行过程

import com.willow.bean.Color;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    //在postProcessBeanDefinitionRegistry() 之后执行
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("postProcessBeanFactory...bean的数量:"+beanFactory.getBeanDefinitionCount());
    }

    //BeanDefinitionRegistry Bean定义信息的保存中心,以后BeanFactory就是按照BeanDefinitionRegistry里面保存的每一个bean定义信息创建bean实例;
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("postProcessBeanDefinitionRegistry...bean的数量:"+registry.getBeanDefinitionCount());
        //RootBeanDefinition beanDefinition = new RootBeanDefinition(Blue.class);
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Color.class).getBeanDefinition();
        registry.registerBeanDefinition("hello", beanDefinition);
    }
}

结论:

  • 优先于BeanFactoryPostProcessor执行;

  • 利用BeanDefinitionRegistryPostProcessor给容器中再额外添加一些组件;

2.1 BeanDefinitionRegistryPostProcessor 执行过程

1)、ioc创建对象

2)、refresh()->PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory);

3)、从容器中获取到所有的BeanDefinitionRegistryPostProcessor组件,并排序

​ 1、依次触发所有的postProcessBeanDefinitionRegistry()方法

4)、再来从容器中找到BeanFactoryPostProcessor组件;然后依次触发postProcessBeanFactory()方法

//先执行 BeanDefinitionRegistryPostProcessor
//PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory); 这个方法中
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
 
//执行所有的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法
private static void invokeBeanDefinitionRegistryPostProcessors(
    Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

    for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
        postProcessor.postProcessBeanDefinitionRegistry(registry);
    }
}
//后执行BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
private static void invokeBeanFactoryPostProcessors(
    Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
    for (BeanFactoryPostProcessor postProcessor : postProcessors) {
        postProcessor.postProcessBeanFactory(beanFactory);
    }
}

三、事件监听ApplicationListener

ApplicationListener:监听容器中发布的事件。事件驱动模型开发;

public interface ApplicationListener<E extends ApplicationEvent>

监听 ApplicationEvent 及其下面的子事件;

3.1创建监听器步骤:

1)、写一个监听器(ApplicationListener实现类)来监听某个事件(ApplicationEvent及其子类)

@EventListener;

原理:使用EventListenerMethodProcessor处理器来解析方法上的@EventListener;

2)、把监听器加入到容器;

3)、只要容器中有相关事件的发布,我们就能监听到这个事件;

​ ContextRefreshedEvent:容器刷新完成(所有bean都完全创建)会发布这个事件;

​ ContextClosedEvent:关闭容器会发布这个事件;

4)、发布一个事件:applicationContext.publishEvent();

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
    //当容器中发布此事件以后,方法触发
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println("收到事件:"+event);
    }
}

测试类:

@Test
public void test01() {
    AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(ExtConfig.class);
    ApplicationEvent applicationEvent=new ApplicationEvent(new String("我发布的一个事件")){};
    annotationConfigApplicationContext.publishEvent(applicationEvent );
    annotationConfigApplicationContext.close();
}

3.2监听器原理:

断点在自定义创建的MyApplicationListener方法上,查看执行流程

3.2.1)、ContextRefreshedEvent事件:
  1. 容器创建对象:refresh();

  2. finishRefresh();容器刷新完成会发布ContextRefreshedEvent事件

    protected void finishRefresh() {
       // Initialize lifecycle processor for this context.
       initLifecycleProcessor();
    
       // Propagate refresh to lifecycle processor first.
       getLifecycleProcessor().onRefresh();
    
       //发布ContextRefreshedEvent事件
       publishEvent(new ContextRefreshedEvent(this));
    
       // Participate in LiveBeansView MBean, if active.
       LiveBeansView.registerApplicationContext(this);
    }
  3. 事件发布publishEvent(new ContextRefreshedEvent(this));

     AbstractApplicationContext.publishEvent() 方法中
    //  getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); 
    1)、获取事件的多播器(派发器):getApplicationEventMulticaster()
    2)、multicastEvent派发事件:
    public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
            ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
            //3)、获取到所有的ApplicationListener;
            for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            //1)、如果有Executor,可以支持使用Executor进行异步派发;
                Executor executor = getTaskExecutor();
                if (executor != null) {
                    executor.execute(new Runnable() {
                        @Override
                        public void run() {
                            invokeListener(listener, event);
                        }
                    });
                }
                else {
        //2)、否则,同步的方式直接执行listener方法;invokeListener(listener, event);
                    invokeListener(listener, event);
                }
            }
    }
    // 拿到listener回调onApplicationEvent方法;listener.onApplicationEvent(event);

3.2.2)、自己发布事件;
3.2.3)、容器关闭会发布ContextClosedEvent;
 AbstractApplicationContext.doClose()  -->publishEvent(new ContextClosedEvent(this));

3.3事件多播器(派发器)初始化原理:

1)、容器创建对象:refresh();

2)、initApplicationEventMulticaster();初始化ApplicationEventMulticaster;

initApplicationEventMulticaster(); //refresh();方法中
//初始化 多播器
protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    //   1)、先去容器中找有没有id=“applicationEventMulticaster”的组件;
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster =
            beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        if (logger.isDebugEnabled()) {
            logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
        }
    }
    else {
        //2)、如果没有创建了一个SimpleApplicationEventMulticaster并且加入到容器中,我们就可以在其他组件要派发事件,自动注入这个applicationEventMulticaster;
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
        if (logger.isDebugEnabled()) {
            logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
                         APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
                         "': using default [" + this.applicationEventMulticaster + "]");
        }
}

3.4 注册监听器原理:

1)、容器创建对象:refresh();

2)、注册监听器到派发器中,refresh()->registerListeners();

//AbstractApplicationContext
protected void registerListeners() {
    // Register statically specified listeners first.
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }

    //从容器中拿到所有的监听器,把他们注册到applicationEventMulticaster中;
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        //将listener注册到ApplicationEventMulticaster中
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }

    // Publish early application events now that we finally have a multicaster...
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (earlyEventsToProcess != null) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

3.4 @EventListener创建监听器:

3.4.1 基于注解的方式创建监听器:
@Component
public class AnnotationListener {
    
    @EventListener(classes={ApplicationEvent.class}) //classes 监听器的类型
    public void listen(ApplicationEvent event){
        System.out.println("UserService...监听到的事件:"+event);
    }
}

3.4.2 @EventListener注解原理

原理:使用EventListenerMethodProcessor处理器来解析方法上的@EventListener;

再看SmartInitializingSingleton 这个类的原理即可

public class EventListenerMethodProcessor implements SmartInitializingSingleton, ApplicationContextAware 
SmartInitializingSingleton 原理:->执行这个方法afterSingletonsInstantiated();

afterSingletonsInstantiated();是在所有bean初始化完成之后调用的,

断点在EventListenerMethodProcessor.afterSingletonsInstantiated()方法上查看执行流程

1)、ioc容器创建对象并refresh();

2)、finishBeanFactoryInitialization(beanFactory);初始化剩下的单实例bean;

​ 1)、DefaultListableBeanFactory.preInstantiateSingletons()->先创建所有的单实例bean;getBean();

​ 2)、获取所有创建好的单实例bean,判断是否是SmartInitializingSingleton类型的;如果是就调用afterSingletonsInstantiated();

//这个类的DefaultListableBeanFactory.preInstantiateSingletons() 
for (String beanName : beanNames) {
    Object singletonInstance = getSingletone(beanName);
    //  2)、获取所有创建好的单实例bean,判断是否是SmartInitializingSingleton类型的;
    if (singletonInstance instanceof SmartInitializingSingleton) {
        final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    smartSingleton.afterSingletonsInstantiated();
                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            //调用SmartInitializingSingleton类型的这个方法afterSingletonsInstantiated()
            smartSingleton.afterSingletonsInstantiated();
        }
    }
}

<think>嗯,用户让我介绍一下Spring IoC的知识点,我需要先回忆一下自己学过的相关内容。首先,IoC,也就是控制反转,是Spring框架的核心之一。那什么是控制反转呢?应该是指将对象的创建依赖关系的管理从应用程序代码转移到容器中,也就是由Spring来负责这些工作。这样开发者就不用自己手动管理对象之间的依赖,降低了耦合度。 接下来,可能需要分几个部分来介绍。首先是IoC的基本概念,然后是它的实现方式,比如依赖注入(DI)。依赖注入又有不同的方式,比如构造器注入、setter方法注入,还有接口注入,不过接口注入好像不太常用,可能主要讲前两种。另外,Spring容器有哪些,比如BeanFactoryApplicationContext,这两者的区别是什么?ApplicationContext提供了更多的企业级功能,比如事件传播、资源访问等。 然后是Bean的相关知识,比如Bean的作用域,单例、原型、请求、会话等,不过默认是单例的。Bean的生命周期,从实例化到初始化,再到销毁的过程,中间可能涉及一些回调方法,比如InitializingBeanDisposableBean接口,或者通过配置init-methoddestroy-method。 还有自动装配的方式,Spring支持几种自动装配的模式,比如byName、byType、constructor等,以及使用注解如@Autowired来进行自动注入。可能需要提到@Autowired@Resource的区别,前者是按类型,后者默认按名称。 配置方式的话,有XML配置、Java注解配置(比如@Component、@Service等),以及Java Config(使用@Configuration@Bean)。现在可能更推荐使用注解Java配置,而不是XML了。 另外,组件扫描也是一个重要的点,通过@ComponentScan来扫描指定包下的组件,自动注册为Bean。条件化注册Bean,比如@Conditional注解,可以根据条件决定是否创建某个Bean。 可能还需要提到一些高级特性,比如Bean的后置处理器,BeanFactoryPostProcessorBeanPostProcessor,它们可以在Bean的创建前后进行一些处理,比如修改Bean的定义或者属性。 还有循环依赖的问题,Spring是如何解决的?在单例作用域下,通过三级缓存来解决循环依赖,但原型作用域下无法解决,会抛出异常。这也是需要注意的地方。 另外,Spring IoC容器的事件机制,比如ApplicationEventApplicationListener,可以实现事件的发布监听,这也是ApplicationContext比BeanFactory多出来的功能之一。 总结一下,可能的结构应该是先介绍IoC的概念,然后依赖注入的方式,接着是容器的类型,Bean的配置方式、作用域、生命周期,自动装配,组件扫描,条件化配置,高级特性如后置处理器,循环依赖处理,以及事件机制等。需要确保每个知识点都简明扼要,不要遗漏重要的内容,同时用例子或者实际应用场景来帮助理解。 不过用户可能已经有一定的开发经验,所以需要深入浅出,避免太过基础,但也不能遗漏关键点。可能需要用中文的术语,比如“控制反转”、“依赖注入”、“Bean作用域”等,确保术语准确。同时,可以比较一下传统的对象创建方式IoC的优势,比如解耦、方便测试等。 可能还要提到Spring Boot对IoC的进一步简化,比如自动配置,但用户的问题主要是Spring IoC,可能不需要深入Boot的内容。总之,需要组织好各个知识点,逻辑清晰,层次分明,让读者能够系统地了解Spring IoC的核心内容。</think>Spring IoC(控制反转)是 Spring 框架的核心机制,负责管理对象的创建、依赖注入生命周期。以下是其核心知识点整理: --- ### **1. IoC 核心概念** - **控制反转(Inversion of Control)** 将对象的创建依赖管理权从代码转移到 Spring 容器,开发者仅需定义对象关系,由容器完成实例化依赖注入。 - **依赖注入(DI,Dependency Injection)** IoC 的具体实现方式,通过容器将依赖对象自动注入到目标对象中,解耦组件间的依赖关系。 --- ### **2. Spring 容器** - **BeanFactory** 基础容器接口,提供 Bean 的注册管理功能(如 `getBean()`),延迟初始化。 - **ApplicationContext** `BeanFactory` 的子接口,扩展了更多企业级功能(如国际化、事件机制、资源加载等),默认立即初始化 Bean。 --- ### **3. Bean 的配置方式** - **XML 配置** 传统方式,通过 `<bean>` 标签定义 Bean 及依赖。 ```xml <bean id="userService" class="com.example.UserService"> <property name="userDao" ref="userDao"/> </bean> ``` - **注解配置** 使用 `@Component`、`@Service` 等注解标记 Bean,结合 `@Autowired` 自动注入依赖。 ```java @Service public class UserService { @Autowired private UserDao userDao; } ``` - **Java Config** 通过 `@Configuration` `@Bean` 以编程方式配置 Bean。 ```java @Configuration public class AppConfig { @Bean public UserDao userDao() { return new UserDaoImpl(); } } ``` --- ### **4. Bean 的作用域** - **Singleton(默认)** 容器中仅存在一个 Bean 实例。 - **Prototype** 每次请求都生成新实例。 - **Request/Session/Application** Web 环境中针对请求、会话或应用级别的单例。 --- ### **5. Bean 生命周期** 1. **实例化**:容器调用构造器创建对象。 2. **属性注入**:通过 Setter 或构造器注入依赖。 3. **初始化**:调用 `InitializingBean.afterPropertiesSet()` 或自定义 `init-method`。 4. **使用**:Bean 处于就绪状态。 5. **销毁**:调用 `DisposableBean.destroy()` 或自定义 `destroy-method`。 --- ### **6. 依赖注入方式** - **构造器注入** 通过构造方法传递依赖,推荐用于强依赖场景。 ```java public class UserService { private final UserDao userDao; public UserService(UserDao userDao) { this.userDao = userDao; } } ``` - **Setter 注入** 通过 Setter 方法注入,适合可选依赖。 - **字段/方法注入** 使用 `@Autowired` 直接注入字段或方法(需开启注解支持)。 --- ### **7. 自动装配(Autowiring)** - **模式** `byType`(按类型)、`byName`(按名称)、`constructor`(构造器匹配)。 - **注解** `@Autowired`(默认按类型,可结合 `@Qualifier` 指定名称),`@Resource`(默认按名称)。 --- ### **8. 高级特性** - **组件扫描** 通过 `@ComponentScan` 自动扫描并注册 Bean。 - **条件化 Bean** 使用 `@Conditional` 根据条件动态注册 Bean。 - **Bean 后置处理器** 实现 `BeanPostProcessor` 接口干预 Bean 初始化过程(如 AOP 代理)。 - **解决循环依赖** 单例模式下通过三级缓存(提前暴露半成品 Bean)处理循环依赖。 --- ### **9. 优势** - **解耦**:对象间依赖由容器管理,降低代码耦合。 - **可测试性**:依赖注入便于单元测试(如 Mock 对象)。 - **灵活性**:通过配置或注解快速调整组件关系。 --- ### **示例代码片段** ```java // 注解配置示例 @Configuration @ComponentScan("com.example") public class AppConfig { @Bean public DataSource dataSource() { return new HikariDataSource(); } } // 使用 @Autowired @Service public class UserService { @Autowired private UserRepository userRepository; } ``` 掌握 Spring IoC 是理解 Spring 生态的基础,后续可结合 Spring AOP、Spring Boot 等进一步深入。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值