深入理解Spring源码之IOC 扩展原理BeanFactoryPostProcessor和事件监听ApplicationListener

简介: 深入理解Spring源码之IOC 扩展原理BeanFactoryPostProcessor和事件监听ApplicationListener

2.BeanFactoryPostProcessor

一个好的框架必备的特性至少得有开闭原则,可扩展性BeanFactoryPostProcessor也是Spring可扩展性的一个体现,我们读一下这个接口的源码

public interface BeanFactoryPostProcessor {
    /**
     * Modify the application context's internal bean factory after its standard
     * initialization. All bean definitions will have been loaded, but no beans
     * will have been instantiated yet. This allows for overriding or adding
     * properties even to eager-initializing beans.
     * @param beanFactory the bean factory used by the application context
     * @throws org.springframework.beans.BeansException in case of errors
     */
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

允许我们在工厂里所有的bean被加载进来后但是还没初始化前,对所有bean的属性进行修改也可以add属性值。

bean工厂后置处理器—>构造方法—>init-method。

3、ApplicationListener

3.1、测试代码:

package com.atguigu.ext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import com.atguigu.bean.Blue;
@ComponentScan("com.atguigu.ext")
@Configuration
public class ExtConfig {
  @Bean
  public Blue blue(){
    return new Blue();
  }
}

 

import org.junit.Test;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.atguigu.ext.ExtConfig;
public class IOCTest_Ext {
  @Test
  public void test01(){
    AnnotationConfigApplicationContext applicationContext  = new AnnotationConfigApplicationContext(ExtConfig.class);
    //发布事件;
    applicationContext.publishEvent(new ApplicationEvent(new String("我发布的时间")) {
    });
    applicationContext.close();
  }
}

 

3.2、ApplicationListener的应用

ApplicationListener:监听容器中发布的事件。事件驱动模型开发;

       public interface ApplicationListener<E extends ApplicationEvent>

         监听 ApplicationEvent 及其下面的子事件;

 

      步骤:

         1)、写一个监听器(ApplicationListener实现类)来监听某个事件(ApplicationEvent及其子类)

             @EventListener;

             原理:使用EventListenerMethodProcessor处理器来解析方法上的@EventListener;

 

         2)、把监听器加入到容器;

         3)、只要容器中有相关事件的发布,我们就能监听到这个事件;

                 ContextRefreshedEvent:容器刷新完成(所有bean都完全创建)会发布这个事件;

                 ContextClosedEvent:关闭容器会发布这个事件;

         4)、发布一个事件:

                 applicationContext.publishEvent();

3.3、ApplicationListener的原理

  【事件发布流程】:

    publishEvent(new ContextRefreshedEvent(this));

             1)、获取事件的多播器(派发器):getApplicationEventMulticaster()

             2)、multicastEvent派发事件:

             3)、获取到所有的ApplicationListener;

                  for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {

                  1)、如果有Executor,可以支持使用Executor进行异步派发;

                      Executor executor = getTaskExecutor();

                  2)、否则,同步的方式直接执行listener方法;invokeListener(listener, event);

                   拿到listener回调onApplicationEvent方法;

注解:为了便于理解下面只保留了最核心的源码,只在关键的调用地方打中文注释

public abstract class AbstractApplicationContext extends DefaultResourceLoader
    implements ConfigurableApplicationContext, DisposableBean {
  @Override
  public void publishEvent(ApplicationEvent event) {
    publishEvent(event, null);
  }
  protected void publishEvent(Object event, ResolvableType eventType) {
    ApplicationEvent applicationEvent;
    if (event instanceof ApplicationEvent) {
      applicationEvent = (ApplicationEvent) event;
    }
    else {
      applicationEvent = new PayloadApplicationEvent<Object>(this, event);
      if (eventType == null) {
        eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
      }
    }
    if (this.earlyApplicationEvents != null) {
      this.earlyApplicationEvents.add(applicationEvent);
    }
    else {
      getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
    }
  }
}
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
  private Executor taskExecutor;
  private ErrorHandler errorHandler;
  @Override
  public void multicastEvent(ApplicationEvent event) {
    multicastEvent(event, resolveDefaultEventType(event));
  }
  @Override
  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);
      }
    }
  }
}

3.4、 @EventListener

3.4.1、基于注解的方式创建监听器:

import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class UserInfoService {
  @EventListener(classes={ApplicationEvent.class})
  public void listen(ApplicationEvent event){
    System.out.println("UserService。。监听到的事件:"+event);
  }
}

3.4.2 @EventListener注解原理

原理:使用EventListenerMethodProcessor处理器来解析方法上的@EventListener;

再看SmartInitializingSingleton  这个类的原理即可

public class EventListenerMethodProcessor implements SmartInitializingSingleton, ApplicationContextAware

SmartInitializingSingleton 原理:->执行这个方法afterSingletonsInstantiated();

afterSingletonsInstantiated();是在所有bean初始化完成之后调用的,

断点在EventListenerMethodProcessor.afterSingletonsInstantiated()方法上查看执行流程

1)、ioc容器创建对象并refresh();

