Spring框架IOC容器初始化核心源码解析之一:基础概念

本文深入剖析Spring框架的三大核心组件:BeanDefinitionRegisterPostProcessor、BeanFactoryPostProcessor和BeanPostProcessor,探讨它们在Spring容器初始化过程中的作用及其实现方式。
摘要由CSDN通过智能技术生成

在开始分析spring框架源码之前,需要先了解spring的几个核心的组件,其中在启动过程中最重要的就是BeanDefinitionRegisterPostProcessor、BeanFactoryPostProcessor、BeanPostProcessor组件。

源代码地址 https://gitee.com/cq-laozhou/spring-stack-source-code-analysis

BeanFactoryPostProcessor 组件

Spring的BeanFactoryPostProcessor接口定义了postProcessBeanFactory()方法,该方法会在spring容器的初始化过程中调用,调用的时机是当所有BeanDefinition已经注册到容器中后,但是所有的bean都没有实例化之前。它可以对已经注册到容器中的beandefinition进行修改。

比如有PersonBeanSetLazyBeanFactoryPostProcessor的类,其实现了BeanFactoryPostProcessor接口,它会找到名称为person的beandefinition,并将lazy属性设置为true。

@Component
public class PersonBeanSetLazyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("--PersonBeanSetLazyBeanFactoryPostProcessor.postProcessBeanFactory---");
        beanFactory.getBeanDefinition("person").setLazyInit(true);
    }
}

补上常规的Person类

public class Person {
    public Person() {
        System.out.println("--person 构造方法--");
    }
}

在配置类中将Person声明为bean,注意配置类上加了@ComponentScan注解,这样会将PersonBeanSetLazyBeanFactoryPostProcessor扫描到,并将之注册为bean。

@Configuration
@ComponentScan
public class MainConfig {

    @Bean
    public Person person(){
        return new Person();
    }

}

在Main类中,初始化容器,输出注册的bean列表:

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
        printAllSpringBeanName(context);
        context.registerShutdownHook();
    }
    private static void printAllSpringBeanName(ApplicationContext context) {
        String[] names = context.getBeanDefinitionNames();
        System.out.println("============================");
        for (String name : names) {
            System.out.println("beanName: " + name);
        }
    }
}

输出:

--PersonBeanSetLazyBeanFactoryPostProcessor.postProcessBeanFactory---
============================
beanName: org.springframework.context.annotation.internalConfigurationAnnotationProcessor
beanName: org.springframework.context.annotation.internalAutowiredAnnotationProcessor
beanName: org.springframework.context.annotation.internalRequiredAnnotationProcessor
beanName: org.springframework.context.annotation.internalCommonAnnotationProcessor
beanName: org.springframework.context.event.internalEventListenerProcessor
beanName: org.springframework.context.event.internalEventListenerFactory
beanName: mainConfig
beanName: personBeanSetLazyBeanFactoryPostProcessor
beanName: person

可以看到,spring容器初始化过程中会调用BeanFactoryPostProcessor.postProcessBeanFactory方法,同时person bean并没有实例化,说明person的beandefinition已经修改生效。

你可以将PersonBeanSetLazyBeanFactoryPostProcessor不注册为bean,此时观察输出,会发现person会实例化。

BeanDefinitionRegisterPostProcessor 组件

BeanDefinitionRegisterPostProcessor 接口继承至 BeanFactoryPostProcessor 接口,提供了新的方法postProcessBeanDefinitionRegistry。它除了能够实现BeanFactoryPostProcessor的修改beandefinition以外,还能够往容器中注册新的beandefinition。调用的时机也是当所有BeanDefinition已经注册到容器中后,但是所有的bean都没有实例化之前,但是它比BeanFactoryPostProcessor先调用。

比如有PersonBeanDefinitionRegistryPostProcessor实现了接口,在postProcessBeanDefinitionRegistry方法中新注册了名为“person2”的Person类型的beandefinition。

