Spring – BeanFactoryAware扩展接口

文章目录

Spring - BeanFactoryAware扩展接口

; Pre

Spring Boot – 扩展接口一览

Spring - BeanFactoryAware扩展接口

; org.springframework.beans.factory.BeanFactoryAware

package org.springframework.beans.factory;

import org.springframework.beans.BeansException;

public interface BeanFactoryAware extends Aware {

    void setBeanFactory(BeanFactory beanFactory) throws BeansException;

}

Spring - BeanFactoryAware扩展接口

扩展点说明

扩展点方法为 setBeanFactory,可以拿到 BeanFactory这个属性。

使用场景:可以在bean实例化之后,但还未初始化之前,拿到 BeanFactory,在这个时候,可以对每个bean进行特殊化的定制。也或者可以把 BeanFactory拿到进行缓存,日后使用。

Aware接口

  • Spring core 和 context的内建Aware接口
ApplicationEventPublisherAware
MessageSourceAware
ResourceLoaderAware
BeanFactoryAware
EnvironmentAware
EmbeddedValueResolverAware
ImportAware
LoadTimeWeaverAware
BeanClassLoaderAware
BeanNameAware
ApplicationContextAware
  • Spring web内建的Aware接口
ServletContextAware
ServletConfigAware
  • Spring其它内建Aware接口
SchedulerContextAware (spring scheduling)
NotificationPublisherAware (spring jmx export)
BootstrapContextAware (spring jca)

Spring内建Aware接口的执行时机及顺序

Aware接口的执行时机肯定是在Spring Bean创建的时候。

对于Aware接口的执行实现主要有一下两种模式

  • 初始化Bean( initializeBean)的时候直接进行方法调用 -> setXXXX
  • BeanPostProcessor -> Object postProcessBeforeInitialization(Object bean, String beanName)

Spring - BeanFactoryAware扩展接口
processor.postProcessBeforeInitialization(result, beanName);

进入到

Spring内置的核心Aware BeanPostProcessor是ApplicationContextAwareProcessor

org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization

Spring - BeanFactoryAware扩展接口

我们继续看下 invokeAwareInterfaces(bean);

Spring - BeanFactoryAware扩展接口

可知ApplicationContextAwareProcessor关联了大部分Spring内置Aware接口,它们的执行顺序如下:

EnvironmentAware -> EmbeddedValueResolverAware -> ResourceLoaderAware -> ApplicationEventPublisherAware -> MessageSourceAware ->   ApplicationStartupAware -> ApplicationContextAware

结论: 直接方法调用的时机要早于通过 BeanPostProcessor#postProcessBeforeInitialization调用的时机

由于Aware的接口的调用受到 BeanPostProcessor的直接影响,因此 BeanPostProcessor的执行顺序也就是Aware接口的调用顺序。

那刚才为啥直接跳到了 ApplicationContextAwareProcessor

我们看看可以看看ApplicationContextAwareProcessor的设置执行时机

AbstractApplicationContext#refresh方法

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {

            prepareRefresh();

            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            prepareBeanFactory(beanFactory);

}

继续看 prepareBeanFactory

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {

        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

}

可以看到 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)这里可以看到 ApplicationContextAwareProcessor直接第一个加入到该 BeanFactory中。

源码解析 (直接调用)

org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors()
    BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        org.springframework.beans.factory.support.AbstractBeanFactory#getBean
          org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
              org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
                    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

doCreateBean方法中

重点看


        Object exposedObject = bean;
        try {
            populateBean(beanName, mbd, instanceWrapper);
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }

进入 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean

if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        }
        else {
            invokeAwareMethods(beanName, bean);
        }

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods
private void invokeAwareMethods(String beanName, Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware) bean).setBeanName(beanName);
            }
            if (bean instanceof BeanClassLoaderAware) {
                ClassLoader bcl = getBeanClassLoader();
                if (bcl != null) {
                    ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
                }
            }
            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
            }
        }
    }

看到了吧

if (bean instanceof BeanFactoryAware) {
        ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}

由以上代码片段可以得出结论:Aware接口执行顺序是

 BeanNameAware -> BeanClassLoaderAware -> BeanFactoryAware

调用链如下

org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors()
    BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        org.springframework.beans.factory.support.AbstractBeanFactory#getBean
          org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
              org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
                    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
                         org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean
                                org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods

源码分析 (BeanPostProcessor调用执行顺序)

