wuxin0011`blog wuxin0011`blog
首页
  • 基础内容

    • HTML
    • CSS
    • JavaScript
  • 进阶

    • JavaScript教程
    • ES6 教程
    • Vue
    • React
    • Typescript
    • Git
  • 推荐阅读
  • java随笔
  • JVM (opens new window)
  • 分类
  • 标签
  • 归档
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • git使用
  • docker部署项目
  • 错误收集
  • github-start
  • background-color
  • live-server
  • tampermonkey-script (opens new window)
  • leetcode-tool (opens new window)
  • 网站
  • 前端
  • 后端
  • Github Topic (opens new window)
GitHub (opens new window)

wuxin0011

懂得越多,懂得越少
首页
  • 基础内容

    • HTML
    • CSS
    • JavaScript
  • 进阶

    • JavaScript教程
    • ES6 教程
    • Vue
    • React
    • Typescript
    • Git
  • 推荐阅读
  • java随笔
  • JVM (opens new window)
  • 分类
  • 标签
  • 归档
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • git使用
  • docker部署项目
  • 错误收集
  • github-start
  • background-color
  • live-server
  • tampermonkey-script (opens new window)
  • leetcode-tool (opens new window)
  • 网站
  • 前端
  • 后端
  • Github Topic (opens new window)
GitHub (opens new window)
  • 推荐阅读
  • Java

    • 常见集合总结
    • mybatis源码阅读
    • springboot启动原理
      • SpringApplication
        • BootstrapRegistryInitializer
        • getSpringFactoriesInstances
        • createSpringFactoriesInstances
        • AnnotationAwareOrderComparator
        • ApplicationContextInitializer
        • ApplicationListener
        • 总结
      • run
        • 执行流程
        • createBootstrapContext
        • configureHeadlessProperty
        • getRunListeners
        • listeners.starting
        • DefaultApplicationArguments
        • prepareEnvironment
        • configureIgnoreBeanInfo
        • printBanner
        • createApplicationContext
        • setApplicationStartup
        • prepareContext
        • refreshContext
        • afterRefresh
        • started
        • callRunners
        • handleRunFailure
        • ready
        • doWithListeners
      • 自动配置原理
        • 思考问题
        • SpringBootApplication
        • EnableAutoConfiguration
        • AutoConfigurationImportSelector
        • processConfigBeanDefinitions
        • parse
        • selectImports
        • validate
        • readaer
        • AutoConfigurationImportSelector 补充
        • 标志位信息
    • springcloud介绍
    • 分布式热点问题
    • Zookeeper介绍
    • RabbitMQ
    • tomcat源码阅读
    • 自定义输出内容颜色和背景
  • python

  • 后端
  • Java
wuxin0011
2023-04-24
目录

springboot启动原理

关于 springboot 启动流程和配置原理 很久就写了,不过没有详细补充 ,现在补充 —— 2023-08-05

# 启动原理

@SpringBootApplication
public class Start {

    public static void main(String[] args) {
        SpringApplication.run(Start.class, args);
    }

}
1
2
3
4
5
6
7
8

# SpringApplication

 public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        this.sources = new LinkedHashSet(); // 
        this.bannerMode = Mode.CONSOLE;// 控制banner
        this.logStartupInfo = true;// 是否启动日志
        this.addCommandLineProperties = true; // 读取命令行配置
        this.addConversionService = true; //添加转换器
        this.headless = true; // 
        this.registerShutdownHook = true; // 注册重启
        this.additionalProfiles = Collections.emptySet();// 读取配置环境
        this.isCustomEnvironment = false;// 是否是自定义环境
        this.lazyInitialization = false; // 是否懒加载
        this.applicationContextFactory = ApplicationContextFactory.DEFAULT;
        this.applicationStartup = ApplicationStartup.DEFAULT; // ApplicationStartup DEFAULT = new DefaultApplicationStartup();
        this.resourceLoader = resourceLoader;// 资源加载器
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources)); // 主程序
        this.webApplicationType = WebApplicationType.deduceFromClasspath();//  SERVLET||REACTIVE; 是servlet还是reactive环境
        // BootstrapRegistryInitializer
	this.bootstrapRegistryInitializers = new ArrayList(this.getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
        // ApplicationContextInitializer
	this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
	// ApplicationListener        
	this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = this.deduceMainApplicationClass();
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# BootstrapRegistryInitializer

BootstrapRegistryInitializer 是一个函数是接口

@FunctionalInterface
public interface BootstrapRegistryInitializer {
	void initialize(BootstrapRegistry registry);
}
1
2
3
4

org.springframework.boot.BootstrapRegistry 接口

# getSpringFactoriesInstances

	private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
		return getSpringFactoriesInstances(type, new Class<?>[] {});
	}

	private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
		ClassLoader classLoader = getClassLoader();
		// 使用 set 结构去重
		Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
		List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
        
        // 加载完毕后排序
		AnnotationAwareOrderComparator.sort(instances);
		return instances;
	}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

加载工厂中组件实现方式

org.springframework.core.io.support.SpringFactoriesLoader#loadSpringFactories

// 1、加载配置
 private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
        Map<String, List<String>> result = (Map)cache.get(classLoader);
        if (result != null) {
            return result;
        } else {
            HashMap result = new HashMap();
            try {
                 //核心 从这里知道读取配置文件位置 默认
                Enumeration urls = classLoader.getResources("META-INF/spring.factories");
		        // ... 这里省略迭代器遍历注册
                
                // result.replaceAll  该函数的作用是对每个值进行去重,并将去重后的结果存储为一个不可修改的列表。最后,replaceAll 方法使用这个函数的结果来替换原始的键值对中的值
                result.replaceAll((factoryType, implementations) -> {
                    return (List)implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
                });
		        // 添加到缓存中 下次读取先获取类加载器 通过类加载器获取 map 结构再获取 bean
                // cache 结构
                // 	static final Map<ClassLoader, Map<String, List<String>>> cache = new ConcurrentReferenceHashMap<>();
                cache.put(classLoader, result);
                return result;
            } catch (IOException var14) {
                // 错误异常信息
            }
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

加载的配置文件

spring-boot:2.7.1.META-INF\spring.factorie

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
1
2
3
4
5
6

​

像 BootstrapRegistryInitializer

另外几个配置是从其他配置文件中读取的

例如

​

# createSpringFactoriesInstances

``org.springframework.core.io.support.SpringFactoriesLoader#createSpringFactoriesInstances 构建实例对象



// 2、获取构造器实例
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) {
        List<T> instances = new ArrayList(names.size());
        Iterator var7 = names.iterator();

        while(var7.hasNext()) {
            String name = (String)var7.next();

            try {
                // 通过类名反射机制调用,读取Class<T> class
                Class<?> instanceClass = ClassUtils.forName(name, classLoader);
                Assert.isAssignable(type, instanceClass);
                Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
                // 通过 BeanUtils 提供静态方法 instantiateClass () 
                // 通过构造函数 和参数 构造一个实例对象
                // 最终调用的是 
 		T instance = BeanUtils.instantiateClass(constructor, args);
                // 添加到构造器中
                instances.add(instance);
            } catch (Throwable var12) {
                // throw error
            }
        }
	// 返回
        return instances;
    }


