在开始分析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能监听到什么事件是基于事件的类型,这个你可以自己去实验看看。