Spring5.0源碼深度解析之容器的功能擴展

版權全部:https://my.oschina.net/u/3995125,禁止轉載

容器的功能擴展

前期準備:

一樣,咱們仍是以 AnnotationConfigApplicationContext 做爲切入點,開始對總體功能進行分析。java

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
   this();
   register(annotatedClasses);
   refresh();
}

一:建立IOC容器

進入this();spring

public AnnotationConfigApplicationContext() {
   this.reader = new AnnotatedBeanDefinitionReader(this);
   this.scanner = new ClassPathBeanDefinitionScanner(this);
}

先執行父類的初始化方法,建立IOC容器bootstrap

public GenericApplicationContext() {
   this.beanFactory = new DefaultListableBeanFactory();
}

2.進入AnnotatedBeanDefinitionReader方法執行初始化方法建立BeanDefinition讀取器app

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
   Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
   Assert.notNull(environment, "Environment must not be null");
   this.registry = registry;
   this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
   AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

AnnotationConfigUtils獲取全部BeanPostProcessor的Bean,把下面6個對象注入到IOC容器中了編輯器

這裏用到了CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME 、AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME 等幾個常量ide

常量 對應的BeanPostProcessor  對應的註解
CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME     ConfigurationClassPostProcessor     @Configuration
AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME     AutowiredAnnotationBeanPostProcessor      @AutoWired
REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME     RequiredAnnotationBeanPostProcessor @Required
COMMON_ANNOTATION_PROCESSOR_BEAN_NAME  CommonAnnotationBeanPostProcessor @javax.annotation.PostConstruct、@javax.annotation.PreDestroy

等等,還有幾個,就不列了。函數

3.進入ClassPathBeanDefinitionScanner方法建立classPath下掃描器工具

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
      Environment environment, @Nullable ResourceLoader resourceLoader) {

   Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
   this.registry = registry;

   if (useDefaultFilters) {
      registerDefaultFilters();
   }
   setEnvironment(environment);
   setResourceLoader(resourceLoader);
}

二:註冊配置類

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
   this();
   register(annotatedClasses);
   refresh();
}
public void register(Class<?>... annotatedClasses) {
   Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
   this.reader.register(annotatedClasses);
}
public void register(Class<?>... annotatedClasses) {
   for (Class<?> annotatedClass : annotatedClasses) {
      registerBean(annotatedClass);
   }
}

public void registerBean(Class<?> annotatedClass) {
   doRegisterBean(annotatedClass, null, null, null);
}

<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
      @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

   AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);//建立BeanDefinition對象
   if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {    //處理 @Condition註解
      return;
   }

   abd.setInstanceSupplier(instanceSupplier); //設置對象是單例模式仍是多例模式,默認單例
   ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
   abd.setScope(scopeMetadata.getScopeName());    //獲取BeanName,設置的化就採用默認值,不然類名第一個字母小寫
   String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

   AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); //處理Lazy,primary等註解
   .....

   BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
   definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);//判斷對象是否須要代理,不須要直接返回,須要的化,從新建立BeanDefinition加入代理的信息
   BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);    //註冊配置類到IOC容器
}

擴展功能

