refresh方法是整个Spring容器的核心,其体现了Spring容器的工作流程

refresh方法中调用了13个子方法完成整个工作流程

@Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// 1、Prepare this context for refreshing.prepareRefresh();// 2、Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// /3、Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// 4、Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);// 5、Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// 6、Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);// 7、Initialize message source for this context.initMessageSource();// 8、Initialize event multicaster for this context.initApplicationEventMulticaster();// 9、Initialize other special beans in specific context subclasses.onRefresh();// 10、Check for listener beans and register them.registerListeners();// 11、Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// 12、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// 13、might not ever need metadata for singleton beans anymore...resetCommonCaches();}}}

4、Bean工厂后置处理器

两种Bean工厂后置处理器:

  1. BeanFactoryPostProcessor
  2. BeanDefinitionRegistryPostProcessor(BeanFactoryPostProcessor的子类)

问题来了:
1、这个两个后置处理器有什么作用?
2、Spring Framwork 中这两个后置处理器实现有哪些?作用是什么?
3、其他框架中有应用案例么?比如SpringBoot、Spring Cloud中是如何使用的这个后置处理器的?
4、如何自定义BeanFactoryPostProcessor?Spring是如何实例化自定义的后置处理器?

问题1:两个后置处理器有什么作用

我们看看这两个接口的定义,然后尝试简略回答一下第一个问题,待我们解析完后面的几个问题,我们就会对第一个问题有更深入的理解了。