其实上面最开始的截图里已经有了,我们再看下

org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors()
    BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        org.springframework.beans.factory.support.AbstractBeanFactory#getBean
          org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
              org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
                    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
                         org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean

继续 initializeBean


Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
  wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
  throws BeansException {

  Object result = existingBean;
  for (BeanPostProcessor processor : getBeanPostProcessors()) {
    Object current = processor.postProcessBeforeInitialization(result, beanName);
    if (current == null) {
      return result;
    }
    result = current;
  }
  return result;
}

public List<BeanPostProcessor> getBeanPostProcessors() {
  return this.beanPostProcessors;
}

private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();

可知 beanPostProcessors是关联该 BeanFactory的有序列表, 这个列表的数据来源就是 ConfigurableBeanFactory#addBeanPostProcessor(BeanPostProcessor beanPostProcessor) 这个方法。

回到 AbstractApplicationContext#refresh()中的

registerBeanPostProcessors(beanFactory);

注册 BeanPostProcessor的最终执行者是 PostProcessorRegistrationDelegate.registerBeanPostProcessors

这其中的排序规则如下(针对于属于该 BeanFactoryBeanPostProcessor BeanDefinition):

String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
  • 实现了PriorityOrdered接口优先级最高, 再按order进行排序 小 -> 大
  • 其次是实现了Ordered接口, 再按order进行排序 小 -> 大
  • 其它的根据BeanDefinition Spring注册顺序来

当然还可以通过 BeanFactoryPostProcessor来配置该BeanFactory, 举个例子 ConfigurationClassPostProcessor

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
  int factoryId = System.identityHashCode(beanFactory);
  if (this.factoriesPostProcessed.contains(factoryId)) {
    throw new IllegalStateException(
      "postProcessBeanFactory already called on this post-processor against " + beanFactory);
  }
  this.factoriesPostProcessed.add(factoryId);
  if (!this.registriesPostProcessed.contains(factoryId)) {

    processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
  }

  enhanceConfigurationClasses(beanFactory);

  beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}

private static class ImportAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {

    ....

  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) {
    if (bean instanceof ImportAware) {
      ImportRegistry ir = this.beanFactory.getBean(IMPORT_REGISTRY_BEAN_NAME, ImportRegistry.class);
      AnnotationMetadata importingClass = ir.getImportingClassFor(ClassUtils.getUserClass(bean).getName());
      if (importingClass != null) {

        ((ImportAware) bean).setImportMetadata(importingClass);
      }
    }
    return bean;
  }
}

由以上可知 ImportAware执行顺序 ApplicationContextAwareProcessor关联的那些Aware接口之后执行。

其实还有一个 LoadTimeWeaverAwareProcessor

AbstractApplicationContext#prepareBeanFactory

if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
  beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));

  beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}

Spring - BeanFactoryAware扩展接口

目前的Aware接口执行顺序如下:

BeanNameAware -> BeanClassLoaderAware -> BeanFactoryAware -> EnvironmentAware -> EmbeddedValueResolverAware -> ResourceLoaderAware -> ApplicationEventPublisherAware -> MessageSourceAware -> ApplicationContextAware -> ImportAware -> LoadTimeWeaverAware

扩展点示例

package com.artisan.bootspringextend.testextends;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.context.annotation.Configuration;

@Slf4j
@Configuration
public class ExtendBeanFactoryAware implements BeanFactoryAware {
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        log.info("----->ExtendBeanFactoryAware  {}" , beanFactory.getBean(ExtendBeanFactoryAware.class).getClass().getSimpleName());
    }
}

再看第二个比较全的扩展

 package com.artisan.bootspringextend.testextends;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.*;
import org.springframework.context.annotation.ImportAware;
import org.springframework.context.weaving.LoadTimeWeaverAware;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.metrics.ApplicationStartup;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.instrument.classloading.LoadTimeWeaver;
import org.springframework.stereotype.Component;
import org.springframework.util.StringValueResolver;

