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.项目层级

springboot 自动注入源码分析spring.factories_第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.项目侧使用


            com.paas 
            cos-spring-boot-starter
            ${project.version}
        

二、星耀源码跟踪分析

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 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 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 filter) throws IOException {
		do {
			sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
		}

	}


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



private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
			Collection importCandidates, Predicate 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 configurations = getCandidateConfigurations(annotationMetadata, attributes);
	}


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

7. SpringFactoriesLoader.loadFactoryNames

public static List 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> loadSpringFactories(ClassLoader classLoader) {
		try {
			Enumeration urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);	
	}

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

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

2.类实现ImportSelector,实现selectImports

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


你可能感兴趣的:(源码解读,springboot,自动装配,源码分析,java)