// 排序 通过debug这里调用的是Integer类型排序方法 List<Integer> list
  public static void sort(List<?> list) {
        if (list.size() > 1) {
            list.sort(INSTANCE);
        }

    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

需要注意的是 BeanUtils.instantiateClass 最终调用的是java.lang.Class#form0 由 底层实现

    private static native Class<?> forName0(String name, boolean initialize,
                                            ClassLoader loader,
                                            Class<?> caller)
        throws ClassNotFoundException;
1
2
3
4

# AnnotationAwareOrderComparator

加载实例完毕后是由 org.springframework.core.annotation.AnnotationAwareOrderComparator


public class AnnotationAwareOrderComparator extends OrderComparator {

	public static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator();
	public static void sort(List<?> list) {
		if (list.size() > 1) {
            // 采用单例模式实现
            // 比较器由 OrderComparator 实现
			list.sort(INSTANCE);
		}
	}
}

1
2
3
4
5
6
7
8
9
10
11
12
13

比较器实现 org.springframework.core.OrderComparator#doCompare()

	private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) {
        // PriorityOrdered 是一种优先级排序
		boolean p1 = (o1 instanceof PriorityOrdered);
		boolean p2 = (o2 instanceof PriorityOrdered);
        
        
        // 逆序
		if (p1 && !p2) {
			return -1;
		}
        // 顺序
		else if (p2 && !p1) {
			return 1;
		}
		int i1 = getOrder(o1, sourceProvider);
		int i2 = getOrder(o2, sourceProvider);
        
        // 最终交给 Integer 的比较器排序
		return Integer.compare(i1, i2);
	}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# ApplicationContextInitializer

同 BootstrapRegistryInitializer加载原理

# ApplicationListener

同 BootstrapRegistryInitializer加载原理

# 总结

image-20230805073247310

# run

# 执行流程

public ConfigurableApplicationContext run(String... args) {
        // 初次启动时间
        long startTime = System.nanoTime();
        // 默认上下文环境
        DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
        ConfigurableApplicationContext context = null;
        this.configureHeadlessProperty();
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting(bootstrapContext, this.mainApplicationClass);

        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            // 加载配置文件
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            
            // 图形 Banner
            Banner printedBanner = this.printBanner(environment);
            context = this.createApplicationContext();
            context.setApplicationStartup(this.applicationStartup);
            this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
            // 加载所有注解使用的扫描的组件
	        this.refreshContext(context);
	        // 刷新
            this.afterRefresh(context, applicationArguments);
            Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), timeTakenToStartup);
            }

            // 启动 listener
            listeners.started(context, timeTakenToStartup);
            
            // 加载完毕处理 调用函数是接口 ApplicationRunner run 方法
            // ApplicationRunner
            // CommandLineRunner
            this.callRunners(context, applicationArguments);
        } catch (Throwable var12) {
            // 启动失败调用 ApplicationEventPublisher 接口实现
            // 事件推送
            this.handleRunFailure(context, var12, listeners);
            throw new IllegalStateException(var12);
        }

        try {
            Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
            // 加载完毕 事件通过 doWithListeners 触发
            listeners.ready(context, timeTakenToReady);
            return context;
        } catch (Throwable var11) {
            this.handleRunFailure(context, var11, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var11);
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

# createBootstrapContext

	private DefaultBootstrapContext createBootstrapContext() {
		DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
		this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));
		return bootstrapContext;
	}
1
2
3
4
5

# configureHeadlessProperty

	private void configureHeadlessProperty() {
		System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
				System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
	}
1
2
3
4

# getRunListeners


	private SpringApplicationRunListeners getRunListeners(String[] args) {
		Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
		return new SpringApplicationRunListeners(logger,
                   // 获取 SpringApplicationRunListener 类型 侦听器, 在构造函数创建时候已经调用了
                   // 
				getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
				this.applicationStartup);
	}

1
2
3
4
5
6
7
8
9
10

获取 侦听器,这次走缓存

image-20230804163314685

image-20230804163532973

# listeners.starting

启动侦听器经过这里 org.springframework.boot.SpringApplicationRunListeners

	void starting(ConfigurableBootstrapContext bootstrapContext, Class<?> mainApplicationClass) {
		doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext),
				(step) -> {
					if (mainApplicationClass != null) {
						step.tag("mainApplicationClass", mainApplicationClass.getName());
					}
				});
	}

1
2
3
4
5
6
7
8
9
	@Override
	public void starting(ConfigurableBootstrapContext bootstrapContext) {
		this.initialMulticaster
				.multicastEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));
	}
1
2
3
4
5

最终触发事件 org.springframework.context.event.SimpleApplicationEventMulticaster

	private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
		try {
			listener.onApplicationEvent(event);
		}
		catch (ClassCastException ex) {
			// 异常处理
		}
	}

1
2
3
4
5
6
7
8
9

image-20230804164650461

image-20230804164908733

org.springframework.boot.context.logging.LoggingApplicationListener#onApplicationEvent

	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		if (event instanceof ApplicationStartingEvent) {
			onApplicationStartingEvent((ApplicationStartingEvent) event);
		}
		else if (event instanceof ApplicationEnvironmentPreparedEvent) {
			onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
		}
		else if (event instanceof ApplicationPreparedEvent) {
			onApplicationPreparedEvent((ApplicationPreparedEvent) event);
		}
		else if (event instanceof ContextClosedEvent) {
			onContextClosedEvent((ContextClosedEvent) event);
		}
		else if (event instanceof ApplicationFailedEvent) {
			onApplicationFailedEvent();
		}
	}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# DefaultApplicationArguments