進入 refresh()方法,能夠說refresh函數中包括了幾乎ApplicationContext中提供的所有功能,並且此函數中邏輯很是清晰明瞭。post

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
   this();
   register(annotatedClasses);
   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();//初始化BeanFacgtory

      // Prepare the bean factory for use in this context.
      prepareBeanFactory(beanFactory);//初始化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);//激活各類BeanFactory處理器

         // Register bean processors that intercept bean creation.
         registerBeanPostProcessors(beanFactory);//註冊攔截Bean建立的Bean處理器,這裏只是註冊,真正的調用是在getBean的時候

         // Initialize message source for this context.
         initMessageSource();//爲上下文初始化Message源,集不一樣語言的消息體,國際化處理

         // Initialize event multicaster for this context.
         initApplicationEventMulticaster();//初始化應用消息廣播器,並放入applicationEventMulticaster bean中

         // Initialize other special beans in specific context subclasses.
         onRefresh();//留給子類來初始化其它的Bean

         // Check for listener beans and register them.
         registerListeners();//在全部註冊的Bean中查找Listener bean,註冊到消息廣播器中

         // Instantiate all remaining (non-lazy-init) singletons.
         finishBeanFactoryInitialization(beanFactory);//初始化剩下的單實例(非惰性)

         // Last step: publish corresponding event.
         finishRefresh();//完成刷新過程,通知生命週期處理器 LifecycleProcessor刷新過程,同時發出 ContextRefreshedEvent 通知別人
      }

      catch (BeansException ex) {
       
         // Destroy already created singletons to avoid dangling resources.
         destroyBeans();//銷燬Bean

         // Reset 'active' flag.
         cancelRefresh(ex);//更改活躍狀態

         // Propagate exception to caller.
         throw ex;
      }
   }
}

準備刷新上下文環境

prepareRefresh();函數主要做用是對系統屬性及環境變量的初始化及驗證測試

/**
 * Prepare this context for refreshing, setting its startup date and
 * active flag as well as performing any initialization of property sources.
 */
protected void prepareRefresh() {
   this.startupDate = System.currentTimeMillis();
   this.closed.set(false);
   this.active.set(true);

   if (logger.isInfoEnabled()) {
      logger.info("Refreshing " + this);
   }

   // Initialize any placeholder property sources in the context environment
   initPropertySources();//留給子類覆蓋

   // Validate that all properties marked as required are resolvable
   // see ConfigurablePropertyResolver#setRequiredProperties
   getEnvironment().validateRequiredProperties();//驗證須要的屬性文件是否都已經放入環境中去了

   // Allow for the collection of early ApplicationEvents,
   // to be published once the multicaster is available...
   this.earlyApplicationEvents = new LinkedHashSet<>();
}

initPropertySources是空的,沒有任何邏輯處理, 而getEnvironment().validateRequiredProperties()也是由於沒有須要驗證的屬性而沒有作任何處理,然而這兩個方法做用仍是很大的。那麼該怎麼用呢?

1.initPropertySources正符合Spring的開放式結構設計,給用戶最大的擴展Spring的能力。

2.validateRequiredProperties則是對屬性進行驗證,那麼如何驗證呢?咱們舉個例子來講明下:

public class MyAnnotationConfigApplication extends AnnotationConfigApplicationContext {
    public MyAnnotationConfigApplication(Class<?>... annotatedClasses){
        super(annotatedClasses);
    }
    @Override
    protected void initPropertySources(){
        //添加驗證要求
        getEnvironment().setRequiredProperties("VAR");
    }
}

咱們自定義了繼承自AnnotationConfigApplicationContext的MyAnnotationConfigApplication,並重寫了initPropertySources方法,在方法中添加了咱們的個性化需求,那麼在驗證的時候也就是程序走到

validateRequiredProperties()代碼的時候,咱們還須要替換掉原有的AnnotationConfigApplicationContext爲咱們自定義的MyAnnotationConfigApplication。

public class Test002 {
    public static void main(String[] args) {
       ApplicationContext context = new MyAnnotationConfigApplication(MyConfig.class);
       Object payEntity = context.getBean("payEntity");
       System.out.println(payEntity);
    }
}

若是系統並無檢測到對應的VAR環境變量,那麼就會拋出異常:

初始化BeanFacgtory

obtainFreshBeanFactory()方法的做用是:通過這個方法,ApplicationContext就已經擁有了BeanFactory的所有功能。

/**
 * Tell the subclass to refresh the internal bean factory.
 * @return the fresh BeanFactory instance
 * @see #refreshBeanFactory()
 * @see #getBeanFactory()
 */
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    //初始化BeanFactory
   refreshBeanFactory();
    //返回當前實體的BeanFactory屬性
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   if (logger.isDebugEnabled()) {
      logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
   }
   return beanFactory;
}

