本文为博主原创,转载请注明出处:
@Configuration 注解对我们来说并不陌生,以javaConfig的方式定义spring IOC容器的配置类使用的就是这个@Configuration.
spring boot 社区推荐使用基于JavaConfig 的配置方式来定义Bean,其可以认为是一个spring IOC 容器的配置类。
指示一个类声明一个或多个@Bean方法,并且可以由Spring容器处理,以便在运行时为这些bean生成BeanDefinition和服务请求
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class TestConfiguration {
* 初始化spring -restTemplate
* @return restTemplate
@Bean
public RestTemplate getRestTemplate(){
System.out.println("获取bean ing");
return new RestTemplate();
public TestConfiguration() {
System.out.println("TestConfiguration容器启动初始化。。。");
@Configuration 注解的工作过程与 ClassXmlPathApplicationContext 的工作过程相同,@Configuration 是通过注解的方式将 bean 注入到spring IOC容器。
ClassXmlPathApplicationContext 是通过xml配置文件,在项目启动加载xml 配置文件时,将其中的bean 标签解析为bena 并注入到 IOC 容器中。
通过 @Configuration 注解的配置类会通过 AnnotationConfigApplicationContext 类进行扫描,并构建扫描 bean ,并注册到spring IoC容器中。
可以通过以下测试方法,看到上面代码中的bean 初始化并调用相关过程的打印:
import com.example.test.config.TestConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.web.client.RestTemplate;
public class ConfigurationBeanTest {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);
RestTemplate restTemplate = (RestTemplate) context.getBean("getRestTemplate");
String url = "https://www.baidu.com/?tn=62095104_19_oem_dg";
String result = restTemplate.getForObject(url,String.class);
System.out.println(result);
上面test运行并进行正常的 http 请求,可以打印出相关的控制台日志如下:
可以查看下 AnnotationConfigApplicationContext 类的相关实现,该类的继承结构通过idea 查看如下:
其中主要涉及到的类和接口如下:
GenericApplicationContext
——通用应用上下文,内部持有一个DefaultListableBeanFactory
实例,这个类实现了BeanDefinitionRegistry
接口,可以在它身上使用任意的bean definition读取器。典型的使用案例是:通过BeanFactoryRegistry
接口注册bean definitions,然后调用refresh()
方法来初始化那些带有应用上下文语义(org.springframework.context.ApplicationContextAware
)的bean,自动探测org.springframework.beans.factory.config.BeanFactoryPostProcessor
等。关于这两个接口,在介绍bean的生命周期时进行详细讲解。
BeanDefinitionRegistry
——用于持有像RootBeanDefinition
和 ChildBeanDefinition
实例的bean definitions的注册表接口。DefaultListableBeanFactory
实现了这个接口,因此可以通过相应的方法向beanFactory
里面注册bean。GenericApplicationContext
内置一个DefaultListableBeanFactory
实例,它对这个接口的实现实际上是通过调用这个实例的相应方法实现的。
AbstractApplicationContext
——ApplicationContext
接口的抽象实现,没有强制规定配置的存储类型,仅仅实现了通用的上下文功能。这个实现用到了模板方法设计模式,需要具体的子类来实现其抽象方法。自动通过registerBeanPostProcessors()
方法注册BeanFactoryPostProcessor
, BeanPostProcessor
和ApplicationListener
的实例用来探测bean factory里的特殊bean——对比1分析
AnnotationConfigRegistry
——注解配置注册表。用于注解配置应用上下文的通用接口,拥有一个注册配置类和扫描配置类的方法。
AnnotationConfigApplicationContext 类的源码如下:
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
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.context.support.GenericApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.metrics.StartupStep;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
private final AnnotatedBeanDefinitionReader reader;
private final ClassPathBeanDefinitionScanner scanner;
// 无参数的构造器,在application 启动的时候初始化一个读取器与扫描器
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);
// 构造一个 bean 工厂的有参构造,并包含了读取器和扫描器
public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
super(beanFactory);
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
// 手动指定注解类
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
this.register(componentClasses);
this.refresh();
// 通过指定的包名进行自动的扫描并刷新
public AnnotationConfigApplicationContext(String... basePackages) {
this();
this.scan(basePackages);
this.refresh();
public void setEnvironment(ConfigurableEnvironment environment) {
super.setEnvironment(environment);
this.reader.setEnvironment(environment);
this.scanner.setEnvironment(environment);
public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
this.reader.setBeanNameGenerator(beanNameGenerator);
this.scanner.setBeanNameGenerator(beanNameGenerator);
this.getBeanFactory().registerSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator", beanNameGenerator);
public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) {
this.reader.setScopeMetadataResolver(scopeMetadataResolver);
this.scanner.setScopeMetadataResolver(scopeMetadataResolver);
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", () -> {
return Arrays.toString(componentClasses);
this.reader.register(componentClasses);
registerComponentClass.end();
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", () -> {
return Arrays.toString(basePackages);
this.scanner.scan(basePackages);
scanPackages.end();
public <T> void registerBean(@Nullable String beanName, Class<T> beanClass, @Nullable Supplier<T> supplier, BeanDefinitionCustomizer... customizers) {
this.reader.registerBean(beanClass, beanName, supplier, customizers);
Spring将被@Configuration注解的配置类定义为full configuration, 而将没有被@Configuration注解的配置类定义为lite configuration。full configuration能重定向从跨方法的引用,
从而保证上述代码中的b bean是一个单例.
调用 ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry 会将 AppConfig 的配置 类属性标注为full。其调用的流程图如下:
其判断是否full的代码如下:
Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, "full");
} else {
if (config == null && !isConfigurationCandidate(metadata)) {
return false;
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, "lite");
跟踪 AnnotationConfigApplicationContext.refresh() 方法:
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
this.prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
this.initMessageSource();
this.initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
this.finishRefresh();
} catch (BeansException var10) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
this.destroyBeans();
this.cancelRefresh(var10);
throw var10;
} finally {
this.resetCommonCaches();
contextRefresh.end();
跟踪invokeBeanFactoryPostProcessors(beanFactory)
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());
if (!IN_NATIVE_IMAGE && beanFactory.getTempClassLoader() == null && beanFactory.containsBean("loadTimeWeaver")) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
跟踪invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
else {
regularPostProcessors.add(postProcessor);
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
//此处调用ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry,
//解析配置类,为配置中的bean定义生成对应beanDefinition,并注入到registry的beanDefinitionMap
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
//调用ConfigurationClassPostProcessor#postProcessBeanFactory增强配置类(通过cglib生成增强类,load到jvm内存,
//设置beanDefinition的beanClass为增强类)
//为什么要增强配置类?主要是为了让@Bean生成的bean是单例,
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
else {
nonOrderedPostProcessorNames.add(ppName);
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
跟踪invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
跟踪ConfigurationClassPostProcessor#postProcessBeanFactory
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + beanFactory);
this.factoriesPostProcessed.add(factoryId);
if (!this.registriesPostProcessed.contains(factoryId)) {
// BeanDefinitionRegistryPostProcessor hook apparently not supported...
// Simply call processConfigurationClasses lazily at this point then.
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
//为@Configuration注解的类生成增强类(如果有必要),并替换bd中的beanClass属性,
enhanceConfigurationClasses(beanFactory);
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
到了这一步谜底几乎已经揭晓了,@Configuration class是通过增强来实现它的语义的。通过增强把跨方法的引用调用重定向到Spring生命周期管理.我们近一步探索下这个enhanceConfigurationClasses方法
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
MethodMetadata methodMetadata = null;
if (beanDef instanceof AnnotatedBeanDefinition) {
methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata();
if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
// Configuration class (full or lite) or a configuration-derived @Bean method
// -> resolve bean class at this point...
AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
if (!abd.hasBeanClass()) {
try {
abd.resolveBeanClass(this.beanClassLoader);
catch (Throwable ex) {
throw new IllegalStateException(
"Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
//在ConfigurationClassUtils.checkConfigurationClassCandidate方法中会标记Configuration is full or lite
if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
if (!(beanDef instanceof AbstractBeanDefinition)) {
throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
logger.info("Cannot enhance @Configuration bean definition '" + beanName +
"' since its singleton instance has been created too early. The typical cause " +
"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
"return type: Consider declaring such methods as 'static'.");
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
if (configBeanDefs.isEmpty()) {
// nothing to enhance -> return immediately
return;
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
AbstractBeanDefinition beanDef = entry.getValue();
// If a @Configuration class gets proxied, always proxy the target class
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
// Set enhanced subclass of the user-specified bean class
Class<?> configClass = beanDef.getBeanClass();
//为@Configuration注解的类生成增强类
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
if (logger.isTraceEnabled()) {
logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
beanDef.setBeanClass(enhancedClass);
看到有那么一句话
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
很明显了,使用cglib技术为config class生成一个enhancedClass,再通过beanDef.setBeanClass(enhancedClass);
修改beanDefinition的BeanClass属性,在bean实例化阶段,会利用反射技术将beanClass属性对应的类实例化出来,所以最终实例化出来的@Configuration bean是一个代理类的实例。这里稍微提一下为什么要使用cglib
,而不是jdk动态代理
,主要是因为jdk动态代理
是基于接口的,而这里AppConfig并没有实现任何接口,所以必须用cglib
技术。
被@Configuration 注解的类,是 full configuration class,该类会被增强(通过cglib
),从而实现跨方法引用调用被重定向到Spring 生命周期管理,最终保证@Bean method生成的bean是一个单例。
参考博客:热心市民小陈 https://www.cnblogs.com/think-in-java/p/11876997.html