默认参数类 org.springframework.boot.DefaultApplicationArguments

此构造函数作用是保存命令参数 如 java -jar -Dspring.xxxx.yyy=cccc mmm.jar获取参数信息

	public DefaultApplicationArguments(String... args) {
		Assert.notNull(args, "Args must not be null");
		this.source = new Source(args);
		this.args = args;
	}
1
2
3
4
5

# prepareEnvironment

配置文件加载在这个逻辑中

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
		// 获取配置环境 默认是 servlet
		ConfigurableEnvironment environment = getOrCreateEnvironment();
        // 环境参数处理
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		ConfigurationPropertySources.attach(environment);
        // 启动配置文件的侦听器
        // 读取配置文件
		listeners.environmentPrepared(bootstrapContext, environment);
        // 默认配置文件合并
		DefaultPropertiesPropertySource.moveToEnd(environment);
		Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
				"Environment prefix cannot be set via properties.");
        // 配置内容绑定到 SpringApplication 这个类中
		bindToSpringApplication(environment);
        // 非自定义环境
		if (!this.isCustomEnvironment) {
			environment = convertEnvironment(environment);
		}
        // 所有配置内容合并
		ConfigurationPropertySources.attach(environment);
		return environment;
	}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

获取 web 环境

	private ConfigurableEnvironment getOrCreateEnvironment() {
		if (this.environment != null) {
			return this.environment;
		}
        
        // 如果不做默认配置 默认是 SERVLET
		switch (this.webApplicationType) {
            // 默认 servelt 环境
			case SERVLET:
				return new ApplicationServletEnvironment();
            // 响应式编程
			case REACTIVE:
				return new ApplicationReactiveWebEnvironment();
			default:
				return new ApplicationEnvironment();
		}
	}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

配置文件加载流程

	void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
		doWithListeners("spring.boot.application.environment-prepared",
				(listener) -> listener.environmentPrepared(bootstrapContext, environment));
	}

1
2
3
4
5

org.springframework.boot.env.EnvironmentPostProcessorApplicationListener#onApplicationEnvironmentPreparedEvent()

	private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
		ConfigurableEnvironment environment = event.getEnvironment();
		SpringApplication application = event.getSpringApplication();
		for (EnvironmentPostProcessor postProcessor : getEnvironmentPostProcessors(application.getResourceLoader(),
				event.getBootstrapContext())) {
			postProcessor.postProcessEnvironment(environment, application);
		}
	}
1
2
3
4
5
6
7
8

image-20230804171058996

org.springframework.core.env.#addFirst

	public void addFirst(PropertySource<?> propertySource) {
		synchronized (this.propertySourceList) {
			removeIfPresent(propertySource);
            // 添加第一个位置
			this.propertySourceList.add(0, propertySource);
		}
	}
1
2
3
4
5
6
7

image-20230804181442412

第一个配置类包括所有内容

image-20230804181643755

# configureIgnoreBeanInfo

	private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
		if (System.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
			Boolean ignore = environment.getProperty("spring.beaninfo.ignore", Boolean.class, Boolean.TRUE);
			System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME, ignore.toString());
		}
	}
1
2
3
4
5
6

# printBanner

	private Banner printBanner(ConfigurableEnvironment environment) {
        // 如果 Banner.Mode.OFF 将不会打印Banner内容
        // 默认为 CONOSLE 也就是输出
		if (this.bannerMode == Banner.Mode.OFF) {
			return null;
		}
		ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
				: new DefaultResourceLoader(null);
		SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);
		if (this.bannerMode == Mode.LOG) {
			return bannerPrinter.print(environment, this.mainApplicationClass, logger);
		}
		return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
	}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

org.springframework.boot.SpringApplicationBannerPrinter#print

image-20230804182922097

阅读上面内容知道一下内容

  • 指定位置信息
  • 指定图片位置信息
  • 默认为 banner.txt
  • 图片格式
	

Banner print(Environment environment, Class<?> sourceClass, PrintStream out) {
		Banner banner = getBanner(environment);
		banner.printBanner(environment, sourceClass, out);
		return new PrintedBanner(banner, sourceClass);
	}
1
2
3
4
5
6
7

org.springframework.boot.SpringBootBanner

默认Banner 内容

class SpringBootBanner implements Banner {

	private static final String[] BANNER = { "", "  .   ____          _            __ _ _",
			" /\\\\ / ___'_ __ _ _(_)_ __  __ _ \\ \\ \\ \\", "( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\",
			" \\\\/  ___)| |_)| | | | | || (_| |  ) ) ) )", "  '  |____| .__|_| |_|_| |_\\__, | / / / /",
			" =========|_|==============|___/=/_/_/_/" };

	private static final String SPRING_BOOT = " :: Spring Boot :: ";

	private static final int STRAP_LINE_SIZE = 42;

	@Override
	public void printBanner(Environment environment, Class<?> sourceClass, PrintStream printStream) {
		for (String line : BANNER) {
            // 输出 BANNER
			printStream.println(line);
		}
          // 获取版本号信息
		String version = SpringBootVersion.getVersion();
     
		version = (version != null) ? " (v" + version + ")" : "";
		StringBuilder padding = new StringBuilder();
		while (padding.length() < STRAP_LINE_SIZE - (version.length() + SPRING_BOOT.length())) {
			padding.append(" ");
		}

        // 最终经过 打印流输出 上面内容
		printStream.println(AnsiOutput.toString(AnsiColor.GREEN, SPRING_BOOT, AnsiColor.DEFAULT, padding.toString(),
				AnsiStyle.FAINT, version));
		printStream.println();
	}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

image-20230804182435543

# createApplicationContext

org.springframework.boot.ApplicationContextFactory

获取服务器环境 默认是 servlet环境

	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) {
		   // hanlder error
		}
	};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

重写接口两个类

image-20230804184151174

# setApplicationStartup

设置

image-20230804184413248