public interface BeanFactoryPostProcessor {/*** 作用:在标准初始化之后修改应用程序上下文的内部bean工厂。* 调用时机:所有bean定义都已加载,但还没有实例化bean。这允许覆盖或添加属性,甚至可以在快速初始化bean中。* @param beanFactory 应用上下文的bean工厂*/void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {/*** 作用:在标准初始化之后修改应用程序上下文的内部bean定义注册表。* 调用时机:所有常规bean定义都已加载,但还没有实例化bean。也就是说在下一个“后置处理阶段”前添加更多的bean定义。* @param registry bean定义的注册表*/void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;}

这两个接口中各有一个方法定义,我们翻译了一下源码中的注释,但看注释还是有几个问题?

❓1.1、什么叫标准初始化?
所谓标准初始化其实就是创建Bean对象,了解JVM的同学知道,Java字节码中构造方法的命名就是/(静态),构造方法中就是解析对象的初始化工作。

❓1.2、什么场景下需要我“覆盖或添加属性”?

❓1.3、什么场景下需要我“添加更多的bean定义”?

问题2:Spring 中内置的后置处理器

2.1、Spring Framwork中的后置处理器

最重要的一个就是 ConfigurationClassPostProcessor,其不仅实现了 BeanDefinitionRegistryPostProcessor 接口,还实现了 PriorityOrdered 接口。

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {// 略...processConfigBeanDefinitions(registry);}public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();String[] candidateNames = registry.getBeanDefinitionNames();// org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration// org.springframework.cloud.bootstrap.encrypt.EncryptionBootstrapConfiguration// org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration// org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration// org.springframework.cloud.config.client.ConfigServiceBootstrapConfiguration// 上面的这个几个类都是标注了@Configuration的类,上面的类什么时候注册进来的呢?for (String beanName : candidateNames) {BeanDefinition beanDef = registry.getBeanDefinition(beanName);if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {if (logger.isDebugEnabled()) {logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);}}else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));}}// Return immediately if no @Configuration classes were foundif (configCandidates.isEmpty()) {return;}// Sort by previously determined @Order value, if applicableCollections.sort(configCandidates, new Comparator<BeanDefinitionHolder>() {@Overridepublic int compare(BeanDefinitionHolder bd1, BeanDefinitionHolder bd2) {int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;}});// Detect any custom bean name generation strategy supplied through the enclosing application contextSingletonBeanRegistry sbr = null;if (registry instanceof SingletonBeanRegistry) {sbr = (SingletonBeanRegistry) registry;if (!this.localBeanNameGeneratorSet && sbr.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {// 正常不走这里,好像需要自定义BeanName的生成器才会走这里BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);this.componentScanBeanNameGenerator = generator;this.importBeanNameGenerator = generator;}}// Parse each @Configuration classConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment,this.resourceLoader, this.componentScanBeanNameGenerator, registry);Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());do {parser.parse(candidates);parser.validate();Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(parser.getConfigurationClasses());configClasses.removeAll(alreadyParsed);// Read the model and create bean definitions based on its contentif (this.reader == null) {this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment,this.importBeanNameGenerator, parser.getImportRegistry());}this.reader.loadBeanDefinitions(configClasses);alreadyParsed.addAll(configClasses);candidates.clear();if (registry.getBeanDefinitionCount() > candidateNames.length) {String[] newCandidateNames = registry.getBeanDefinitionNames();Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames));Set<String> alreadyParsedClasses = new HashSet<String>();for (ConfigurationClass configurationClass : alreadyParsed) {alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());}for (String candidateName : newCandidateNames) {if (!oldCandidateNames.contains(candidateName)) {BeanDefinition bd = registry.getBeanDefinition(candidateName);if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory)&&!alreadyParsedClasses.contains(bd.getBeanClassName())) {candidates.add(new BeanDefinitionHolder(bd, candidateName));}}}candidateNames = newCandidateNames;}}while (!candidates.isEmpty());// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classesif (sbr != null) {if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());}}if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();}}
}

❓ 1、为什么会调用两次?

第一次调用栈:
processConfigBeanDefinitions:275, ConfigurationClassPostProcessor (org.springframework.context.annotation)
postProcessBeanDefinitionRegistry:228, ConfigurationClassPostProcessor (org.springframework.context.annotation)
invokeBeanDefinitionRegistryPostProcessors:272, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:92, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:687, AbstractApplicationContext (org.springframework.context.support)
refresh:525, AbstractApplicationContext (org.springframework.context.support)
refresh:693, SpringApplication (org.springframework.boot)
refreshContext:360, SpringApplication (org.springframework.boot)
run:303, SpringApplication (org.springframework.boot)
run:134, SpringApplicationBuilder (org.springframework.boot.builder)
bootstrapServiceContext:187, BootstrapApplicationListener (org.springframework.cloud.bootstrap)
onApplicationEvent:102, BootstrapApplicationListener (org.springframework.cloud.bootstrap)
onApplicationEvent:68, BootstrapApplicationListener (org.springframework.cloud.bootstrap)
doInvokeListener:172, SimpleApplicationEventMulticaster (org.springframework.context.event)
invokeListener:165, SimpleApplicationEventMulticaster (org.springframework.context.event)
multicastEvent:139, SimpleApplicationEventMulticaster (org.springframework.context.event)
multicastEvent:122, SimpleApplicationEventMulticaster (org.springframework.context.event)
environmentPrepared:74, EventPublishingRunListener (org.springframework.boot.context.event)
environmentPrepared:54, SpringApplicationRunListeners (org.springframework.boot)
prepareEnvironment:325, SpringApplication (org.springframework.boot)
run:296, SpringApplication (org.springframework.boot)
run:1118, SpringApplication (org.springframework.boot)
run:1107, SpringApplication (org.springframework.boot)
main:16, AppBMain (com.yh.stu)
第二次调用栈:
processConfigBeanDefinitions:275, ConfigurationClassPostProcessor (org.springframework.context.annotation)
postProcessBeanDefinitionRegistry:228, ConfigurationClassPostProcessor (org.springframework.context.annotation)
invokeBeanDefinitionRegistryPostProcessors:272, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:92, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:687, AbstractApplicationContext (org.springframework.context.support)
refresh:525, AbstractApplicationContext (org.springframework.context.support)
refresh:122, EmbeddedWebApplicationContext (org.springframework.boot.context.embedded)
refresh:693, SpringApplication (org.springframework.boot)
refreshContext:360, SpringApplication (org.springframework.boot)
run:303, SpringApplication (org.springframework.boot)
run:1118, SpringApplication (org.springframework.boot)
run:1107, SpringApplication (org.springframework.boot)
main:16, AppBMain (com.yh.stu)

❓ 2、String[] candidateNames = registry.getBeanDefinitionNames(),candidateNames 哪来的?

1、SpringFramework 创建上下文
创建 AnnotationConfigApplicationContext 实例,在其构造方法中实例化AnnotatedBeanDefinitionReader ,其他构造方法中调用registerAnnotationConfigProcessors方法,方法中硬编码注册了一些BeanDefinition

registerBeanDefinition:861, DefaultListableBeanFactory (o.s.beans.factory.support)
registerBeanDefinition:315, GenericApplicationContext (o.s.context.support)
registerPostProcessor:218, AnnotationConfigUtils (o.s.context.annotation)
registerAnnotationConfigProcessors:163, AnnotationConfigUtils (o.s.context.annotation)
// AnnotatedBeanDefinitionReader 构造方法中调用registerAnnotationConfigProcessors
registerAnnotationConfigProcessors:134, AnnotationConfigUtils (o.s.context.annotation)
<init>:83, AnnotatedBeanDefinitionReader (o.s.context.annotation)
<init>:66, AnnotatedBeanDefinitionReader (o.s.context.annotation) // 创建 AnnotatedBeanDefinitionReader
<init>:61, AnnotationConfigApplicationContext (o.s.context.annotation)
newInstance0:-1, NativeConstructorAccessorImpl (sun.reflect)
newInstance:62, NativeConstructorAccessorImpl (sun.reflect)
newInstance:45, DelegatingConstructorAccessorImpl (sun.reflect)
newInstance:423, Constructor (java.lang.reflect)
newInstance:442, Class (java.lang)
instantiate:77, BeanUtils (o.s.beans)
createApplicationContext:529, SpringApplication (o.s.boot) // 创建ApplicationContext
run:299, SpringApplication (o.s.boot)
------------------------------------------------------------------------------
run:134, SpringApplicationBuilder (o.s.boot.builder)
bootstrapServiceContext:187, BootstrapApplicationListener (o.s.cloud.bootstrap)
onApplicationEvent:102, BootstrapApplicationListener (o.s.cloud.bootstrap)
onApplicationEvent:68, BootstrapApplicationListener (o.s.cloud.bootstrap)
doInvokeListener:172, SimpleApplicationEventMulticaster (o.s.context.event)
invokeListener:165, SimpleApplicationEventMulticaster (o.s.context.event)
multicastEvent:139, SimpleApplicationEventMulticaster (o.s.context.event)
multicastEvent:122, SimpleApplicationEventMulticaster (o.s.context.event)
environmentPrepared:74, EventPublishingRunListener (o.s.boot.context.event)
environmentPrepared:54, SpringApplicationRunListeners (o.s.boot)
prepareEnvironment:325, SpringApplication (o.s.boot)
run:296, SpringApplication (o.s.boot)
run:1118, SpringApplication (o.s.boot)
run:1107, SpringApplication (o.s.boot)
main:16, AppBMain (com.yh.stu)

2、Spring Boot run方法的prepareContext阶段

registerBeanDefinition:861, DefaultListableBeanFactory (o.s.beans.factory.support)
registerBeanDefinition:315, GenericApplicationContext (o.s.context.support)
registerBeanDefinition:149, BeanDefinitionReaderUtils (o.s.beans.factory.support)
registerBean:192, AnnotatedBeanDefinitionReader (o.s.context.annotation)
registerBean:142, AnnotatedBeanDefinitionReader (o.s.context.annotation)
register:131, AnnotatedBeanDefinitionReader (o.s.context.annotation)
load:159, BeanDefinitionLoader (o.s.boot)
load:135, BeanDefinitionLoader (o.s.boot)
load:127, BeanDefinitionLoader (o.s.boot)// 这个方法中 this.sources 有多个值
load:635, SpringApplication (o.s.boot)
prepareContext:355, SpringApplication (o.s.boot)
run:301, SpringApplication (o.s.boot)
------------------------------------------------------------------------------
同上

SpringApplication.sources从哪来?
1、主启动类

public static ConfigurableApplicationContext run(Object[] sources, String[] args) {return new SpringApplication(sources).run(args);
}
public SpringApplication(Object... sources) {initialize(sources);
}
private void initialize(Object[] sources) {if (sources != null && sources.length > 0) {this.sources.addAll(Arrays.asList(sources));}......
}
initialize:246, SpringApplication (org.springframework.boot)
<init>:225, SpringApplication (org.springframework.boot)
run:1118, SpringApplication (org.springframework.boot)
run:1107, SpringApplication (org.springframework.boot)
main:16, AppBMain (com.yh.stu)

2、

//org.springframework.cloud.bootstrap.BootstrapApplicationListener#bootstrapServiceContext
private ConfigurableApplicationContext bootstrapServiceContext(ConfigurableEnvironment environment, final SpringApplication application,String configName) {.......List<String> names = SpringFactoriesLoader.loadFactoryNames(BootstrapConfiguration.class, classLoader);for (String name : StringUtils.commaDelimitedListToStringArray(environment.getProperty("spring.cloud.bootstrap.sources", ""))) {names.add(name);}.......List<Class<?>> sources = new ArrayList<>();for (String name : names) {Class<?> cls = ClassUtils.resolveClassName(name, null);try {cls.getDeclaredAnnotations();}catch (Exception e) {continue;}sources.add(cls);}AnnotationAwareOrderComparator.sort(sources);builder.sources(sources.toArray(new Class[sources.size()]));.......return context;
}bootstrapServiceContext:183, BootstrapApplicationListener (org.springframework.cloud.bootstrap)
onApplicationEvent:102, BootstrapApplicationListener (org.springframework.cloud.bootstrap)
onApplicationEvent:68, BootstrapApplicationListener (org.springframework.cloud.bootstrap)
doInvokeListener:172, SimpleApplicationEventMulticaster (org.springframework.context.event)
invokeListener:165, SimpleApplicationEventMulticaster (org.springframework.context.event)
multicastEvent:139, SimpleApplicationEventMulticaster (org.springframework.context.event)
multicastEvent:122, SimpleApplicationEventMulticaster (org.springframework.context.event)
environmentPrepared:74, EventPublishingRunListener (org.springframework.boot.context.event)
environmentPrepared:54, SpringApplicationRunListeners (org.springframework.boot)
prepareEnvironment:325, SpringApplication (org.springframework.boot)
run:296, SpringApplication (org.springframework.boot)
run:1118, SpringApplication (org.springframework.boot)
run:1107, SpringApplication (org.springframework.boot)
main:16, AppBMain (com.yh.stu)

2.2、Spring Boot中的后置处理器

beanFactoryPostProcessors = {ArrayList@2894} size = 3
0 = {ConfigurationWarningsApplicationContextInitializerKaTeX parse error: Expected 'EOF', got '}' at position 40: …tProcessor@2893}̲ 1 = {SharedM…CachingMetadataReaderFactoryPostProcessor@2970}
2 = {ConfigFileApplicationListener$PropertySourceOrderingPostProcessor@3150}

这三个都是通过

问题3:其他框架中的应用案例

3.1、Spring Boot中的应用案例1:

// org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer#initialize
@Override
public void initialize(ConfigurableApplicationContext context) {context.addBeanFactoryPostProcessor(new ConfigurationWarningsPostProcessor(getChecks()));
}

调用栈:

addBeanFactoryPostProcessor:478, AbstractApplicationContext (o.s.context.support)
initialize:60, ConfigurationWarningsApplicationContextInitializer (o.s.boot.context)
applyInitializers:567, SpringApplication (o.s.boot)
prepareContext:338, SpringApplication (o.s.boot)
run:301, SpringApplication (o.s.boot)
run:134, SpringApplicationBuilder (o.s.boot.builder)
....
main:13, AppBMain (com.yh.stu)

在Spring Boot 容器的prepareContext方法中 (该方法在refresh方法前调用),会调用所有实现了ApplicationContextInitializer接口的类的对象的initialize 方法,其中ConfigurationWarningsApplicationContextInitializer 类的对象

1、ApplicationContextInitializer这些对象实例从哪里来?
我们从上面的调用栈中找到调用各个ApplicationContextInitializer的方法,看方法名 applyInitializers 就是我们要找的。点进去看一下

protected void applyInitializers(ConfigurableApplicationContext context) {for (ApplicationContextInitializer initializer : getInitializers()) {Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(), ApplicationContextInitializer.class);Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");initializer.initialize(context);}
}

我们看到所用的 ApplicationContextInitializer 实例都是通过 getInitializers()方法得到的,点进该方法

private List<ApplicationContextInitializer<?>> initializers;
public Set<ApplicationContextInitializer<?>> getInitializers() {return asUnmodifiableOrderedSet(this.initializers);
}

看方法体我们目标,initializers已经存在了,那么我们找找哪些地方给其赋值的,然后打上断点,我们通过搜索(Found Usages )找到setInitializers 方法:

public void setInitializers(Collection<? extends ApplicationContextInitializer<?>> initializers) {this.initializers = new ArrayList<ApplicationContextInitializer<?>>();this.initializers.addAll(initializers);
}

看方法体initializers是参数传过来的,在通过搜索(Found Usages )找到 initialize方法:

private void initialize(Object[] sources) {if (sources != null && sources.length > 0) {this.sources.addAll(Arrays.asList(sources));}this.webEnvironment = deduceWebEnvironment();setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));this.mainApplicationClass = deduceMainApplicationClass();
}

