Spring Framework 5 源码——在所有bean创建后触发事件

本文介绍了如何在SpringFramework5源码基础上构建测试工程,通过实现SmartInitializingSingleton接口或添加ApplicationEvent监听器,实现在所有bean创建后触发事件。作者详细剖析了两种方法的工作原理和源码实现过程。
摘要由CSDN通过智能技术生成

前面的文章中已经讲了如何通过Intellij搭建Spring Framework 5 的源码开发环境,下面我们来通过结合源码来解决实际问题,知道问题背后的本质。

搭建测试工程

我们通过在spring framework源码上添加一个gradle的module模块,来实现自己的一些测试功能验证,本文中的案例使用的是DEMO_01的package,截图如下:
image.png

所有代码如下

package com.jz.learning.demo.DEMO_01;

import com.jz.learning.demo.DEMO_01.config.AppConfig;
import com.jz.learning.demo.DEMO_01.pojo.Dog;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

        Dog dog = applicationContext.getBean(Dog.class);
    }
}

package com.jz.learning.demo.DEMO_01.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = {"com.jz.learning.demo.DEMO_01.pojo",
                               "com.jz.learning.demo.DEMO_01.custom_smartInitialization",
                               "com.jz.learning.demo.DEMO_01.custom_applicationEvent"})
public class AppConfig {
}

package com.jz.learning.demo.DEMO_01.custom_applicationEvent;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationEventListener {
    Log log = LogFactory.getLog(MyApplicationEventListener.class.getName());
    @EventListener(classes = ApplicationEvent.class)
    public void listenAfterAllBeanCreated(ApplicationEvent event){
        log.info("ApplicationEvent Listener execute!");
    }

}

package com.jz.learning.demo.DEMO_01.custom_smartInitialization;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.stereotype.Component;

@Component
public class MySmartInitialization implements SmartInitializingSingleton {

    static Log log = LogFactory.getLog(MySmartInitialization.class.getName());
    @Override
    public void afterSingletonsInstantiated() {
        log.info("All Bean Instantiated!");
    }
}

package com.jz.learning.demo.DEMO_01.custom_smartInitialization;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.stereotype.Component;



@Component
public class MySmartInitialization_02 implements SmartInitializingSingleton {
    static Log log = LogFactory.getLog(MySmartInitialization_02.class.getName());

    @Override
    public void afterSingletonsInstantiated() {
        log.info("All Bean Instantiated!");
    }
}

运行结果

红色框出来的是log日志的输出,可以看到,Cat和Dog两个Bean先创建,然后调用了2个自定义的MySmartInitialization的afterSingletonsInstantiatied() 方法,和一个自定义的MyApplicationEventListener事件的监听方法listenAfterAllBeanCreated()
image.png

源码分析

进入AnnotationConfigApplicationContext类

image.png

找到大名鼎鼎的refresh()方法

image.png

重点关注两个方法

finishBeanFactoryInitialization

image.png

所有的秘密都藏在源码的这两个方法背后,首先看第一个方法 finishBeanFactoryInitialization
image.png
进入后继续跟进beanFactory.preInstantiateSingletions() 方法,并找到对应实现类DefaultListableBeanFactory里的preInstantiateSingletons() 方法
image.png
在方法的结尾发现有如下一段代码
image.png
可以发现,spring源码在创建所有bean结束后的finishBeanFactoryInitialization() 方法中调用了DefaultListableBeanFactory的preInstantiateSingletons()方法的结尾处,对所有的bean进行遍历,如果该类实现了SmartInitializingSingleton接口,则调用该接口里的afterSingletonsInstantiated()方法

finishRefresh

接着来看另外一种实现方式,通过监听ApplicationEvent时间来实现,答案就在finishRefresh()方法里
image.png
继续跟进代码
image.png
知道一个方法叫publishEvent() ,如上截图所示,然后继续跟进
image.png
最后会调用到 multicastEvent方法,并且遍历执行所有的Listener
image.png
image.png

总结

本文在源码中搭建了一个项目工程,实现了在所有bean创建完后触发事件,有两种方法可以实现:1)通过继承SmartInitializingSingleton接口,2)通过添加ApplicationEvent的EventListener。
最后通过源码分析,阐述了两种方法实现的本质原理。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jzlover

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值