# prepareContext

    private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
            SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
        // 上下文中设置环境
        context.setEnvironment(environment);
        // 上下文处理
        postProcessApplicationContext(context);
        // 初始化
        applyInitializers(context);
        // 监听器中放入上下文
        listeners.contextPrepared(context);
        if (this.logStartupInfo) {
            logStartupInfo(context.getParent() == null);
            logStartupProfileInfo(context);
        }
        // Add boot specific singleton beans
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        // 单例对象注册
        beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
        if (printedBanner != null) {
            beanFactory.registerSingleton("springBootBanner", printedBanner);
        }
        if (beanFactory instanceof DefaultListableBeanFactory) {
            ((DefaultListableBeanFactory) beanFactory)
                    .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
        if (this.lazyInitialization) {
            context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
        }
        // Load the sources
        Set<Object> sources = getAllSources();
        Assert.notEmpty(sources, "Sources must not be empty");
        // 加载上下文
        load(context, sources.toArray(new Object[0]));
        // 监听器做加载上下文操作
        listeners.contextLoaded(context);
    }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

注册类型转换器

image-20230804205815320

image-20230804184554622

# refreshContext

核心实现 org.springframework.context.support.AbstractApplicationContext.refresh()

	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
				contextRefresh.end();
			}
		}
	}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

# afterRefresh

这个方法什么都没写 为以后拓展需要

protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) {
	}
1
2

# started

任务开始启动中...

	void started(ConfigurableApplicationContext context, Duration timeTaken) {
		doWithListeners("spring.boot.application.started", (listener) -> listener.started(context, timeTaken));
	}
1
2
3

由 org.springframework.boot.context.event.EventPublishingRunListener#started()实现

	@Override
	public void started(ConfigurableApplicationContext context, Duration timeTaken) {
        // 发布事件
		context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context, timeTaken));
        // 发布事件
		AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);
	}
1
2
3
4
5
6
7

实现类

image-20230804222459574

# callRunners

private void callRunners(ApplicationContext context, ApplicationArguments args) {
		List<Object> runners = new ArrayList<>();
        // 从容器工厂中获取 ApplicationRunner 和  CommandLineRunner 的子类对象
		runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
		runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
        // 排序下
		AnnotationAwareOrderComparator.sort(runners);
        // 执行 run
		for (Object runner : new LinkedHashSet<>(runners)) {
			if (runner instanceof ApplicationRunner) {
				callRunner((ApplicationRunner) runner, args);
			}
			if (runner instanceof CommandLineRunner) {
				callRunner((CommandLineRunner) runner, args);
			}
		}
	}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// // org.springframework.boot.CommandLineRunner
@FunctionalInterface
public interface ApplicationRunner {
	void run(ApplicationArguments args) throws Exception;
}


// org.springframework.boot.CommandLineRunner

@FunctionalInterface
public interface CommandLineRunner {
	void run(String... args) throws Exception;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14

org.springframework.boot.SpringApplication.callRunner


	private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
		try {
            // 调用接口
			(runner).run(args);
		}
		catch (Exception ex) {
			throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
		}
	}
1
2
3
4
5
6
7
8
9
10
	private void callRunner(CommandLineRunner runner, ApplicationArguments args) {
		try {
             // 调用接口
			(runner).run(args.getSourceArgs());
		}
		catch (Exception ex) {
			throw new IllegalStateException("Failed to execute CommandLineRunner", ex);
		}
	}
1
2
3
4
5
6
7
8
9

# handleRunFailure

	private void handleRunFailure(ConfigurableApplicationContext context, Throwable exception,
			SpringApplicationRunListeners listeners) {
		try {
			try {
				handleExitCode(context, exception);
				if (listeners != null) {
					listeners.failed(context, exception);
				}
			}
			finally {
				reportFailure(getExceptionReporters(context), exception);
				if (context != null) {
					context.close();
					shutdownHook.deregisterFailedApplicationContext(context);
				}
			}
		}
		catch (Exception ex) {
			logger.warn("Unable to close ApplicationContext", ex);
		}
		ReflectionUtils.rethrowRuntimeException(exception);
	}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private void handleExitCode(ConfigurableApplicationContext context, Throwable exception) {
        // 获取错误 code
		int exitCode = getExitCodeFromException(context, exception);
        // 为什么是 不等于 0 ? 
        // 因为系统认为 System.exit(0) 是强制退出
		if (exitCode != 0) {
			if (context != null) {
                // 发布错误 event
				context.publishEvent(new ExitCodeEvent(context, exitCode));
			}
			SpringBootExceptionHandler handler = getSpringBootExceptionHandler();
			if (handler != null) {
                // 注册错误 code
				handler.registerExitCode(exitCode);
			}
		}
	}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# ready

执行到这里基本上就完毕了,ready 意为就绪

	void ready(ConfigurableApplicationContext context, Duration timeTaken) {
		doWithListeners("spring.boot.application.ready", (listener) -> listener.ready(context, timeTaken));
	}
1
2
3

# doWithListeners

	private void doWithListeners(String stepName, Consumer<SpringApplicationRunListener> listenerAction,
			Consumer<StartupStep> stepAction) {
		StartupStep step = this.applicationStartup.start(stepName);
        
        // 触发 监听器 事件
		this.listeners.forEach(listenerAction);
		if (stepAction != null) {
            // 触发事件
			stepAction.accept(step);
		}
        // 结束
		step.end();
	}

1
2
3
4
5
6
7
8
9
10
11
12
13
14

所有组件经过org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader方法加载注册组件

org.springframework.beans.factory.support.DefaultListableBeanFactory

  • registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition())

# 自动配置原理

# 思考问题

了解自动配置之前你可以思考以下问题

  • 组件是如何注册的呢?如果让你来实现你扫描组件你会如何实现?需要注意哪些需求?
  • 批量注册

使用中只需要在主类中使用 @SpringBootApplication 注解就可以扫描该类包下 所有注册的组件,注册组件

# SpringBootApplication

// ... 常见省略
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
    @AliasFor(annotation = EnableAutoConfiguration.class)
    Class<?>[] exclude() default {};

    @AliasFor(annotation = EnableAutoConfiguration.class)
    String[] excludeName() default {};

    @AliasFor(annotation = ComponentScan.class,attribute = "basePackages")
    String[] scanBasePackages() default {};

    @AliasFor(annotation = ComponentScan.class,attribute = "basePackageClasses")
    Class<?>[] scanBasePackageClasses() default {};

    @AliasFor(annotation = ComponentScan.class,attribute = "nameGenerator")
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    @AliasFor(annotation = Configuration.class)
    boolean proxyBeanMethods() default true;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