我们发现initializers是通过 getSpringFactoriesInstances方法获取的(从调用的参数发现,这个是个通用的方法,根据不同的class返回不同类型实例的Collection)。

追踪该方法 getSpringFactoriesInstances:

private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,Class<?>[] parameterTypes, Object... args) {ClassLoader classLoader = Thread.currentThread().getContextClassLoader();// Use names and ensure unique to protect against duplicatesSet<String> names = new LinkedHashSet<String>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));List<T> instances = createSpringFactoriesInstances(type, parameterTypes,classLoader, args, names);AnnotationAwareOrderComparator.sort(instances);return instances;
}

看方法名 loadFactoryNames 和其参数 ,我们猜测这个就是加载ApplicationContextInitializer类型的类的名称的。

看方法名 createSpringFactoriesInstances 和其参数和返回值,我们推测这个方法是创建ApplicationContextInitializer类型的类的实例的。

我们再来看看loadFactoryNames(..) 方法:

// org.springframework.core.io.support.SpringFactoriesLoader
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {String factoryClassName = factoryClass.getName();try {// 拿到classpath下的META-INF/spring.factories文件Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));// 1、spring-boot-1.5.13.RELEASE.jar!/META-INF/spring.factories// 2、spring-cloud-context-1.3.3.RELEASE.jar!/META-INF/spring.factoriesList<String> result = new ArrayList<String>();while (urls.hasMoreElements()) {URL url = urls.nextElement();Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));String factoryClassNames = properties.getProperty(factoryClassName);result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));}return result;}catch (IOException ex) {throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +"] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);}
}

该方法就是从classpath 下,加载所有的 “META-INF/spring.factories” 文件,然后将 spring.factories 解析成 Properties 并从中选出指定类型的类的名称

3.2、Spring Boot中的应用案例2:

//o.s.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {applicationContext.addBeanFactoryPostProcessor(new CachingMetadataReaderFactoryPostProcessor());
}//o.s.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer.CachingMetadataReaderFactoryPostProcessor
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)throws BeansException {register(registry);configureConfigurationClassPostProcessor(registry);
}
private void configureConfigurationClassPostProcessor(BeanDefinitionRegistry registry) {try {//"org.springframework.context.annotation.internalConfigurationAnnotationProcessor"BeanDefinition definition = registry.getBeanDefinition(AnnotationConfigUtils.CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME);definition.getPropertyValues().add("metadataReaderFactory",new RuntimeBeanReference(BEAN_NAME));}catch (NoSuchBeanDefinitionException ex) {}
}

2、AbstractApplicationContext的refresh功能概述相关推荐

  1. 4.1.1 网络层功能概述

    网络层 4.1.1 网络层功能概述

  2. 3.1 数据链路层功能概述

    3.1 数据链路层功能概述

  3. 计算机控制zos,第二章zOS操作系统的功能概述2.1zOS的内存管理.PDF

    第二章zOS操作系统的功能概述2.1zOS的内存管理.PDF 第二章 z/OS 操作系统的功能概述 2.1 z/OS 的内存管理 与其它平台不同的是,主机系统里,storage 指的是内存的概念,而不 ...

  4. 5.1 计算机网络之传输层(传输层提供的服务及功能概述、端口、套接字--Socket、无连接UDP和面向连接TCP服务)

    文章目录 1.传输层提供的服务及功能概述 2.传输层的寻址与端口 (1)端口的作用 (2)端口号的分类 (3)套接字 3.无连接UDP和面向连接TCP服务 1.传输层提供的服务及功能概述 传输层的功能 ...

  5. 3.1.1 计算机网络之数据链路的基本概念和功能概述

    文章目录 1.基本概念 2.功能概述 1.基本概念 2.功能概述 因为物理层可能会把数据弄丢,所以数据链路层需要进行一些设置来使得物理层可以可靠的传输数据

  6. java概述_Java 7功能概述

    java概述 前面我们讨论了所有未纳入Java 7的内容,然后回顾了将其纳入Java的有用的Fork / Join框架 . 今天的帖子将带我们了解Project Coin的每个功能-一系列小的语言增强 ...

  7. Java 7功能概述

    前面我们讨论了所有未纳入Java 7的内容,然后回顾了将其纳入Java 7的有用的Fork / Join框架 . 今天的帖子将带我们了解Project Coin的每个功能-一系列小的语言增强功能,这些 ...

  8. 【计算机网络复习 数据链路层】3.1 数据链路层功能概述

    数据链路层功能概述 一.数据链路层基本概念 二.数据链路层功能概述 一.数据链路层基本概念 结点: 主机.路由器 链路: 网络钟两个结点之间的物理通道,链路的传输介质主要有双绞线.光纤和微波.分为有线 ...

  9. 3.1.1 计算机网络之数据链路的基本概念和功能概述(转载)

    原文链接:https://blog.csdn.net/weixin_43914604/article/details/104778017 本博客为个人学习.研究或者欣赏用,如有侵权,请与我联系删除,谢 ...

最新文章

  1. 设置腾讯云linux服务器中 MySQL 允许远程访问
  2. yum配置代理,通过CCProxy有线网络安装软件
  3. 在centos上搭建svn服务器
  4. mybatis-plus代码生成器使用和代码
  5. matlab文件目录表示,Matlab - 文件目录路径操作_读取不同路径下的相同文件名表格...
  6. 牛客小白月赛18-记录
  7. 国内手机产业混乱:产业一窝蜂 企业捞快钱
  8. 计算机主机机箱面板辐射,电脑机箱如何防辐射----给大家科普一下
  9. Leetcode每日一题:26.remove-duplicates-from-sorted-array(删除排序数组中的重复项)
  10. Linux命令----系统目录结构
  11. thinkpad电源管理解决办法 win2019
  12. Kotlinx.serialization VS Gson
  13. 深度学习工作站装机指南
  14. Leetcode| 216. 组合总和III、17. 电话号码的字母组合 Day25
  15. 使用Portia时docker-compose失败 /bin/sh: 1: /app/provision.sh: Permission denied
  16. 游戏防封技术是学易语言还是学c,易语言写游戏脚本防封执行sqlplus 之后没执行...
  17. 当前流行的智能硬件产品整理
  18. java调用oracle过程,JAVA调用ORACLE存储过程报错
  19. QT for WinCE
  20. 无惧浩瀚数据 超云XS5000集群存储为扩展而生

热门文章

  1. redis3.0 java spring_Redis-3.0.6 集群部署集成SpringJava工程-----环境搭建
  2. php7 runkit,runkit - PHP 7 中文文档
  3. 2019蓝桥杯Java决赛题答案_2019-01-15 第八届蓝桥杯javaB组第二题
  4. Python中的@classmethod修饰符
  5. java 面向对象 重载_Java方法重载
  6. kettle执行组件时为什么使用克隆对象
  7. MySQL优化SQL性能问题
  8. mysql 引擎 类型_MySQL(一)之存储引擎类型
  9. androidstudio 评论栏_android-studio 添加没有菜单栏和actionBar的模板
  10. JDK8的LocalDateTime用法