SpringBoot源码分析 (构造方法)

SpringBoot源码分析 (构造方法) ,第1张


构造方法解析


  1. 获取BeanDefinition 主源
  2. 推断应用类型
  3. ApplicationContext初始化器
  4. 监听器和事件
  5. 主类推断
    文章目录
        • 构造方法解析
          • 1.1 获取BeanDefinition 主源
          • 1.2 推断应用类型
          • 1.3 ApplicationContext初始化器
          • 1.4 监听器和事件
          • 1.5 主类推断
1.1 获取BeanDefinition 主源


这里可以理解为获取一个ResourceLoader 用于获取BeanDefinition
然后断言主源是否存在
然后将主源添加到集合中, 这个集合为primarySources
集合用于后续解析获取到BeanDefinition

1.2 推断应用类型


用于判断是SERVLET 还是 REACTIVE 还是 NONE

	static WebApplicationType deduceFromClasspath() {
		if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
				&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
			return WebApplicationType.REACTIVE;
		}
		for (String className : SERVLET_INDICATOR_CLASSES) {
			if (!ClassUtils.isPresent(className, null)) {
				return WebApplicationType.NONE;
			}
		}
		return WebApplicationType.SERVLET;
	}
1.3 ApplicationContext初始化器

初始化进行增强

	private List<BootstrapRegistryInitializer> getBootstrapRegistryInitializersFromSpringFactories() {
		ArrayList<BootstrapRegistryInitializer> initializers = new ArrayList<>();
		getSpringFactoriesInstances(Bootstrapper.class).stream()
				.map((bootstrapper) -> ((BootstrapRegistryInitializer) bootstrapper::initialize))
				.forEach(initializers::add);
		initializers.addAll(getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
		return initializers;
	}
        springApplication.addInitializers(new ApplicationContextInitializer<ConfigurableApplicationContext>() {
            @Override
            public void initialize(ConfigurableApplicationContext applicationContext) {
                // context
                GenericApplicationContext context = (GenericApplicationContext) applicationContext;
                context.registerBean("bean1", Bean1.class);
            }
        });

在spring.factories下面的ApplicationContextInitializer加载类

spring-boot项目下

# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer

spring-boot-autoconfigure项目下

# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener


 具体的加载方法为 getSpringFacotiesInstance()方法

	private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
		ClassLoader classLoader = getClassLoader();
		// Use names and ensure unique to protect against duplicates
		Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
		List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
		AnnotationAwareOrderComparator.sort(instances);
		return instances;
	}

SpringFactoriesLoader.loadFactoryNames(type, classLoader)中具体查看加载文件的过程

loadSpringFactories()


通过 loadSpringFactories 方法我们看到把 spring.factories文件中的所有信息都加载到了内存中了,但是我们现在只需要加载 ApplicationContextInitializer类型的数据。

getOrDefault():

    default V getOrDefault(Object key, V defaultValue) {
        V v;
        return (((v = get(key)) != null) || containsKey(key))
            ? v
            : defaultValue;
    }


 然后会根据反射获取对应的实例对象。


getSpringFactoriesInstances方法就是帮我们定义在META-INF/spring.factories文件中的认为是ApplicationContextInitializer的值, 并通过反射获取实例对象, 然后将实例对象存储在initializers属性中。

1.4 监听器和事件

注册监听器, 用于后面使用

要获取的 META-INF/spring.factories文件中定义ApplicationListener的值

加入到listeners 属性中。

1.5 主类推断

判断main方法是哪个类

这里我利用反射调用这个方法

@SpringBootApplication
public class Main {
    public static void main(String[] args)throws Exception{
        SpringApplication app = new SpringApplication(Main.class);
        app.run(args);
        Method method = SpringApplication.class.getDeclaredMethod("deduceMainApplicationClass");
        method.setAccessible(true);
        System.out.println(method.invoke(app));

    }
}

获取类名

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/871366.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存