2)、finishBeanFactoryInitialization(beanFactory);初始化剩下的单实例bean;

      1)、DefaultListableBeanFactory.preInstantiateSingletons()->先创建所有的单实例bean;getBean();

      2)、获取所有创建好的单实例bean,判断是否是SmartInitializingSingleton类型的;如果是就调用afterSingletonsInstantiated();

 

 public abstract class AbstractApplicationContext extends DefaultResourceLoader
    implements ConfigurableApplicationContext, DisposableBean {
  //ioc容器创建对象并refresh();
  @Override
  public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
      prepareRefresh();
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
      prepareBeanFactory(beanFactory);
      try {
        postProcessBeanFactory(beanFactory);
        invokeBeanFactoryPostProcessors(beanFactory);
        registerBeanPostProcessors(beanFactory);
        initMessageSource();
        initApplicationEventMulticaster();
        onRefresh();
        registerListeners();
        // 初始化剩下的单实例bean
        finishBeanFactoryInitialization(beanFactory);
        finishRefresh();
      }
      catch (BeansException ex) {
        destroyBeans();
        cancelRefresh(ex);
        throw ex;
      }
      finally {
        resetCommonCaches();
      }
    }
  }
}
public abstract class AbstractApplicationContext extends DefaultResourceLoader
    implements ConfigurableApplicationContext, DisposableBean {
  protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
        beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
      beanFactory.setConversionService(
          beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    }
    if (!beanFactory.hasEmbeddedValueResolver()) {
      beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
        @Override
        public String resolveStringValue(String strVal) {
          return getEnvironment().resolvePlaceholders(strVal);
        }
      });
    }
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
      getBean(weaverAwareName);
    }
    beanFactory.setTempClassLoader(null);
    beanFactory.freezeConfiguration();
                //先创建所有的单实例bean
    beanFactory.preInstantiateSingletons();
  }
}
@SuppressWarnings("serial")
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
    implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
  @Override
  public void preInstantiateSingletons() throws BeansException {
    if (this.logger.isDebugEnabled()) {
      this.logger.debug("Pre-instantiating singletons in " + this);
    }
    List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
    for (String beanName : beanNames) {
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
        if (isFactoryBean(beanName)) {
          final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
          boolean isEagerInit;
          if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
            isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
              @Override
              public Boolean run() {
                return ((SmartFactoryBean<?>) factory).isEagerInit();
              }
            }, getAccessControlContext());
          }
          else {
            isEagerInit = (factory instanceof SmartFactoryBean &&
                ((SmartFactoryBean<?>) factory).isEagerInit());
          }
          if (isEagerInit) {
            getBean(beanName);
          }
        }
        else {
          getBean(beanName);
        }
      }
    }
    for (String beanName : beanNames) {
      Object singletonInstance = getSingleton(beanName);
                       //获取所有创建好的单实例bean,判断是否是SmartInitializingSingleton类型的;
      if (singletonInstance instanceof SmartInitializingSingleton) {
        final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
        if (System.getSecurityManager() != null) {
          AccessController.doPrivileged(new PrivilegedAction<Object>() {
            @Override
            public Object run() {
              smartSingleton.afterSingletonsInstantiated();
              return null;
            }
          }, getAccessControlContext());
        }
        else { 
                                         //如果是就调用afterSingletonsInstantiated();
          smartSingleton.afterSingletonsInstantiated();
        }
      }
    }
  }
}

待续。。。


相关文章
|
23天前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
122 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
|
10天前
|
XML Java 测试技术
spring复习01,IOC的思想和第一个spring程序helloWorld
Spring框架中IOC(控制反转)的思想和实现,通过一个简单的例子展示了如何通过IOC容器管理对象依赖,从而提高代码的灵活性和可维护性。
spring复习01,IOC的思想和第一个spring程序helloWorld
|
1天前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
18 9
|
7天前
|
缓存 Java Spring
手写Spring Ioc 循环依赖底层源码剖析
在Spring框架中,IoC(控制反转)是一个核心特性,它通过依赖注入(DI)实现了对象间的解耦。然而,在实际开发中,循环依赖是一个常见的问题。
16 4
|
11天前
|
XML Java 开发者
经典面试---spring IOC容器的核心实现原理
作为一名拥有十年研发经验的工程师,对Spring框架尤其是其IOC(Inversion of Control,控制反转)容器的核心实现原理有着深入的理解。
34 3
|
24天前
|
Java 数据库连接 数据格式
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
IOC/DI配置管理DruidDataSource和properties、核心容器的创建、获取bean的方式、spring注解开发、注解开发管理第三方bean、Spring整合Mybatis和Junit
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
|
2月前
|
XML Java 数据格式
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
这篇文章是Spring5框架的实战教程,主要介绍了如何在Spring的IOC容器中通过XML配置方式使用外部属性文件来管理Bean,特别是数据库连接池的配置。文章详细讲解了创建属性文件、引入属性文件到Spring配置、以及如何使用属性占位符来引用属性文件中的值。
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
|
4月前
|
XML Java 数据格式
Spring5系列学习文章分享---第一篇(概述+特点+IOC原理+IOC并操作之bean的XML管理操作)
Spring5系列学习文章分享---第一篇(概述+特点+IOC原理+IOC并操作之bean的XML管理操作)
41 1
|
4月前
|
XML druid Java
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
45 0
|
2月前
|
XML Java 数据格式
Spring5入门到实战------3、IOC容器-Bean管理XML方式(一)
这篇文章详细介绍了Spring框架中IOC容器的Bean管理,特别是基于XML配置方式的实现。文章涵盖了Bean的定义、属性注入、使用set方法和构造函数注入,以及如何注入不同类型的属性,包括null值、特殊字符和外部bean。此外,还探讨了内部bean的概念及其与外部bean的比较,并提供了相应的示例代码和测试结果。
Spring5入门到实战------3、IOC容器-Bean管理XML方式(一)
下一篇
无影云桌面