Add application startup metrics support
This commit adds a new `StartupStep` interface and its factory `ApplicationStartup`. Such steps are created, tagged with metadata and thir execution time can be recorded - in order to collect metrics about the application startup. The default implementation is a "no-op" variant and has no side-effect. Other implementations can record and collect events in a dedicated metrics system or profiling tools. We provide here an implementation for recording and storing steps with Java Flight Recorder. This commit also instruments the Spring application context to gather metrics about various phases of the application context, such as: * context refresh phase * bean definition registry post-processing * bean factory post-processing * beans instantiation and post-processing Third part libraries involved in the Spring application context can reuse the same infrastructure to record similar metrics. Closes gh-24878
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context;
|
||||
|
||||
import org.springframework.beans.factory.Aware;
|
||||
import org.springframework.beans.metrics.ApplicationStartup;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by any object that wishes to be notified
|
||||
* of the {@link ApplicationStartup} that it runs with.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @since 5.3.0
|
||||
* @see ApplicationContextAware
|
||||
*/
|
||||
public interface ApplicationStartupAware extends Aware {
|
||||
|
||||
/**
|
||||
* Set the ApplicationStartup that this object runs with.
|
||||
* <p>Invoked after population of normal bean properties but before an init
|
||||
* callback like InitializingBean's afterPropertiesSet or a custom init-method.
|
||||
* Invoked before ApplicationContextAware's setApplicationContext.
|
||||
* @param applicationStartup application startup to be used by this object
|
||||
*/
|
||||
void setApplicationStartup(ApplicationStartup applicationStartup);
|
||||
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import java.io.Closeable;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.metrics.ApplicationStartup;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.ProtocolResolver;
|
||||
@@ -87,6 +88,12 @@ public interface ConfigurableApplicationContext extends ApplicationContext, Life
|
||||
*/
|
||||
String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";
|
||||
|
||||
/**
|
||||
* Name of the {@link ApplicationStartup} bean in the factory.
|
||||
* @since 5.3.0
|
||||
*/
|
||||
String APPLICATION_STARTUP_BEAN_NAME = "applicationStartup";
|
||||
|
||||
/**
|
||||
* {@link Thread#getName() Name} of the {@linkplain #registerShutdownHook()
|
||||
* shutdown hook} thread: {@value}.
|
||||
@@ -127,6 +134,21 @@ public interface ConfigurableApplicationContext extends ApplicationContext, Life
|
||||
@Override
|
||||
ConfigurableEnvironment getEnvironment();
|
||||
|
||||
/**
|
||||
* Set the {@link ApplicationStartup} for this application context.
|
||||
* <p>This allows the application context to record metrics
|
||||
* during startup.
|
||||
* @param applicationStartup the new context event factory
|
||||
* @since 5.3.0
|
||||
*/
|
||||
void setApplicationStartup(ApplicationStartup applicationStartup);
|
||||
|
||||
/**
|
||||
* Return the {@link ApplicationStartup} for this application context.
|
||||
* @since 5.3.0
|
||||
*/
|
||||
ApplicationStartup getApplicationStartup();
|
||||
|
||||
/**
|
||||
* Add a new BeanFactoryPostProcessor that will get applied to the internal
|
||||
* bean factory of this application context on refresh, before any of the
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinitionCustomizer;
|
||||
import org.springframework.beans.factory.support.BeanNameGenerator;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.metrics.StartupStep;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -63,7 +65,9 @@ public class AnnotationConfigApplicationContext extends GenericApplicationContex
|
||||
* through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
|
||||
*/
|
||||
public AnnotationConfigApplicationContext() {
|
||||
StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
|
||||
this.reader = new AnnotatedBeanDefinitionReader(this);
|
||||
createAnnotatedBeanDefReader.end();
|
||||
this.scanner = new ClassPathBeanDefinitionScanner(this);
|
||||
}
|
||||
|
||||
@@ -159,7 +163,10 @@ public class AnnotationConfigApplicationContext extends GenericApplicationContex
|
||||
@Override
|
||||
public void register(Class<?>... componentClasses) {
|
||||
Assert.notEmpty(componentClasses, "At least one component class must be specified");
|
||||
StartupStep registerComponentClass = this.getApplicationStartup().start("spring.context.component-classes.register")
|
||||
.tag("classes", () -> Arrays.toString(componentClasses));
|
||||
this.reader.register(componentClasses);
|
||||
registerComponentClass.end();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,7 +180,10 @@ public class AnnotationConfigApplicationContext extends GenericApplicationContex
|
||||
@Override
|
||||
public void scan(String... basePackages) {
|
||||
Assert.notEmpty(basePackages, "At least one base package must be specified");
|
||||
StartupStep scanPackages = this.getApplicationStartup().start("spring.context.base-packages.scan")
|
||||
.tag("packages", () -> Arrays.toString(basePackages));
|
||||
this.scanner.scan(basePackages);
|
||||
scanPackages.end();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -48,6 +48,9 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
|
||||
import org.springframework.beans.factory.support.BeanNameGenerator;
|
||||
import org.springframework.beans.metrics.ApplicationStartup;
|
||||
import org.springframework.beans.metrics.StartupStep;
|
||||
import org.springframework.context.ApplicationStartupAware;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.context.annotation.ConfigurationClassEnhancer.EnhancedConfiguration;
|
||||
@@ -84,7 +87,7 @@ import org.springframework.util.ClassUtils;
|
||||
* @since 3.0
|
||||
*/
|
||||
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
|
||||
PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
|
||||
PriorityOrdered, ResourceLoaderAware, ApplicationStartupAware, BeanClassLoaderAware, EnvironmentAware {
|
||||
|
||||
/**
|
||||
* A {@code BeanNameGenerator} using fully qualified class names as default bean names.
|
||||
@@ -142,6 +145,8 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
/* Using fully qualified class names as default bean names by default. */
|
||||
private BeanNameGenerator importBeanNameGenerator = IMPORT_BEAN_NAME_GENERATOR;
|
||||
|
||||
private ApplicationStartup applicationStartup = ApplicationStartup.getDefault();
|
||||
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
@@ -223,6 +228,10 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationStartup(ApplicationStartup applicationStartup) {
|
||||
this.applicationStartup = applicationStartup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Derive further bean definitions from the configuration classes in the registry.
|
||||
@@ -323,6 +332,7 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
|
||||
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
|
||||
do {
|
||||
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
|
||||
parser.parse(candidates);
|
||||
parser.validate();
|
||||
|
||||
@@ -337,6 +347,7 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
}
|
||||
this.reader.loadBeanDefinitions(configClasses);
|
||||
alreadyParsed.addAll(configClasses);
|
||||
processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
|
||||
|
||||
candidates.clear();
|
||||
if (registry.getBeanDefinitionCount() > candidateNames.length) {
|
||||
@@ -379,6 +390,7 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
* @see ConfigurationClassEnhancer
|
||||
*/
|
||||
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
|
||||
StartupStep enhanceConfigClasses = this.applicationStartup.start("spring.context.config-classes.enhance");
|
||||
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
|
||||
for (String beanName : beanFactory.getBeanDefinitionNames()) {
|
||||
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
|
||||
@@ -417,6 +429,7 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
}
|
||||
if (configBeanDefs.isEmpty()) {
|
||||
// nothing to enhance -> return immediately
|
||||
enhanceConfigClasses.end();
|
||||
return;
|
||||
}
|
||||
if (IN_NATIVE_IMAGE) {
|
||||
@@ -439,6 +452,7 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
beanDef.setBeanClass(enhancedClass);
|
||||
}
|
||||
}
|
||||
enhanceConfigClasses.tag("classCount", () -> String.valueOf(configBeanDefs.keySet().size())).end();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,6 +22,8 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.metrics.ApplicationStartup;
|
||||
import org.springframework.beans.metrics.StartupStep;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.core.ResolvableType;
|
||||
@@ -44,6 +46,7 @@ import org.springframework.util.ErrorHandler;
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Stephane Nicoll
|
||||
* @author Brian Clozel
|
||||
* @see #setTaskExecutor
|
||||
*/
|
||||
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
|
||||
@@ -54,6 +57,9 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM
|
||||
@Nullable
|
||||
private ErrorHandler errorHandler;
|
||||
|
||||
@Nullable
|
||||
private ApplicationStartup applicationStartup;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new SimpleApplicationEventMulticaster.
|
||||
@@ -121,6 +127,21 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM
|
||||
return this.errorHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ApplicationStartup} to track event listener invocations during startup.
|
||||
* @since 5.3
|
||||
*/
|
||||
public void setApplicationStartup(@Nullable ApplicationStartup applicationStartup) {
|
||||
this.applicationStartup = applicationStartup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current application startup for this multicaster.
|
||||
*/
|
||||
@Nullable
|
||||
public ApplicationStartup getApplicationStartup() {
|
||||
return this.applicationStartup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void multicastEvent(ApplicationEvent event) {
|
||||
@@ -135,6 +156,16 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM
|
||||
if (executor != null) {
|
||||
executor.execute(() -> invokeListener(listener, event));
|
||||
}
|
||||
else if (this.applicationStartup != null) {
|
||||
StartupStep invocationStep = this.applicationStartup.start("spring.event.invoke-listener");
|
||||
invokeListener(listener, event);
|
||||
invocationStep.tag("event", event::toString);
|
||||
if (eventType != null) {
|
||||
invocationStep.tag("eventType", eventType::toString);
|
||||
}
|
||||
invocationStep.tag("listener", listener::toString);
|
||||
invocationStep.end();
|
||||
}
|
||||
else {
|
||||
invokeListener(listener, event);
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.metrics.ApplicationStartup;
|
||||
import org.springframework.beans.metrics.StartupStep;
|
||||
import org.springframework.beans.support.ResourceEditorRegistrar;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
@@ -119,6 +121,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
* @author Stephane Nicoll
|
||||
* @author Sam Brannen
|
||||
* @author Sebastien Deleuze
|
||||
* @author Brian Clozel
|
||||
* @since January 21, 2001
|
||||
* @see #refreshBeanFactory
|
||||
* @see #getBeanFactory
|
||||
@@ -227,6 +230,9 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
@Nullable
|
||||
private ApplicationEventMulticaster applicationEventMulticaster;
|
||||
|
||||
/** Application startup metrics. **/
|
||||
private ApplicationStartup applicationStartup = ApplicationStartup.getDefault();
|
||||
|
||||
/** Statically specified listeners. */
|
||||
private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
|
||||
|
||||
@@ -444,6 +450,17 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
return this.applicationEventMulticaster;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationStartup(ApplicationStartup applicationStartup) {
|
||||
Assert.notNull(applicationStartup, "applicationStartup should not be null");
|
||||
this.applicationStartup = applicationStartup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApplicationStartup getApplicationStartup() {
|
||||
return this.applicationStartup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the internal LifecycleProcessor used by the context.
|
||||
* @return the internal LifecycleProcessor (never {@code null})
|
||||
@@ -532,6 +549,8 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
@Override
|
||||
public void refresh() throws BeansException, IllegalStateException {
|
||||
synchronized (this.startupShutdownMonitor) {
|
||||
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
|
||||
|
||||
// Prepare this context for refreshing.
|
||||
prepareRefresh();
|
||||
|
||||
@@ -545,11 +564,13 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
// Allows post-processing of the bean factory in context subclasses.
|
||||
postProcessBeanFactory(beanFactory);
|
||||
|
||||
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
|
||||
// Invoke factory processors registered as beans in the context.
|
||||
invokeBeanFactoryPostProcessors(beanFactory);
|
||||
|
||||
// Register bean processors that intercept bean creation.
|
||||
registerBeanPostProcessors(beanFactory);
|
||||
beanPostProcess.end();
|
||||
|
||||
// Initialize message source for this context.
|
||||
initMessageSource();
|
||||
@@ -590,6 +611,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
// Reset common introspection caches in Spring's core, since we
|
||||
// might not ever need metadata for singleton beans anymore...
|
||||
resetCommonCaches();
|
||||
contextRefresh.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -676,6 +698,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
|
||||
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
|
||||
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
|
||||
beanFactory.ignoreDependencyInterface(ApplicationStartup.class);
|
||||
|
||||
// BeanFactory interface not registered as resolvable type in a plain factory.
|
||||
// MessageSource registered (and found for autowiring) as a bean.
|
||||
@@ -704,6 +727,9 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
|
||||
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
|
||||
}
|
||||
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
|
||||
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -789,7 +815,9 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
|
||||
SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
|
||||
simpleApplicationEventMulticaster.setApplicationStartup(getApplicationStartup());
|
||||
this.applicationEventMulticaster = simpleApplicationEventMulticaster;
|
||||
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,6 +25,7 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.beans.factory.config.EmbeddedValueResolver;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.context.ApplicationStartupAware;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.EmbeddedValueResolverAware;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
@@ -80,7 +81,8 @@ class ApplicationContextAwareProcessor implements BeanPostProcessor {
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
|
||||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
|
||||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
|
||||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
|
||||
bean instanceof ApplicationStartupAware)) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
@@ -119,6 +121,9 @@ class ApplicationContextAwareProcessor implements BeanPostProcessor {
|
||||
if (bean instanceof MessageSourceAware) {
|
||||
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
|
||||
}
|
||||
if (bean instanceof ApplicationStartupAware) {
|
||||
((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
|
||||
}
|
||||
if (bean instanceof ApplicationContextAware) {
|
||||
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -266,6 +266,7 @@ public class GenericApplicationContext extends AbstractApplicationContext implem
|
||||
throw new IllegalStateException(
|
||||
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
|
||||
}
|
||||
this.beanFactory.setApplicationStartup(this.getApplicationStartup());
|
||||
this.beanFactory.setSerializationId(getId());
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProce
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.metrics.ApplicationStartup;
|
||||
import org.springframework.beans.metrics.StartupStep;
|
||||
import org.springframework.core.OrderComparator;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.PriorityOrdered;
|
||||
@@ -94,7 +96,7 @@ final class PostProcessorRegistrationDelegate {
|
||||
}
|
||||
sortPostProcessors(currentRegistryProcessors, beanFactory);
|
||||
registryProcessors.addAll(currentRegistryProcessors);
|
||||
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
|
||||
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
|
||||
currentRegistryProcessors.clear();
|
||||
|
||||
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
|
||||
@@ -107,7 +109,7 @@ final class PostProcessorRegistrationDelegate {
|
||||
}
|
||||
sortPostProcessors(currentRegistryProcessors, beanFactory);
|
||||
registryProcessors.addAll(currentRegistryProcessors);
|
||||
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
|
||||
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
|
||||
currentRegistryProcessors.clear();
|
||||
|
||||
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
|
||||
@@ -124,7 +126,7 @@ final class PostProcessorRegistrationDelegate {
|
||||
}
|
||||
sortPostProcessors(currentRegistryProcessors, beanFactory);
|
||||
registryProcessors.addAll(currentRegistryProcessors);
|
||||
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
|
||||
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
|
||||
currentRegistryProcessors.clear();
|
||||
}
|
||||
|
||||
@@ -275,10 +277,13 @@ final class PostProcessorRegistrationDelegate {
|
||||
* Invoke the given BeanDefinitionRegistryPostProcessor beans.
|
||||
*/
|
||||
private static void invokeBeanDefinitionRegistryPostProcessors(
|
||||
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
|
||||
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {
|
||||
|
||||
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
|
||||
StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
|
||||
.tag("postProcessor", postProcessor::toString);
|
||||
postProcessor.postProcessBeanDefinitionRegistry(registry);
|
||||
postProcessBeanDefRegistry.end();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,7 +294,10 @@ final class PostProcessorRegistrationDelegate {
|
||||
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
|
||||
|
||||
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
|
||||
StartupStep postProcessBeanFactory = beanFactory.getApplicationStartup().start("spring.context.bean-factory.post-process")
|
||||
.tag("postProcessor", postProcessor::toString);
|
||||
postProcessor.postProcessBeanFactory(beanFactory);
|
||||
postProcessBeanFactory.end();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user