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工厂后置处理器:
- BeanFactoryPostProcessor
- 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) {
}
}