核心注解是

  • @SpringBootConfiguration

    • 本质是一个配置类
  • @EnableAutoConfiguration

    • 自动配置核心

# EnableAutoConfiguration

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14

核心是@Import({AutoConfigurationImportSelector.class}) ,将 AutoConfigurationImportSelector 注入实现了自动配置,也就是说 AutoConfigurationImportSelector 类具有自动注入组件功能,下面看看

AutoConfigurationImportSelector 类的实现吧

# AutoConfigurationImportSelector

# processConfigBeanDefinitions

解析配置文件类

org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry()

核心实现部分

	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
        // 获取所有已注册的 bean 的 name
		String[] candidateNames = registry.getBeanDefinitionNames();

		for (String beanName : candidateNames) {
            // 通过 name 从 工厂中获取 bean
			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
            // 	public static final String CONFIGURATION_CLASS_ATTRIBUTE =
			//Conventions.getQualifiedAttributeName(ConfigurationClassPostProcessor.class, "configurationClass");
			if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
				// ...
			}
            // 是不是配置类
			else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}

		// Return immediately if no @Configuration classes were found
		if (configCandidates.isEmpty()) {
			return;
		}

		// 根据条件排序
		configCandidates.sort((bd1, bd2) -> {
			int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
			int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
			return Integer.compare(i1, i2);
		});

		// Detect any custom bean name generation strategy supplied through the enclosing application context
		SingletonBeanRegistry sbr = null;
		if (registry instanceof SingletonBeanRegistry) {
			sbr = (SingletonBeanRegistry) registry;
			if (!this.localBeanNameGeneratorSet) {
				BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
						AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
				if (generator != null) {
					this.componentScanBeanNameGenerator = generator;
					this.importBeanNameGenerator = generator;
				}
			}
		}

        // 运行环境判断
        // 没有赋值一个默认环境
		if (this.environment == null) {
			this.environment = new StandardEnvironment();
		}

		// 解析所有配置类
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);
        // 去重
		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
		Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
        // 开始遍历所有配置类
		do {
			StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
            // 核心逻辑
			parser.parse(candidates);
            // 校验
			parser.validate();

           // 获取所有配置类
			Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
            // 释放缓存
			configClasses.removeAll(alreadyParsed);

			// Read the model and create bean definitions based on its content
			if (this.reader == null) {
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
            // reader 读取
            // org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader
			this.reader.loadBeanDefinitions(configClasses);
			alreadyParsed.addAll(configClasses);
			processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

			candidates.clear();
			if (registry.getBeanDefinitionCount() > candidateNames.length) {
				String[] newCandidateNames = registry.getBeanDefinitionNames();
				Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
				Set<String> alreadyParsedClasses = new HashSet<>();
				for (ConfigurationClass configurationClass : alreadyParsed) {
					alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
				}
				for (String candidateName : newCandidateNames) {
					if (!oldCandidateNames.contains(candidateName)) {
						BeanDefinition bd = registry.getBeanDefinition(candidateName);
						if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
								!alreadyParsedClasses.contains(bd.getBeanClassName())) {
							candidates.add(new BeanDefinitionHolder(bd, candidateName));
						}
					}
				}
				candidateNames = newCandidateNames;
			}
		}
       // ...
	}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

# parse

org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGrouping#getImports

	public Iterable<Group.Entry> getImports() {
			for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
                // 开始执行解析
				this.group.process(deferredImport.getConfigurationClass().getMetadata(),
						deferredImport.getImportSelector());
			}
			return this.group.selectImports();
		}

1
2
3
4
5
6
7
8
9

image-20230805080711390

可以看到类型是org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup

image-20230805080804051

org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup#parse()

		@Override
		public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
             // ...
			AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
                    // 读取配置信息
                    
					.getAutoConfigurationEntry(annotationMetadata);
			this.autoConfigurationEntries.add(autoConfigurationEntry);
			for (String importClassName : autoConfigurationEntry.getConfigurations()) {
				this.entries.putIfAbsent(importClassName, annotationMetadata);
			}
		}
1
2
3
4
5
6
7
8
9
10
11
12

org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getAutoConfigurationEntry

判断是否开启了自动配置类注解

	protected boolean isEnabled(AnnotationMetadata metadata) {
		if (getClass() == AutoConfigurationImportSelector.class) {
			return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class, true);
		}
		return true;
	}
1
2
3
4
5
6

image-20230805081515370

读取的自动配置类

	protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
        // 加载 工厂中所有自动配置类
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
        // 去重
		configurations = removeDuplicates(configurations);
        // 获取排除的类型
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
        // 排除 需要排除的类型
		checkExcludedClasses(configurations, exclusions);
        // 清空 释放内存
		configurations.removeAll(exclusions);
        // 获取过滤信息
		configurations = getConfigurationClassFilter().filter(configurations);
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return new AutoConfigurationEntry(configurations, exclusions);
	}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

image-20230805081721184

​ 经过筛选之后可以看到

image-20230805082823473

``org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getCandidateConfigurations`

`

	protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        // 获取 EnableAutoConfiguration.class bean
        // 这就是为什么自动配置必须要使用 @EnableAutoConfiguration 这个注解了
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
				getBeanClassLoader());
		// 断言部分 ...
		return configurations;
	}


1
2
3
4
5
6
7
8
9
10

org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getCandidateConfigurations

// 这就是为什么自动配置必须要使用 @EnableAutoConfiguration 这个注解了
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
	return EnableAutoConfiguration.class;
}
1
2
3
4

org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#fireAutoConfigurationImportEvents

	private void fireAutoConfigurationImportEvents(List<String> configurations, Set<String> exclusions) {
        // 获取自动配置类的监听器
		List<AutoConfigurationImportListener> listeners = getAutoConfigurationImportListeners();
		if (!listeners.isEmpty()) {
            // 获取 event
			AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this, configurations, exclusions);
			for (AutoConfigurationImportListener listener : listeners) {
				invokeAwareMethods(listener);
				listener.onAutoConfigurationImportEvent(event);
			}
		}
	}