方法中將核心實現委託給了refreshBeanFactory:

/**
 * This implementation performs an actual refresh of this context's underlying
 * bean factory, shutting down the previous bean factory (if any) and
 * initializing a fresh bean factory for the next phase of the context's lifecycle.
 */
@Override
protected final void refreshBeanFactory() throws BeansException {
   if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
   }
   try {
      DefaultListableBeanFactory beanFactory = createBeanFactory();//建立DefaultListableBeanFactory 
      beanFactory.setSerializationId(getId());//序列化id
      customizeBeanFactory(beanFactory);//定製BeanFactory,設置相關屬性,是否容許循環依賴,是否容許覆蓋
      loadBeanDefinitions(beanFactory);//加載BeanDefinition
      synchronized (this.beanFactoryMonitor) {
         this.beanFactory = beanFactory;
      }
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}

1.定製BeanFactory

protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
    //若是屬性不爲空,則設置給beanFactory對象相應屬性,此屬性的含義是:是否容許覆蓋同名稱的不一樣定義的對象
   if (this.allowBeanDefinitionOverriding != null) {
      beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
   }
    //若是屬性不爲空,設置給beanFactory對象相應的屬性,這塊屬性的含義是:是否容許Bean之間存在循環依賴
   if (this.allowCircularReferences != null) {
      beanFactory.setAllowCircularReferences(this.allowCircularReferences);
   }
}

對於容許覆蓋和容許循環依賴的設置這裏只是進行了非空判斷,若是不爲空的化要進行設置,可是這裏沒有設置,因此仍是那個套路,使用子類覆蓋方法。

public class MyAnnotationConfigApplication extends AnnotationConfigApplicationContext {
    public MyAnnotationConfigApplication(Class<?>... annotatedClasses){
        super(annotatedClasses);
    }
    protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory){
        super.setAllowBeanDefinitionOverriding(false);//是否容許覆蓋同名稱的不一樣定義的對象
        super.setAllowCircularReferences(false);//是否容許Bean之間存在循環依賴
    }
}

2.加載BeanDefinition

/**
 * Loads the bean definitions via an XmlBeanDefinitionReader.
 * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
 * @see #initBeanDefinitionReader
 * @see #loadBeanDefinitions
 */
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
   // Create a new XmlBeanDefinitionReader for the given BeanFactory.
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);//爲指定的beanFactory建立XmlBeanDefinitionReader

   // Configure the bean definition reader with this context's
   // resource loading environment.
   beanDefinitionReader.setEnvironment(this.getEnvironment());//對beanDefinitionReader進行環境變量的設置
   beanDefinitionReader.setResourceLoader(this);
   beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

   // Allow a subclass to provide custom initialization of the reader,
   // then proceed with actually loading the bean definitions.
   initBeanDefinitionReader(beanDefinitionReader);//進行設置能夠覆蓋
   loadBeanDefinitions(beanDefinitionReader);
}

在初始化了DefaultListableBeanFactoryXmlBeanDefinitionReader後就能夠進行配置文件的讀取了

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
   Resource[] configResources = getConfigResources();
   if (configResources != null) {
      reader.loadBeanDefinitions(configResources);
   }
   String[] configLocations = getConfigLocations();
   if (configLocations != null) {
      reader.loadBeanDefinitions(configLocations);
   }
}
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
   Assert.notNull(resources, "Resource array must not be null");
   int counter = 0;
   for (Resource resource : resources) {
      counter += loadBeanDefinitions(resource);
   }
   return counter;
}

通過此步驟,類型DefaultListableBeanFactory的變量beanFactory已經包含了全部已經解析好的配置

功能擴展