@Component
public class PersonBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("---PersonBeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry--");
        registry.registerBeanDefinition("person2", new RootBeanDefinition(Person.class));
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("---PersonBeanDefinitionRegistryPostProcessor.postProcessBeanFactory--");
    }
}

补上配置类和测试代码:

@Configuration
@ComponentScan
public class MainConfig {
}
public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
        printAllSpringBeanName(context);
        context.registerShutdownHook();
    }
    private static void printAllSpringBeanName(ApplicationContext context) {
        String[] names = context.getBeanDefinitionNames();
        System.out.println("============================");
        for (String name : names) {
            System.out.println("beanName: " + name);
        }
    }
}

观察下输出结果:

---PersonBeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry--
---PersonBeanDefinitionRegistryPostProcessor.postProcessBeanFactory--
============================
beanName: org.springframework.context.annotation.internalConfigurationAnnotationProcessor
beanName: org.springframework.context.annotation.internalAutowiredAnnotationProcessor
beanName: org.springframework.context.annotation.internalRequiredAnnotationProcessor
beanName: org.springframework.context.annotation.internalCommonAnnotationProcessor
beanName: org.springframework.context.event.internalEventListenerProcessor
beanName: org.springframework.context.event.internalEventListenerFactory
beanName: mainConfig
beanName: personBeanDefinitionRegistryPostProcessor
beanName: person2

ApplicationEventMulticaster & ApplicationListener 组件

spring使用观察者模式,提供了ApplicationEventMulticaster & ApplicationListener 组件,ApplicationEventMulticaster用来发布事件,ApplicationListener用于监听事件。spring内部的一些事件就是通过它来发布的,我们也可以单独使用它来满足我们自己的事件发布与监听。

比如有PrintEventListener,实现了ApplicationListener接口,它会监听所有ApplicationEvent类型的事件,并打印事件信息:

@Component
public class PrintEventListener implements ApplicationListener{
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println("---收到Event:["+event.toString()+"]---");
    }
}

给出配置类和测试代码:

@Configuration
@ComponentScan
public class MainConfig {

}
public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
        Assert.isTrue(context.containsBean("applicationEventMulticaster"),"容器中没有包含多播器");

        context.registerShutdownHook();
    }
}

运行输出:

---收到Event:[org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@1134affc: startup date [Fri Dec 06 16:02:51 CST 2019]; root of context hierarchy]]---
---收到Event:[org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@1134affc: startup date [Fri Dec 06 16:02:51 CST 2019]; root of context hierarchy]]---

我们自己的监听器,监听到了容器初始化和关闭时发布的事件了。

我们也可以定义和发布自己的事件:

public class OnlyMessageEvent extends ApplicationEvent {

    private String message;

    public OnlyMessageEvent(Object source, String message) {
        super(source);
        this.message = message;
    }

    public OnlyMessageEvent(Object source) {
        super(source);
    }
}
public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
        Assert.isTrue(context.containsBean("applicationEventMulticaster"),"容器中没有包含多播器");
        context.publishEvent(new OnlyMessageEvent(context,"手动发布了一个事件"));
        context.registerShutdownHook();
    }
}

运行输出:

---收到Event:[org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@1134affc: startup date [Fri Dec 06 16:02:51 CST 2019]; root of context hierarchy]]---
---收到Event:[com.zyy.sc.analysis.framework.testEventAndListener.OnlyMessageEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@1134affc: startup date [Fri Dec 06 16:06:22 CST 2019]; root of context hierarchy]]---
---收到Event:[org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@1134affc: startup date [Fri Dec 06 16:02:51 CST 2019]; root of context hierarchy]]---

可以看到,自己发布的事件也被接收到了。

ApplicationListener接口实际上是定义为泛型的,因此,ApplicationListener能监听到什么事件是基于事件的类型,这个你可以自己去实验看看。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值