1
2
3
4
5
6
7
8
9
10
11
12
13

org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#invokeAwareMethods

调用不同类型 event

	private void invokeAwareMethods(Object instance) {
		if (instance instanceof Aware) {
			if (instance instanceof BeanClassLoaderAware) {
				((BeanClassLoaderAware) instance).setBeanClassLoader(this.beanClassLoader);
			}
			if (instance instanceof BeanFactoryAware) {
				((BeanFactoryAware) instance).setBeanFactory(this.beanFactory);
			}
			if (instance instanceof EnvironmentAware) {
				((EnvironmentAware) instance).setEnvironment(this.environment);
			}
			if (instance instanceof ResourceLoaderAware) {
				((ResourceLoaderAware) instance).setResourceLoader(this.resourceLoader);
			}
		}
	}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# selectImports

	@Override
		public Iterable<Entry> selectImports() {
            // 非空
			if (this.autoConfigurationEntries.isEmpty()) {
				return Collections.emptyList();
			}
           // 一下所有都是根据条件注解过滤
			Set<String> allExclusions = this.autoConfigurationEntries.stream()
					.map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
            //
			Set<String> processedConfigurations = this.autoConfigurationEntries.stream()
					.map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
					.collect(Collectors.toCollection(LinkedHashSet::new));
			processedConfigurations.removeAll(allExclusions);

            // 排序
			return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
					.map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
					.collect(Collectors.toList());
		}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# validate

校验核心逻辑

	void validate(ProblemReporter problemReporter) {
		// A configuration class may not be final (CGLIB limitation) unless it declares proxyBeanMethods=false
		Map<String, Object> attributes = this.metadata.getAnnotationAttributes(Configuration.class.getName());
        // 获取 proxyBeanMethods 属性
		if (attributes != null && (Boolean) attributes.get("proxyBeanMethods")) {
            // proxyBeanMethods 为 true 才执行下面逻辑
			if (this.metadata.isFinal()) {
				problemReporter.error(new FinalConfigurationProblem());
			}
			for (BeanMethod beanMethod : this.beanMethods) {
                // 校验 有 BeanMethod类实现
				beanMethod.validate(problemReporter);
			}
		}
	}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

org.springframework.context.annotation.BeanMethod#validate

	@Override
	public void validate(ProblemReporter problemReporter) {
        // 对于静态的方法直接返回
		if (getMetadata().isStatic()) {
		
			return;
		}

        // 包含有配置类注解 Configuration.class
		if (this.configurationClass.getMetadata().isAnnotated(Configuration.class.getName())) 
            {
            // 重写
			if (!getMetadata().isOverridable()) {
				problemReporter.error(new NonOverridableMethodError());
			}
		}
	}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# readaer

image-20230805085003770

	public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
		TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
		for (ConfigurationClass configClass : configurationModel) {
			loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
		}
	}
1
2
3
4
5
6

org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader

这个类负责处理 配置的各种属性

  • 别名
  • ref
  • autowire