進入函數prepareBeanFactory前,Spring已經完成了對配置的解析,而ApplicationContext在功能上的擴展也由此展開。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   // Tell the internal bean factory to use the context's class loader etc.
   beanFactory.setBeanClassLoader(getClassLoader());//設置BeanFactory的classLoader爲當前context的classLoader
   beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));//設置beanFactory的表達式語言處理器,默承認以使用#{bean.xx}的形式來調用相關的屬性值。
   beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));//爲BeanFactory增長了一個默認的propertyEditor,這個主要是對bean的屬性等設置管理的一個工具

   // Configure the bean factory with context callbacks.
   beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));//添加BeanPostProcessor     //設置了幾個忽略自定裝配的接口
   beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
   beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
   beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
   beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

    //設置了幾個自定裝配的規則
   beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
   beanFactory.registerResolvableDependency(ResourceLoader.class, this);
   beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
   beanFactory.registerResolvableDependency(ApplicationContext.class, this);

   // Register early post-processor for detecting inner beans as ApplicationListeners.
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

   // 增長了對AspectJ的支持
   if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      // Set a temporary ClassLoader for type matching.
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }

   // 添加了默認的系統環境bean
   if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
   }
   if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
      beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
   }
   if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
   }
}

上面函數中主要進行了幾個方面的擴展

  • 增長了對SpEL語言的支持
  • 增長對屬性編輯器的支持
  • 增長了對一些內置類,好比實現了Aware接口的類信息注入
  • 設置了依賴功能可忽略接口
  • 註冊一些固定依賴的屬性
  • 增長了AspectJ的支持,後面再去分析
  • 將相關環境變量及屬性註冊以單例模式註冊

上面可擴展功能不少,我就不一一介紹了,下面咱們來挑幾個咱們感興趣的函數來分析下:

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)),其主要目的就是註冊個BeanPostProcessor,而真正的邏輯仍是在ApplicationContextAwareProcessor中

ApplicationContextAwareProcessor實現了BeanPostProcessor接口,咱們回顧下以前講解的內容,在Bean實例化的時候,也就是Spring激活Bean的init-method方法先後,

會調用BeanPostProcessor的postProcessBeforeInitializationpostProcessAfterInitialization方法。因此咱們也就去看看ApplicationContextAwareProcessor對這兩個方法的實現。

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
   return bean;
}

對於後置處理器BeanPostProcessor的後置處理方法中並無作任何邏輯處理,那麼咱們轉向後置處理器的前置處理

public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
   AccessControlContext acc = null;

   if (System.getSecurityManager() != null &&
         (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
               bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
               bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
      acc = this.applicationContext.getBeanFactory().getAccessControlContext();
   }

   if (acc != null) {
      AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
         invokeAwareInterfaces(bean);
         return null;
      }, acc);
   }
   else {
      invokeAwareInterfaces(bean);
   }

   return bean;
}
private void invokeAwareInterfaces(Object bean) {
   if (bean instanceof Aware) {
      if (bean instanceof EnvironmentAware) {
         ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
      }
      if (bean instanceof EmbeddedValueResolverAware) {
         ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
      }
      if (bean instanceof ResourceLoaderAware) {
         ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
      }
      if (bean instanceof ApplicationEventPublisherAware) {
         ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
      }
      if (bean instanceof MessageSourceAware) {
         ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
      }
      if (bean instanceof ApplicationContextAware) {
         ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
      }
   }
}

postProcessBeforeInitialization方法中調用了invokeAwareInterfaces。從invokeAwareInterfaces方法中,咱們或許已經差很少知道了Spring的用意,實現了這些Aware接口的Bean在被初始化後,能夠取到一些對於的資源。

示例:

@Component
public class MyApplicationContext implements ApplicationContextAware {
    /**
     * spring底層中爲何可以實現ApplicationContextAware接口 就可以拿到ApplicationContext
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("applicationContext:>>>>"+applicationContext);
    }
}

BeanFactory的後處理

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()));
   }
}

註冊BeanPostProcessor

咱們自定義MyInstantiationAwareBeanPostProcessor實現BeanPostProcessor 接口

@Component
public class MyInstantiationAwareBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization....");
        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization....");
        return null;
    }
}
@Import(MyInstantiationAwareBeanPostProcessor.class)

結果輸出:每次初始化一個Bean就會在以前和以後處理一些自定義邏輯

postProcessBeforeInitialization....
4.bean init方法執行..
postProcessAfterInitialization....

初始化ApplicationEventMulticaster

/**
 * Initialize the ApplicationEventMulticaster.
 * Uses SimpleApplicationEventMulticaster if none defined in the context.
 * @see org.springframework.context.event.SimpleApplicationEventMulticaster
 */
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 + "]");
      }
   }
}

