2、AbstractApplicationContext的refresh功能概述

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

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

@Override
	public 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 found
		if (configCandidates.isEmpty()) {
			return;
		}

		// Sort by previously determined @Order value, if applicable
		Collections.sort(configCandidates, new Comparator<BeanDefinitionHolder>() {
			@Override
			public 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 context
		SingletonBeanRegistry 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 class
		ConfigurationClassParser 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 content
			if (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 classes
		if (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 duplicates
	Set<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.factories
		List<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) {
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java硕哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值