栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot源码分析 (构造方法) (二)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot源码分析 (构造方法) (二)


构造方法解析


  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 getBootstrapRegistryInitializersFromSpringFactories() {
		ArrayList 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() {
            @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  Collection getSpringFactoriesInstances(Class type, Class[] parameterTypes, Object... args) {
		ClassLoader classLoader = getClassLoader();
		// Use names and ensure unique to protect against duplicates
		Set names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
		List 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));

    }
}

获取类名

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/862695.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号