進入SimpleApplicationEventMulticaster找到這段代碼:

public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
   ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
   for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
      Executor executor = getTaskExecutor();
      if (executor != null) {
         executor.execute(() -> invokeListener(listener, event));
      }
      else {
         invokeListener(listener, event);
      }
   }
}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
   ErrorHandler errorHandler = getErrorHandler();
   if (errorHandler != null) {
      try {
         doInvokeListener(listener, event);
      }
      catch (Throwable err) {
         errorHandler.handleError(err);
      }
   }
   else {
      doInvokeListener(listener, event);
   }
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
        ....
      listener.onApplicationEvent(event);
}

能夠推斷,當產生Spring事件的時候會默認使用SimpleApplicationEventMulticastermulticastEvent來廣播事件遍歷全部監聽器,並使用監聽器中的onApplicationEvent方法來進行監聽事件的處理。

而對於每一個監聽器來講其實均可以獲取到產生的事件,可是是否進行處理則由事件監聽器來決定。

註冊監聽器

進入registerListeners函數,開始註冊監聽器:

protected void registerListeners() {

   for (ApplicationListener<?> listener : getApplicationListeners()) {//硬編碼方式註冊的監聽器處理
      getApplicationEventMulticaster().addApplicationListener(listener);
   }

   String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);//配置文件註冊的監聽器處理
   for (String listenerBeanName : listenerBeanNames) {
      getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
   }
   Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
   this.earlyApplicationEvents = null;
   if (earlyEventsToProcess != null) {
      for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
         getApplicationEventMulticaster().multicastEvent(earlyEvent);
      }
   }
}

Application下抽象子類ApplicationContextEvent的下面有4個已經實現好的事件 

  • ContextClosedEvent(容器關閉時) 
  • ContextRefreshedEvent(容器刷新時) 
  • ContextStartedEvent(容器啓動時候) 
  • ContextStoppedEvent(容器中止的時候) 

一樣,這四個事件都繼承了ApplicationEvent,若是咱們想自定義事件,也能夠經過繼承ApplicationEvent來實現 

使用示例:

1.定義監聽事件

public class TestEvent extends ApplicationEvent {
    private String msg;
    public TestEvent(Object source){
        super(source);
    }
    public TestEvent(Object source,String msg){
        super(source);
        this.msg=msg;
    }
    public void print(){
        System.out.println(msg);
    }
}

2.定義監聽器

public class TestListener implements ApplicationListener {
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof TestEvent){
            TestEvent testEvent= (TestEvent)event;
            testEvent.print();
        }
    }
}

注入容器

@Import(TestListener.class)

測試:

public class Test001 {

    public static void main(String[] args) {
        /**
         * IOC容器初始化單例對象都是循環遍歷調用getBean方法
         */
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        TestEvent testEvent = new TestEvent("hello", "hello word");
        applicationContext.publishEvent(testEvent);
    }
}

輸出結果:

咱們在補充一個註解形式的例子:

public class TestEvent extends ApplicationEvent {

    private String msg;
    public TestEvent(Object source){
        super(source);
    }
    public TestEvent(Object source,String msg){
        super(source);
        this.msg=msg;
    }
    public void print(){
        System.out.println("註冊監聽器..,TestEvent....");
    }
}
@Component
public class MyAnnotationListener {

   @EventListener
    public String listener1(TestEvent event) {
        if (event instanceof TestEvent){
            TestEvent testEvent=event;
            testEvent.print();
        }
        return "xd";
    }
}
@Import(MyAnnotationListener.class)
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
MyAnnotationListener myAnnotationListener = new MyAnnotationListener();
applicationContext.publishEvent(myAnnotationListener.listener1(new TestEvent("jj")));

輸出:

初始化非延遲加載單例

進入finishBeanFactoryInitialization函數初始化全部非懶加載Bean

/**
 * Finish the initialization of this context's bean factory,
 * initializing all remaining singleton beans.
 */
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {

   if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
         beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
      beanFactory.setConversionService(//定義轉換器從String轉爲Date的方式,能夠本身擴展,我就很少說了
            beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
   }
   if (!beanFactory.hasEmbeddedValueResolver()) {
      beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
   }
   String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
   for (String weaverAwareName : weaverAwareNames) {
      getBean(weaverAwareName);
   }
   beanFactory.setTempClassLoader(null);

   // Allow for caching all bean definition metadata, not expecting further changes.
   beanFactory.freezeConfiguration();//凍結全部Bean的定義,說明註冊的Bean定義將不被修改或處理。

   // Instantiate all remaining (non-lazy-init) singletons.
   beanFactory.preInstantiateSingletons();//初始化剩下的單實例(非惰性)
}

凍結配置

@Override
public void freezeConfiguration() {
   this.configurationFrozen = true;
   this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);

初始化非延遲加載

ApplicationContext實現的默認行爲就是在啓動時將全部單例bean提早進行實例化。提早實例化的好處是,在配置中任何錯誤就會當即被發現Z(不然的化,一旦出錯,排除bug至關困難)。

public void preInstantiateSingletons() throws BeansException {
   if (this.logger.isDebugEnabled()) {
      this.logger.debug("Pre-instantiating singletons in " + this);
   }

   // Iterate over a copy to allow for init methods which in turn register new bean definitions.
   // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
   List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

   // Trigger initialization of all non-lazy singleton beans...
   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((PrivilegedAction<Boolean>) () ->
                     ((SmartFactoryBean<?>) factory).isEagerInit(),
                     getAccessControlContext());
            }
            else {
               isEagerInit = (factory instanceof SmartFactoryBean &&
                     ((SmartFactoryBean<?>) factory).isEagerInit());
            }
            if (isEagerInit) {
               getBean(beanName);
            }
         }
         else {
            getBean(beanName);
         }
      }
   }

finishRefresh

在Spring中還提供了Lifecycle接口,Lifecycle接口中包含start/stop方法,實現此接口後Spring會保證在啓動的時候調用其start方法開始生命週期,而且在spring關閉的時候調用stop方法來結束生命週期,

一般用來配置後臺程序,在啓動後一直運行(such as MQ進行輪詢等)。

/**
 * Finish the refresh of this context, invoking the LifecycleProcessor's
 * onRefresh() method and publishing the
 * {@link org.springframework.context.event.ContextRefreshedEvent}.
 */
protected void finishRefresh() {
   // Clear context-level resource caches (such as ASM metadata from scanning).
   clearResourceCaches();

   // Initialize lifecycle processor for this context.
   initLifecycleProcessor();//當ApplicationContext啓動或者中止時,會經過LifecycleProcessor來與全部聲明的bean的週期作狀態更新,而在LifecycleProcessor使用前須要初始化

   // Propagate refresh to lifecycle processor first.
   getLifecycleProcessor().onRefresh();//啓動全部實現了Lifecycle接口的bean

   // Publish the final event.
   publishEvent(new ContextRefreshedEvent(this));//當完成ApplicationContext初始化的時候,要經過Spring中的事件發佈機制來發出ContextRefreshedEvent監聽事件,以保證對應的監聽器能夠作進一步的邏輯處理

   // Participate in LiveBeansView MBean, if active.
   LiveBeansView.registerApplicationContext(this);
}

到這裏,咱們就談完了!!!

參考書籍:Spring源碼深度解析

參考連接:http://www.mayikt.com

版權全部:https://my.oschina.net/u/3995125,禁止轉載

相關文章
相關標籤/搜索