@Slf4j
@Component
public class ExtendInvokeAware implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, EnvironmentAware, EmbeddedValueResolverAware,
        ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware,ApplicationStartupAware, ApplicationContextAware, ImportAware,
        LoadTimeWeaverAware {

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        log.info(" ------> BeanClassLoaderAware::setBeanClassLoader invoked");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        log.info(" ------> BeanFactoryAware::setBeanFactory invoked");
    }

    @Override
    public void setBeanName(String s) {
        log.info(" ------> BeanNameAware::setBeanName invoked");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        log.info(" ------> ApplicationContextAware::setApplicationContext invoked");
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        log.info(" ------> ApplicationEventPublisherAware::setApplicationEventPublisher invoked");
    }

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        log.info(" ------> EmbeddedValueResolverAware::setEmbeddedValueResolver invoked");
    }

    @Override
    public void setEnvironment(Environment environment) {
        log.info(" ------> EnvironmentAware::setEnvironment invoked");
    }

    @Override
    public void setMessageSource(MessageSource messageSource) {
        log.info(" ------> MessageSourceAware::setMessageSource invoked");
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        log.info(" ------> ResourceLoaderAware::setResourceLoader invoked");
    }

    @Override
    public void setApplicationStartup(ApplicationStartup applicationStartup) {
        log.info(" ------> ApplicationStartup::setApplicationStartup invoked");
    }

    @Override
    public void setImportMetadata(AnnotationMetadata importMetadata) {
        log.info(" ------> ImportAware::setImportMetadata invoked");
    }

    @Override
    public void setLoadTimeWeaver(LoadTimeWeaver loadTimeWeaver) {
        log.info(" ------> LoadTimeWeaverAware::setLoadTimeWeaver invoked");
    }

}

输出结果

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.4.2)

2022-12-04 19:14:25.103  INFO 12832 --- [           main] .b.t.ExtendApplicationContextInitializer : ExtendApplicationContextInitializer # initialize  Called
2022-12-04 19:14:25.110  INFO 12832 --- [           main] c.a.b.BootSpringExtendApplication        : Starting BootSpringExtendApplication using Java 1.8.0_261 on LAPTOP-JF3RBRRJ with PID 12832 (D:\IdeaProjects\boot2\boot-spring-extend\target\classes started by artisan in D:\IdeaProjects\boot2)
2022-12-04 19:14:25.111  INFO 12832 --- [           main] c.a.b.BootSpringExtendApplication        : No active profile set, falling back to default profiles: default
2022-12-04 19:14:25.444  INFO 12832 --- [           main] c.a.b.testextends.ExtendInvokeAware      :  ------> BeanNameAware::setBeanName invoked
2022-12-04 19:14:25.444  INFO 12832 --- [           main] c.a.b.testextends.ExtendInvokeAware      :  ------> BeanClassLoaderAware::setBeanClassLoader invoked
2022-12-04 19:14:25.444  INFO 12832 --- [           main] c.a.b.testextends.ExtendInvokeAware      :  ------> BeanFactoryAware::setBeanFactory invoked
2022-12-04 19:14:25.444  INFO 12832 --- [           main] c.a.b.testextends.ExtendInvokeAware      :  ------> EnvironmentAware::setEnvironment invoked
2022-12-04 19:14:25.444  INFO 12832 --- [           main] c.a.b.testextends.ExtendInvokeAware      :  ------> EmbeddedValueResolverAware::setEmbeddedValueResolver invoked
2022-12-04 19:14:25.444  INFO 12832 --- [           main] c.a.b.testextends.ExtendInvokeAware      :  ------> ResourceLoaderAware::setResourceLoader invoked
2022-12-04 19:14:25.444  INFO 12832 --- [           main] c.a.b.testextends.ExtendInvokeAware      :  ------> ApplicationEventPublisherAware::setApplicationEventPublisher invoked
2022-12-04 19:14:25.444  INFO 12832 --- [           main] c.a.b.testextends.ExtendInvokeAware      :  ------> MessageSourceAware::setMessageSource invoked
2022-12-04 19:14:25.444  INFO 12832 --- [           main] c.a.b.testextends.ExtendInvokeAware      :  ------> ApplicationStartup::setApplicationStartup invoked
2022-12-04 19:14:25.444  INFO 12832 --- [           main] c.a.b.testextends.ExtendInvokeAware      :  ------> ApplicationContextAware::setApplicationContext invoked
2022-12-04 19:14:25.529  INFO 12832 --- [           main] c.a.b.BootSpringExtendApplication        : Started BootSpringExtendApplication in 0.747 seconds (JVM running for 1.792)

Process finished with exit code 0

Spring - BeanFactoryAware扩展接口

Original: https://blog.csdn.net/yangshangwei/article/details/128169160
Author: 小小工匠
Title: Spring – BeanFactoryAware扩展接口

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/724060/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球