1.BeanFactoryPostProcessor
BeanPostProcessor:Bean后置处理器,在bean创建对象初始化前后进行拦截工作。
BeanFactoryPostProcessor:BeanFactory的后置处理器,在BeanFactory标准初始化后调用,可以修改BeanFactory的内容,此时所有Bean定义都已经加载到BeanFactory了,但是Bean还没有创建实例。
创建ExtConfig配置类,MyBeanFactoryPostProcessor类进行测试。
package com.atguigu.ext;
import com.atguigu.bean.Car;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan({"com.atguigu.ext"})
public class ExtConfig {
@Bean
public Car cat() {
return new Car();
}
}
package com.atguigu.ext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("MyBeanFactoryPostProcessor.postProcessBeanFactory");
int count = configurableListableBeanFactory.getBeanDefinitionCount();
System.out.println("当前BeanFactory中有" + count + "个Bean");
String[] beanDefinitionNames = configurableListableBeanFactory.getBeanDefinitionNames();
System.out.println(Arrays.asList(beanDefinitionNames));
}
}
查看IOC容器的refresh()方法,其中有一个invokeBeanFactoryPostProcessors()方法,用来执行BeanFactoryPostProcessor的方法,在这个方法的后面,可以看到finishBeanFactoryInitialization()方法,在这里才为单实例bean创建对象。
2.BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子类,这是一个接口,它有一个postProcessBeanDefinitionRegistry()方法。它在所有bean定义信息将要被加载,bean实例还没创建的时候执行,它比BeanFactoryPostProcessor的postProcessBeanFactory()要早。
创建一个MyBeanDefinitionRegistryPostProcessor类,实现BeanDefinitionRegistryPostProcessor接口中的方法。
package com.atguigu.ext;
import com.atguigu.bean.Car;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.*;
import org.springframework.stereotype.Component;
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
/**
* @param beanDefinitionRegistry bean信息保存中心,后面BeanFactory就是按照BeanDefinitionRegistry里保存的每一个bean定义信息创建Bean实例
* @throws BeansException
*/
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
System.out.println("MyBeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry...bean的数量:" + beanDefinitionRegistry.getBeanDefinitionCount());
// 还可以通过beanDefinitionRegistry自己添加bean
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Car.class);
// 另一种获取BeanDefinition的方式
// AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Car.class).getBeanDefinition();
beanDefinitionRegistry.registerBeanDefinition("car", rootBeanDefinition);
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("MyBeanDefinitionRegistryPostProcessor.postProcessBeanFactory...bean的数量:" + configurableListableBeanFactory.getBeanDefinitionCount());
}
}
因为BeanDefinitionRegistryPostProcessor在BeanFactoryPostProcessor前执行,所以我们可以利用BeanDefinitionRegistryPostProcessor给容器中添加一些组件。
3.ApplicationListener用法
ApplicationListener可以监听容器中发生的事件,进行事件驱动模型开发。public interface ApplicationListener<E extends ApplicationEvent> extends EventListener可以监听ApplicationListener及其下面的子事件。
创建一个MyApplicationListener实现ApplicationListener接口的方法。
package com.atguigu.ext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
public void onApplicationEvent(ApplicationEvent applicationEvent) {
System.out.println("MyApplicationListener.onApplicationEvent...收到事件" + applicationEvent);
}
}
发布自定义监听器:
- 编写一个监听器来监听事件(ApplicationEvent及其子事件)
- 将监听器添加到容器中
- 容器中有相关事件发布,监听器就可以监听到事件,现在我们可以监听到ContextRefreshedEvent和ContextClosedEvent
- 发布事件
4.ApplicationListener原理
事件发布流程:
调用refresh()方法刷新IOC容器→在refresh()方法最后一步,执行finishRefresh()方法→调用publishEvent方法将事件发布出去→获取事件多播器getApplicationEventMulticaster()并调用multicastEvent()方法进行派发。
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
// 获取所有的ApplicationListener用于遍历
Iterator var4 = this.getApplicationListeners(event, type).iterator();
while(var4.hasNext()) {
final ApplicationListener<?> listener = (ApplicationListener)var4.next();
Executor executor = this.getTaskExecutor();
// 可以异步执行,则创建线程异步执行
if (executor != null) {
executor.execute(new Runnable() {
public void run() {
SimpleApplicationEventMulticaster.this.invokeListener(listener, event);
}
});
} else {// 同步执行
this.invokeListener(listener, event);
}
}
}
执行invokeListener()方法→执行doInvokeListener()→执行onApplicationEvent()方法。
在refresh()方法中,initApplicationEventMulticaster()方法用于创建事件多播器。
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
// 查找容器中是否有以applicationEventMulticaster为id的组件,如果有就用它
if (beanFactory.containsLocalBean("applicationEventMulticaster")) {
this.applicationEventMulticaster = (ApplicationEventMulticaster)beanFactory.getBean("applicationEventMulticaster", ApplicationEventMulticaster.class);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
} else {// 如果没有,就自己创建一个SimpleApplicationEventMulticaster类型的多播器组件,并注册进容器,其他组件在派发事件的时候,直接从容器中获取这个多播器即可使用
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton("applicationEventMulticaster", this.applicationEventMulticaster);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Unable to locate ApplicationEventMulticaster with name 'applicationEventMulticaster': using default [" + this.applicationEventMulticaster + "]");
}
}
}
在refresh()方法中,有一个registerListeners()方法,首先获取所有的ApplicationListener,并把它们加到多播器中。
5.@EventListener与SmartInitializingSingleton
@EventListener可以标注在方法上,表示这个方法用来监听事件。
package com.atguigu.ext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class UserService {
// 在classes里指定要监听的事件
@EventListener(classes = {ApplicationEvent.class})
public void listen(ApplicationEvent applicationEvent) {
System.out.println("UserService.listen...监听到的事件:" + applicationEvent);
}
}
@EventListener能起作用,是EventListenerMethodProcessor类来做的处理。EventListenerMethodProcessor实现了SmartInitializingSingleton接口,接口里有一个afterSingletonsInstantiated()方法,afterSingletonsInstantiated()方法会在所有的单实例bean创建完成后执行,通过调试,可以查看调用路径。
refresh()→finishBeanFactoryInitialization()→beanFactory.preInstantiateSingletons()→DefaultListableBeanFactory.preInstantiateSingletons()→smartSingleton.afterSingletonsInstantiated()。