核心方法是``org.springframework.context.annotation.ConfigurationClassBeanDefinitionReaderloadBeanDefinitionsForBeanMethod`

随便贴点吧

	private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
		ConfigurationClass configClass = beanMethod.getConfigurationClass();
		MethodMetadata metadata = beanMethod.getMetadata();
		String methodName = metadata.getMethodName();

		// Do we need to mark the bean as skipped by its condition?
		if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
			configClass.skippedBeanMethods.add(methodName);
			return;
		}
		if (configClass.skippedBeanMethods.contains(methodName)) {
			return;
		}

		AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
		Assert.state(bean != null, "No @Bean annotation attributes");

		// Consider name and any aliases
		List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
		String beanName = (!names.isEmpty() ? names.remove(0) : methodName);

		
        // 别名组件
		for (String alias : names) {
			this.registry.registerAlias(beanName, alias);
		}

		// Has this effectively been overridden before (e.g. via XML)?
		if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
			if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
				// ...
			}
			return;
		}

		ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata, beanName);
		beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));

		if (metadata.isStatic()) {
			// static @Bean method
			if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {
				beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());
			}
			else {
				beanDef.setBeanClassName(configClass.getMetadata().getClassName());
			}
			beanDef.setUniqueFactoryMethodName(methodName);
		}
		else {
			// instance @Bean method
			beanDef.setFactoryBeanName(configClass.getBeanName());
			beanDef.setUniqueFactoryMethodName(methodName);
		}

		if (metadata instanceof StandardMethodMetadata) {
			beanDef.setResolvedFactoryMethod(((StandardMethodMetadata) metadata).getIntrospectedMethod());
		}

		beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
		beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
				SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);

		AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);

		Autowire autowire = bean.getEnum("autowire");
		if (autowire.isAutowire()) {
			beanDef.setAutowireMode(autowire.value());
		}

		boolean autowireCandidate = bean.getBoolean("autowireCandidate");
		if (!autowireCandidate) {
			beanDef.setAutowireCandidate(false);
		}

		String initMethodName = bean.getString("initMethod");
		if (StringUtils.hasText(initMethodName)) {
			beanDef.setInitMethodName(initMethodName);
		}

		String destroyMethodName = bean.getString("destroyMethod");
		beanDef.setDestroyMethodName(destroyMethodName);

		// Consider scoping
		ScopedProxyMode proxyMode = ScopedProxyMode.NO;
		AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
		if (attributes != null) {
			beanDef.setScope(attributes.getString("value"));
			proxyMode = attributes.getEnum("proxyMode");
			if (proxyMode == ScopedProxyMode.DEFAULT) {
				proxyMode = ScopedProxyMode.NO;
			}
		}

		// ref
		BeanDefinition beanDefToRegister = beanDef;
		if (proxyMode != ScopedProxyMode.NO) {
			BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
					new BeanDefinitionHolder(beanDef, beanName), this.registry,
					proxyMode == ScopedProxyMode.TARGET_CLASS);
			beanDefToRegister = new ConfigurationClassBeanDefinition(
					(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata, beanName);
		}

		this.registry.registerBeanDefinition(beanName, beanDefToRegister);
	}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105

# AutoConfigurationImportSelector 补充

image-20230804121054483

# 标志位信息

标志位数字,JMV加载后的标志位 由 org.springframework.asm.Opcodes,由于存放在接口中的常量,天然是静态方法

public interface Opcodes {

  // ASM API versions.

  int ASM4 = 4 << 16 | 0 << 8;
  int ASM5 = 5 << 16 | 0 << 8;
  int ASM6 = 6 << 16 | 0 << 8;
  int ASM7 = 7 << 16 | 0 << 8;
  int ASM8 = 8 << 16 | 0 << 8;
  int ASM9 = 9 << 16 | 0 << 8;

  int SOURCE_DEPRECATED = 0x100;
  int SOURCE_MASK = SOURCE_DEPRECATED;
  int V1_1 = 3 << 16 | 45;
  int V1_2 = 0 << 16 | 46;
  int V1_3 = 0 << 16 | 47;
  int V1_4 = 0 << 16 | 48;
  int V1_5 = 0 << 16 | 49;
  int V1_6 = 0 << 16 | 50;
  int V1_7 = 0 << 16 | 51;
  int V1_8 = 0 << 16 | 52;
  int V9 = 0 << 16 | 53;
  int V10 = 0 << 16 | 54;
  int V11 = 0 << 16 | 55;
  int V12 = 0 << 16 | 56;
  int V13 = 0 << 16 | 57;
  int V14 = 0 << 16 | 58;
  int V15 = 0 << 16 | 59;
  int V16 = 0 << 16 | 60;
  int V17 = 0 << 16 | 61;
  int V18 = 0 << 16 | 62;
  int V19 = 0 << 16 | 63;

  /**
   * Version flag indicating that the class is using 'preview' features.
   *
   * <p>{@code version & V_PREVIEW == V_PREVIEW} tests if a version is flagged with {@code
   * V_PREVIEW}.
   */
  int V_PREVIEW = 0xFFFF0000;

  // Access flags values, defined in
  // - https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.1-200-E.1
  // - https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.5-200-A.1
  // - https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.6-200-A.1
  // - https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.25

  int ACC_PUBLIC = 0x0001; // class, field, method
  int ACC_PRIVATE = 0x0002; // class, field, method
  int ACC_PROTECTED = 0x0004; // class, field, method
  int ACC_STATIC = 0x0008; // field, method
  int ACC_FINAL = 0x0010; // class, field, method, parameter
  int ACC_SUPER = 0x0020; // class
  int ACC_SYNCHRONIZED = 0x0020; // method
  int ACC_OPEN = 0x0020; // module
  int ACC_TRANSITIVE = 0x0020; // module requires
  int ACC_VOLATILE = 0x0040; // field
  int ACC_BRIDGE = 0x0040; // method
  int ACC_STATIC_PHASE = 0x0040; // module requires
  int ACC_VARARGS = 0x0080; // method
  int ACC_TRANSIENT = 0x0080; // field
  int ACC_NATIVE = 0x0100; // method
  int ACC_INTERFACE = 0x0200; // class
  int ACC_ABSTRACT = 0x0400; // class, method
  int ACC_STRICT = 0x0800; // method
  int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter, module *
  int ACC_ANNOTATION = 0x2000; // class
  int ACC_ENUM = 0x4000; // class(?) field inner
  int ACC_MANDATED = 0x8000; // field, method, parameter, module, module *
  int ACC_MODULE = 0x8000; // class

  // ASM specific access flags.
  // WARNING: the 16 least significant bits must NOT be used, to avoid conflicts with standard
  // access flags, and also to make sure that these flags are automatically filtered out when
  // written in class files (because access flags are stored using 16 bits only).

  int ACC_RECORD = 0x10000; // class
  int ACC_DEPRECATED = 0x20000; // class, field, method

  // Possible values for the type operand of the NEWARRAY instruction.
  // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html#jvms-6.5.newarray.

  int T_BOOLEAN = 4;
  int T_CHAR = 5;
  int T_FLOAT = 6;
  int T_DOUBLE = 7;
  int T_BYTE = 8;
  int T_SHORT = 9;
  int T_INT = 10;
  int T_LONG = 11;

  // Possible values for the reference_kind field of CONSTANT_MethodHandle_info structures.
  // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.4.8.

  int H_GETFIELD = 1;
  int H_GETSTATIC = 2;
  int H_PUTFIELD = 3;
  int H_PUTSTATIC = 4;
  int H_INVOKEVIRTUAL = 5;
  int H_INVOKESTATIC = 6;
  int H_INVOKESPECIAL = 7;
  int H_NEWINVOKESPECIAL = 8;
  int H_INVOKEINTERFACE = 9;

  // ASM specific stack map frame types, used in {@link ClassVisitor#visitFrame}.

  /** An expanded frame. See {@link ClassReader#EXPAND_FRAMES}. */
  int F_NEW = -1;

  /** A compressed frame with complete frame data. */
  int F_FULL = 0;

  /**
   * A compressed frame where locals are the same as the locals in the previous frame, except that
   * additional 1-3 locals are defined, and with an empty stack.
   */
  int F_APPEND = 1;

  /**
   * A compressed frame where locals are the same as the locals in the previous frame, except that
   * the last 1-3 locals are absent and with an empty stack.
   */
  int F_CHOP = 2;

  /**
   * A compressed frame with exactly the same locals as the previous frame and with an empty stack.
   */
  int F_SAME = 3;

  /**
   * A compressed frame with exactly the same locals as the previous frame and with a single value
   * on the stack.
   */
  int F_SAME1 = 4;

  // Standard stack map frame element types, used in {@link ClassVisitor#visitFrame}.

  Integer TOP = Frame.ITEM_TOP;
  Integer INTEGER = Frame.ITEM_INTEGER;
  Integer FLOAT = Frame.ITEM_FLOAT;
  Integer DOUBLE = Frame.ITEM_DOUBLE;
  Integer LONG = Frame.ITEM_LONG;
  Integer NULL = Frame.ITEM_NULL;
  Integer UNINITIALIZED_THIS = Frame.ITEM_UNINITIALIZED_THIS;

  // The JVM opcode values (with the MethodVisitor method name used to visit them in comment, and
  // where '-' means 'same method name as on the previous line').
  // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html.

  int NOP = 0; // visitInsn
  int ACONST_NULL = 1; // -
  int ICONST_M1 = 2; // -
  int ICONST_0 = 3; // -
  int ICONST_1 = 4; // -
  int ICONST_2 = 5; // -
  int ICONST_3 = 6; // -
  int ICONST_4 = 7; // -
  int ICONST_5 = 8; // -
  int LCONST_0 = 9; // -
  int LCONST_1 = 10; // -
  int FCONST_0 = 11; // -
  int FCONST_1 = 12; // -
  int FCONST_2 = 13; // -
  int DCONST_0 = 14; // -
  int DCONST_1 = 15; // -
  int BIPUSH = 16; // visitIntInsn
  int SIPUSH = 17; // -
  int LDC = 18; // visitLdcInsn
  int ILOAD = 21; // visitVarInsn
  int LLOAD = 22; // -
  int FLOAD = 23; // -
  int DLOAD = 24; // -
  int ALOAD = 25; // -
  int IALOAD = 46; // visitInsn
  int LALOAD = 47; // -
  int FALOAD = 48; // -
  int DALOAD = 49; // -
  int AALOAD = 50; // -
  int BALOAD = 51; // -
  int CALOAD = 52; // -
  int SALOAD = 53; // -
  int ISTORE = 54; // visitVarInsn
  int LSTORE = 55; // -
  int FSTORE = 56; // -
  int DSTORE = 57; // -
  int ASTORE = 58; // -
  int IASTORE = 79; // visitInsn
  int LASTORE = 80; // -
  int FASTORE = 81; // -
  int DASTORE = 82; // -
  int AASTORE = 83; // -
  int BASTORE = 84; // -
  int CASTORE = 85; // -
  int SASTORE = 86; // -
  int POP = 87; // -
  int POP2 = 88; // -
  int DUP = 89; // -
  int DUP_X1 = 90; // -
  int DUP_X2 = 91; // -
  int DUP2 = 92; // -
  int DUP2_X1 = 93; // -
  int DUP2_X2 = 94; // -
  int SWAP = 95; // -
  int IADD = 96; // -
  int LADD = 97; // -
  int FADD = 98; // -
  int DADD = 99; // -
  int ISUB = 100; // -
  int LSUB = 101; // -
  int FSUB = 102; // -
  int DSUB = 103; // -
  int IMUL = 104; // -
  int LMUL = 105; // -
  int FMUL = 106; // -
  int DMUL = 107; // -
  int IDIV = 108; // -
  int LDIV = 109; // -
  int FDIV = 110; // -
  int DDIV = 111; // -
  int IREM = 112; // -
  int LREM = 113; // -
  int FREM = 114; // -
  int DREM = 115; // -
  int INEG = 116; // -
  int LNEG = 117; // -
  int FNEG = 118; // -
  int DNEG = 119; // -
  int ISHL = 120; // -
  int LSHL = 121; // -
  int ISHR = 122; // -
  int LSHR = 123; // -
  int IUSHR = 124; // -
  int LUSHR = 125; // -
  int IAND = 126; // -
  int LAND = 127; // -
  int IOR = 128; // -
  int LOR = 129; // -
  int IXOR = 130; // -
  int LXOR = 131; // -
  int IINC = 132; // visitIincInsn
  int I2L = 133; // visitInsn
  int I2F = 134; // -
  int I2D = 135; // -
  int L2I = 136; // -
  int L2F = 137; // -
  int L2D = 138; // -
  int F2I = 139; // -
  int F2L = 140; // -
  int F2D = 141; // -
  int D2I = 142; // -
  int D2L = 143; // -
  int D2F = 144; // -
  int I2B = 145; // -
  int I2C = 146; // -
  int I2S = 147; // -
  int LCMP = 148; // -
  int FCMPL = 149; // -
  int FCMPG = 150; // -
  int DCMPL = 151; // -
  int DCMPG = 152; // -
  int IFEQ = 153; // visitJumpInsn
  int IFNE = 154; // -
  int IFLT = 155; // -
  int IFGE = 156; // -
  int IFGT = 157; // -
  int IFLE = 158; // -
  int IF_ICMPEQ = 159; // -
  int IF_ICMPNE = 160; // -
  int IF_ICMPLT = 161; // -
  int IF_ICMPGE = 162; // -
  int IF_ICMPGT = 163; // -
  int IF_ICMPLE = 164; // -
  int IF_ACMPEQ = 165; // -
  int IF_ACMPNE = 166; // -
  int GOTO = 167; // -
  int JSR = 168; // -
  int RET = 169; // visitVarInsn
  int TABLESWITCH = 170; // visiTableSwitchInsn
  int LOOKUPSWITCH = 171; // visitLookupSwitch
  int IRETURN = 172; // visitInsn
  int LRETURN = 173; // -
  int FRETURN = 174; // -
  int DRETURN = 175; // -
  int ARETURN = 176; // -
  int RETURN = 177; // -
  int GETSTATIC = 178; // visitFieldInsn
  int PUTSTATIC = 179; // -
  int GETFIELD = 180; // -
  int PUTFIELD = 181; // -
  int INVOKEVIRTUAL = 182; // visitMethodInsn
  int INVOKESPECIAL = 183; // -
  int INVOKESTATIC = 184; // -
  int INVOKEINTERFACE = 185; // -
  int INVOKEDYNAMIC = 186; // visitInvokeDynamicInsn
  int NEW = 187; // visitTypeInsn
  int NEWARRAY = 188; // visitIntInsn
  int ANEWARRAY = 189; // visitTypeInsn
  int ARRAYLENGTH = 190; // visitInsn
  int ATHROW = 191; // -
  int CHECKCAST = 192; // visitTypeInsn
  int INSTANCEOF = 193; // -
  int MONITORENTER = 194; // visitInsn
  int MONITOREXIT = 195; // -
  int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn
  int IFNULL = 198; // visitJumpInsn
  int IFNONNULL = 199; // -
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
编辑 (opens new window)
#springboot
上次更新: 2024-05-21, 09:50:09
mybatis源码阅读
springcloud介绍

← mybatis源码阅读 springcloud介绍→

最近更新
01
LeetCode刷题工具之本地对拍
04-04
02
sublime对应语言模板使用技巧
02-28
03
经典字符串匹配算法
02-05
更多文章>
Theme by Vdoing | Copyright © 2020-2024 wuxin0011 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式