springboot 自动注入源码分析spring.factories

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

前言

一、铂金手写starter组件,开源starter组件结构

1.项目层级

2. 各个项目引入关系

3.项目侧使用

二、星耀源码跟踪分析

1.SpringApplication.run开始到->refreshContext

2.spring的refreshContext->invokeBeanFactoryPostProcessors

3. invokeBeanFactoryPostProcessors

4.ConfigurationClassPostProcessor.postProcessBeanFactory(beanFactory)

5. ConfigurationClassParser.parse

6.AutoConfigurationImportSelector.selectImports

7. SpringFactoriesLoader.loadFactoryNames

 三.王者手写简单自动装配机制


前言

spingboot自动装配

黄金:了解spring.factories自动装配

铂金:自己写starter实现自动装配,知道加一个spring.factories然后配置一个@Configuration配置类

钻石:通过网上搜索一些信息,知道关键加载位置@SpringBootApplication ->@EnableAutoConfiguration->@Import(AutoConfigurationImportSelector.class)->AutoConfigurationImportSelector.selectImports->AutoConfigurationImportSelector.getAutoConfigurationEntry->AutoConfigurationImportSelector.getCandidateConfigurations->SpringFactoriesLoader.loadSpringFactories

星耀:自己跟踪springboot项目启动源码,分析springboot自动装配全过程实现

王者:自己手写一个简单的springboot自动装配机制


一、铂金手写starter组件,开源starter组件结构

1.项目层级

cos-minio为核心代码

cos-servicer不是重点忽略

cos-spring-boot-autoconfiure自动装配配置类

cos-spring-boot-starter各个系统使用所引入的starter

2. 各个项目引入关系

cos-spring-boot-starter的pom引入cos-spring-boot-autoconfiure,cos-spring-boot-autoconfiure引入cos-minio

3.项目侧使用

<dependency>
            <groupId>com.paas</groupId> 
            <artifactId>cos-spring-boot-starter</artifactId>
            <version>${project.version}</version>
        </dependency>

二、星耀源码跟踪分析

1.SpringApplication.run开始到->refreshContext

SpringApplication.run(BaseOauthApplication.class, args);


public ConfigurableApplicationContext run(String... args) {
		try {
			refreshContext(context);
		}
		return context;
	}

2.spring的refreshContext->invokeBeanFactoryPostProcessors

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			try {			
				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);
			}

		}
	}

3. invokeBeanFactoryPostProcessors

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
		}
	}


private static void invokeBeanFactoryPostProcessors(
			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();
		}
	}

4.ConfigurationClassPostProcessor.postProcessBeanFactory(beanFactory)

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {

		if (!this.registriesPostProcessed.contains(factoryId)) {
			processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
		}
	}


public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
		for (String beanName : candidateNames) {
			parser.parse(candidates);
			
	    }
}

5. ConfigurationClassParser.parse

public void parse(Set<BeanDefinitionHolder> configCandidates) {
		for (BeanDefinitionHolder holder : configCandidates) {
			try {
					parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());			
			}
		}
	}


protected final void parse(Class<?> clazz, String beanName) throws IOException {
		processConfigurationClass(new ConfigurationClass(clazz, beanName), DEFAULT_EXCLUSION_FILTER);
	}



protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
		do {
			sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
		}

	}


@Nullable
	protected final SourceClass doProcessConfigurationClass(
			ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
			throws IOException {
		// Process any @Import annotations
		processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
	}



private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
			Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
			boolean checkForCircularImports) {
		String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
	}

6.AutoConfigurationImportSelector.selectImports

	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
	}


	protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
	}


protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
				getBeanClassLoader());
	}

7. SpringFactoriesLoader.loadFactoryNames

public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
		return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
	}


	public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
		try {
			Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);	
	}

 三.王者手写简单自动装配机制

1.定义自己的注解如@EnableAutoConfiguration

2.类实现ImportSelector,实现selectImports

3.在spring.factories里面定义自己的装配机制


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值