Spring源码分析之IOC的三种常见用法及源码实现(二)
回顾上文 我们研究的是
AnnotationConfigApplicationContext annotationConfigApplication = new AnnotationConfigApplicationContext (MainConfig.class);
Person person2 = (Person)annotationConfigApplication.getBean("person2");
这两句话的实现,其中来到了主角儿AnnotationConfigApplicationContext的构造器实现:
public AnnotationConfigApplicationContext(Class>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}
其中this()和register(annotatedClasses);看完了,我们这次来看看refresh();
一、跟进refresh()的代码
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
讲这个之前铺垫一点前置基础知识
Spring中事件驱动开发
spring中是通过ApplicationListener及ApplicationEventMulticaster来进行事件驱动开发的,即实现观察者设计模式或发布-订阅模式。
ApplicationListener:监听容器中发布的事件,只要事件发生,就触发监听器的回调,来完成事件驱动开发。属于观察者设计模式中的Observer对象。
ApplicationEventMulticaster:用来通知所有的观察者对象,属于观察者设计模式中的Subject对象。
Spring后置处理器
BeanFactoryPostProcessor:继承这个的类它的实现方法可以在spring的bean定义好之后 而未实例化的时候做一些逻辑操作
BeanDefinitionRegistryPostProcessor:继承这个类它的实现方法可以在spring的bean未加载定义之前加些我们自己定义的bean定义
ok讲完了,回到代码。
我们铺垫了前置知识那么就对其中的
initApplicationEventMulticaster();
和
registerListeners();
进行讲解
二、refresh()中的initApplicationEventMulticaster
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
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 {
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 + "]");
}
}
}
非常好懂,就一个if else,首先获取beanfactory,翻看源码知道这个beanfactory就是上篇文章讲的初始化父类时创建的DefaultListableBeanFactory,拿到这玩意。还是围绕这玩意的功能操作
接下来判断beanfactory里是不是有这个APPLICATION_EVENT_MULTICASTER_BEAN_NAME,翻看源码:
public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
是不是就是之前铺垫知识的listener?用来通知事件的。看看它在不在容器里面,不在的话走else创建一个,并且作为单例注册进去,在的话就从容器里面取出来赋值给当前this对象即我们的主角儿AnnotationConfigApplicationContext,而主角本身没定义这个是在主角父类AbstractApplicationContext里定义的,我们看看:
/** Helper class used in event publishing */
private ApplicationEventMulticaster applicationEventMulticaster;
看看,给了注释,辅助类 :用于事件派发的。
综上所述,这个initApplicationEventMulticaster()这行代码就是获取事件通知发布类的,没有的话就以单例创建一个放到容器并拿给主角儿,否则就直接拿到给主角儿。接下来看另一个registerListeners();
三、refresh()中的registerListeners();
源码如下:
protected void registerListeners() {
// Register statically specified listeners first.
for (ApplicationListener> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
Set
earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
第一个for循环是把所有listener都加到Multicaster里了(它用来通知相关事件)。其中
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
这个是从容器中拿ApplicationListener.class类型的,从名字也可以看出来getBeanForType,拿出来之后也放到Multicaster里(它用来通知相关事件),这也就是为什么我们可以自己实现ApplicationListener接口并且打上@Component注解之后能通知的原因了!它在这里加进去了。
最后一段是获取早期事件,获取了之后for循环进行触发事件。我们来看看它到底是个怎么触发的。
Set earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
打开里面的multicastEvent方法
@Override
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run() {
invokeListener(listener, event);
}
});
}
else {
invokeListener(listener, event);
}
}
}
一个解析类型、一个执行invokeListener,进去再看看这个咋invokeListener调用的
protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
listener.onApplicationEvent(event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || msg.startsWith(event.getClass().getName())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
Log logger = LogFactory.getLog(getClass());
if (logger.isDebugEnabled()) {
logger.debug("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
}
仔细看下就发现重点了,其实最终就是调用listener.onApplicationEvent(event);,而这个onApplicationEvent就是ApplicationListener接口唯一的方法。换句话说,你只要实现这个接口类,并加入@Compent加入容器中,就会调用你实现类的onApplicationEvent里你自己的代码!
可能细心的同学会发现刚刚前面看到的registerListeners中最后一段里获取的是earlyApplicationEvents,这个early是什么意思?实际上是把Multicaster还没创建时就已经缓存的事件给获取播放,因为之前来了事件也不能丢掉啊。那么什么时候会有这个early事件呢?实际上是在refresh()代码里的registerListeners方法的前一句onRefresh方法中,这个方法默认是没有early事件的,会在springboot中使用.
至此registerListeners方法也讲完了。
接下来我们来讲讲refresh()中的invokeBeanFactoryPostProcessors(beanFactory);
四、refresh()中的invokeBeanFactoryPostProcessors(beanFactory);
/**
* 按照明确的顺序实例化并调用所有在BeanFactoryPostProcessor注册的bean
* Must be called before singleton instantiation.
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
很明显继续跟进这个invokeBeanFactoryPostProcessors同名方法:
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set processedBeans = new HashSet();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List regularPostProcessors = new LinkedList();
List registryPostProcessors =
new LinkedList();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryPostProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
registryPostProcessors.add(registryPostProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
List priorityOrderedPostProcessors = new ArrayList();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
registryPostProcessors.addAll(priorityOrderedPostProcessors);
invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProces