ConfigurationClassPostProcessor在Spring中的加载流程(一)

ConfigurationClassPostProcessor作为SpringBoot自动配置原理的核心类,其加载流程是怎么样的呢?

一、ConfigurationClassPostProcessor类信息的注册

(1)创建应用上下文(也就是Spring容器)

public class SpringApplication {
    public ConfigurableApplicationContext run(String... args) {

        ......
        // 创建Spring容器
        context = createApplicationContext();
        ......
    }
}


(2)根据Web应用类型创建应用上下文(可以看一下ConfigurableApplicationContext该类的继承体系,就知道为什么它就是Spring容器了)

public class SpringApplication {
   
    protected ConfigurableApplicationContext createApplicationContext() {
		return this.applicationContextFactory.create(this.webApplicationType);
	}
}

        根据Web应用类型创建应用上下文(此处采用了工厂模式),那么ApplicationContextFactory是怎么是实例化的呢,如下:

public class SpringApplication {
    private ApplicationContextFactory applicationContextFactory = ApplicationContextFactory.DEFAULT;

}

        SpringApplication实例化过程中,实例化了一个ApplicationContextFactory对象,赋给成员变量applicationContextFactory,而ApplicationContextFactory是一个函数式接口,我们进去看下细节:

@FunctionalInterface
public interface ApplicationContextFactory {
    ApplicationContextFactory DEFAULT = (webApplicationType) -> {
		try {
			for (ApplicationContextFactory candidate : SpringFactoriesLoader
					.loadFactories(ApplicationContextFactory.class, ApplicationContextFactory.class.getClassLoader())) {
				ConfigurableApplicationContext context = candidate.create(webApplicationType);
				if (context != null) {
					return context;
				}
			}
			return new AnnotationConfigApplicationContext();
		}
		catch (Exception ex) {
			throw new IllegalStateException("Unable create a default ApplicationContext instance, "
					+ "you may need a custom ApplicationContextFactory", ex);
		}
	};

	ConfigurableApplicationContext create(WebApplicationType webApplicationType);

}

        DEFAULTApplicationContextFactory函数式接口的静态常量采用Lambda表达式创建一个应用上下文工厂。那么应用上下文工厂的元数据是怎么加载的呢?核心实现就是SpringFactoriesLoader,该类的静态常量cache中保存了SpringBoot启动时,从META-INF/spring.factories文件中解析的ApplicationContextFactory映射的类信息,如下:

# Application Context Factories
org.springframework.boot.ApplicationContextFactory=\
org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext.Factory,\
org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext.Factory

该映射信息的spring.factories文件位于spring-boot-x.x.xx.jarMETA-INF目录下。

        DEFAULTLambda表达式内部实现中,SpringFactoriesLoader加载了应用上下文工厂的实例(AnnotationConfigServletWebServerApplicationContext中内部类Factory对象和

        AnnotationConfigReactiveWebServerApplicationContext中内部类Factory对象)集合,分别看下这两个Factory对象:

public class AnnotationConfigReactiveWebServerApplicationContext extends ReactiveWebServerApplicationContext
		implements AnnotationConfigRegistry {、
    ......
    static class Factory implements ApplicationContextFactory {
		@Override
		public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
			return (webApplicationType != WebApplicationType.REACTIVE) ? null
					: new AnnotationConfigReactiveWebServerApplicationContext();
		}
	}
}
public class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext
		implements AnnotationConfigRegistry {
    ......
    static class Factory implements ApplicationContextFactory {
		@Override
		public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
			return (webApplicationType != WebApplicationType.SERVLET) ? null
					: new AnnotationConfigServletWebServerApplicationContext();
		}
	}
}

        可以看到create(WebApplicationType webApplicationType)中,根据WebApplicationType创建了对应的Web应用上下文实例。

        因为在Springboot启动的时候,确定了WebApplicationType(枚举)SERVIET类型(那么怎么确定SERVLET类型的呢,会有另外的文章专门介绍,这里先不讨论),所以最后创建的Web应用上下文是AnnotationConfigServletWebServerApplicationContext的实例。

那么到此,为什么要介绍Web应用上下文(AnnotationConfigServletWebServerApplicationContext)的实例化流程呢,因为在该对象的实例化的构造方法中,有ConfigurationClassPostProcessor类信息注册的实现细节。

public class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext
		implements AnnotationConfigRegistry {
    ......
	public AnnotationConfigServletWebServerApplicationContext() {
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}
    ......
}

        重点this.reader = new AnnotatedBeanDefinitionReader(this);

public class AnnotatedBeanDefinitionReader {
    ......
    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
		this(registry, getOrCreateEnvironment(registry));
	}
    ......
}

        继续看this(registry, getOrCreateEnvironment(registry));

public class AnnotatedBeanDefinitionReader {
    ......
    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		Assert.notNull(environment, "Environment must not be null");
		this.registry = registry;
		this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	}
    ......
}

        重点来了,AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

public abstract class AnnotationConfigUtils {
	......
    public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
		registerAnnotationConfigProcessors(registry, null);
	}
    ......
}
public abstract class AnnotationConfigUtils {
    	public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
			"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
    ......
    public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {
       ......
        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

		if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
		}
    }
    ......
}

        可以看到将ConfigurationClassPostProcessor.class封装成了RootBeanDefinition,然后将RootBeanDefinition注册入Web应用上下文(registry

public abstract class AnnotationConfigUtils {
    	public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
			"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
    ......
    // 将bean的定义信息注册入应用上下文registry中
	private static BeanDefinitionHolder registerPostProcessor(
			BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
        
		definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		registry.registerBeanDefinition(beanName, definition);
		return new BeanDefinitionHolder(definition, beanName);
	}
    ......
}

        该方法中,beanName就是“org.springframework.context.annotation.internalConfigurationAnnotationProcessor”。而internalConfigurationAnnotationProcessor这个类是不存的,只是SpringinternalConfigurationAnnotationProcessorConfigurationClassPostProcessor.class做了映射,封装成RootBeanDefinition对象注册入Web应用上下文。

        ConfigurationClassPostProcessor类信息在容器中的注册完成。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值