首页 文章 精选 留言 我的

精选列表

搜索[原理],共10002篇文章
优秀的个人博客,低调大师

Docker 架构及工作原理

通过下图可以得知,Docker 在运行时分为 Docker 引擎(服务端守护进程) 和 客户端工具,我们日常使用各种 docker 命令,其实就是在使用 客户端工具 与 Docker 引擎 进行交互。 Client 客户端 Docker 是一个客户端-服务器(C/S)架构程序。Docker 客户端只需要向 Docker 服务器或者守护进程发出请求,服务器或者守护进程将完成所有工作并返回结果。Docker 提供了一个命令行工具 Docker 以及一整套 RESTful API。你可以在同一台宿主机上运行 Docker 守护进程和客户端,也可以从本地的 Docker 客户端连接到运行在另一台宿主机上的远程 Docker 守护进程。 Host 主机(Docker 引擎) 一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。 Image 镜像 什么是 Docker 镜像?简单的理解,Docker 镜像就是一个 Linux 的文件系统(Root FileSystem),这个文件系统里面包含可以运行在 Linux 内核的程序以及相应的数据。 通过镜像启动一个容器,一个镜像就是一个可执行的包,其中包括运行应用程序所需要的所有内容:包含代码,运行时间,库,环境变量和配置文件等。 Docker 把 App 文件打包成为一个镜像,并且采用类似多次快照的存储技术,可以实现: 多个 App 可以共用相同的底层镜像(初始的操作系统镜像); App 运行时的 IO 操作和镜像文件隔离; 通过挂载包含不同配置/数据文件的目录或者卷(Volume),单个 App 镜像可以用来运行无数个不同业务的容器。 Container 容器 镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。 Docker 面向对象 容器 对象 镜像 类 镜像分层 Docker 支持通过扩展现有镜像,创建新的镜像。实际上,Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的。 从上图可以看到,新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。 镜像分层最大的一个好处就是共享资源。比如说有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。 如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如 /etc 下的文件,这时其他容器的 /etc 是不会被修改的,修改只会被限制在单个容器内。这就是容器 Copy-on-Write 特性。 可写的容器层 当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。 所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的。 镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统。如果不同层中有一个相同路径的文件,比如 /a,上层的 /a 会覆盖下层的 /a,也就是说用户只能访问到上层中的文件 /a。在容器层中,用户看到的是一个叠加之后的文件系统。 文件操作 说明 添加文件 在容器中创建文件时,新文件被添加到容器层中。 读取文件 在容器中读取某个文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后打开并读入内存。 修改文件 在容器中修改已存在的文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后修改之。 删除文件 在容器中删除文件时,Docker 也是从上往下依次在镜像层中查找此文件。找到后,会在容器层中记录下此删除操作。(只是记录删除操作) 只有当需要修改时才复制一份数据,这种特性被称作 Copy-on-Write。可见,容器层保存的是镜像变化的部分,不会对镜像本身进行任何修改。 总结下来就是:容器层记录对镜像的修改,所有镜像层都是只读的,不会被容器修改,所以镜像可以被多个容器共享。 Volume 数据卷 实际上我们的容器就好像是一个简易版的操作系统,只不过系统中只安装了我们的程序运行所需要的环境,前边说到我们的容器是可以删除的,那如果删除了,容器中的程序产生的需要持久化的数据怎么办呢?容器运行的时候我们可以进容器去查看,容器一旦删除就什么都没有了。 所以数据卷就是来解决这个问题的,是用来将数据持久化到我们宿主机上,与容器间实现数据共享,简单的说就是将宿主机的目录映射到容器中的目录,应用程序在容器中的目录读写数据会同步到宿主机上,这样容器产生的数据就可以持久化了,比如我们的数据库容器,就可以把数据存储到我们宿主机上的真实磁盘中。 Registry 注册中心 Docker 用 Registry 来保存用户构建的镜像。Registry 分为公共和私有两种。Docker 公司运营公共的 Registry 叫做 Docker Hub。用户可以在 Docker Hub 注册账号,分享并保存自己的镜像。 Docker 公司提供了公共的镜像仓库 https://hub.docker.com(Docker 称之为 Repository)提供了庞大的镜像集合供使用。 一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。 通常,一个仓库会包含同一个软件不同版本的镜像,而标签对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。 总结 Docker 官网写着这样一句话:Build and Ship any Application Anywhere,再结合刚才我们所理解的内容,总结下来就是:一次构建,到处运行。 此外,Docker 公司提供了公共的镜像仓库 https://hub.docker.com(Docker 称之为 Repository),GitHub connect,自动构建镜像,大大简化了应用分发、部署、升级流程。加上 Docker 可以非常方便的建立各种自定义的镜像文件,这些都是 Docker 成为最流行的容器技术的重要因素。 通过以上这些技术的组合,最后的结果就是:绝大部分应用,开发者都可以通过 docker build 创建镜像,通过 docker push 上传镜像,用户通过 docker pull 下载镜像,使用 docker run 运行容器应用。用户不再需要去关心如何搭建环境,如何安装,如何解决不同发行版的库冲突——而且通常不会消耗更多的硬件资源,不会明显降低性能。 从下文开始,我们就进入 Docker 实操部分,先从 Docker 的安装及配置镜像加速讲起,然后再学习一些镜像和容器最常用的命令。 本文采用 知识共享「署名-非商业性使用-禁止演绎 4.0 国际」许可协议。 大家可以通过 分类 查看更多关于 Docker 的文章。 🤗 您的点赞和转发是对我最大的支持。 📢 扫码关注 哈喽沃德先生「文档 + 视频」每篇文章都配有专门视频讲解,学习更轻松噢 ~

优秀的个人博客,低调大师

深入理解EnableAutoConfiguration原理

源码分析@EnableAutoConfiguration在SpringBoot中的加载和实例化过程 万里长征第一步,我们先理解下什么是EnableAutoConfiguration? 什么是EnableAutoConfiguration注解? 在哪? org.springframework.boot.autoconfigure.EnableAutoConfiguration EnableAutoConfiguration概述 我们先来看下源码 package org.springframework.boot.autoconfigure; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.core.io.support.SpringFactoriesLoader; /** * Enable auto-configuration of the Spring Application Context, attempting to guess and * configure beans that you are likely to need. Auto-configuration classes are usually * applied based on your classpath and what beans you have defined. For example, If you * have {@code tomcat-embedded.jar} on your classpath you are likely to want a * {@link TomcatEmbeddedServletContainerFactory} (unless you have defined your own * {@link EmbeddedServletContainerFactory} bean). * <p> * When using {@link SpringBootApplication}, the auto-configuration of the context is * automatically enabled and adding this annotation has therefore no additional effect. * <p> * Auto-configuration tries to be as intelligent as possible and will back-away as you * define more of your own configuration. You can always manually {@link #exclude()} any * configuration that you never want to apply (use {@link #excludeName()} if you don't * have access to them). You can also exclude them via the * {@code spring.autoconfigure.exclude} property. Auto-configuration is always applied * after user-defined beans have been registered. * <p> * The package of the class that is annotated with {@code @EnableAutoConfiguration}, * usually via {@code @SpringBootApplication}, has specific significance and is often used * as a 'default'. For example, it will be used when scanning for {@code @Entity} classes. * It is generally recommended that you place {@code @EnableAutoConfiguration} (if you're * not using {@code @SpringBootApplication}) in a root package so that all sub-packages * and classes can be searched. * <p> * Auto-configuration classes are regular Spring {@link Configuration} beans. They are * located using the {@link SpringFactoriesLoader} mechanism (keyed against this class). * Generally auto-configuration beans are {@link Conditional @Conditional} beans (most * often using {@link ConditionalOnClass @ConditionalOnClass} and * {@link ConditionalOnMissingBean @ConditionalOnMissingBean} annotations). */ @SuppressWarnings("deprecation") @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(EnableAutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; /** * Exclude specific auto-configuration classes such that they will never be applied. * @return the classes to exclude */ Class<?>[] exclude() default {}; /** * Exclude specific auto-configuration class names such that they will never be * applied. * @return the class names to exclude * @since 1.3.0 */ String[] excludeName() default {}; } 类图 注意“@Import(EnableAutoConfigurationImportSelector.class)” 部分。后边源码分析中会使用到。 说明 EnableAutoConfiguration注解的功能大概如下。 开启Spring应该上下文的自动配置,尽可能去加载需要的配置Beans。自动配置类,一般是根据你的classpath路径来应用的。 当你使用了SpringBootApplication注解,在context中自动加载配置就已经开启,不需要其他操作。 可以通过exclude()传入Class类型;excludeName() 传入名称来排除其他类型的加载。自动加载的配置始终是在普通用户定义的Bean加载之后执行。 默认EnableAutoConfiguration扫描的是当前启用注解的Class对象的目录作为root目录。所以这个目录下的所有子目录都会被扫描。 自动装载的配置类,也是常规的SpringBean(被@Configuration修饰,@Configuration则被@Component修饰(如果你写的@Configuration在启动类的包名下,开启注解扫描的情况下,也是会把@Configuration注册为Bean对象。))。当然也可以通过SpringFactoriesLoader的机制来定位到对应的org.springframework.boot.autoconfigure.EnableAutoConfiguration类(不在同用户扫描包目录中)。 一般配合Conditional、ConditionalOnClass、ConditionalOnMissingBean一起使用。 测试项目 │ pom.xml └─src └─main ├─java │ └─com │ └─baigt │ ├─autoconfig │ │ BaigtAutoConfig.java │ │ │ └─sb │ SBStarter.java │ └─resources └─META-INF spring.factories pom <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.baigt</groupId> <artifactId>SpringBootCodeAnalyze</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.14.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> BaigtAutoConfig 注意和启动类不在一个目录中 package com.baigt.autoconfig; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * 测试Autoconfig */ @Configuration public class BaigtAutoConfig { @Bean public String env(){ return new String("Baigt Test"); } } SBStarter 注意和config不在一个目录 中 package com.baigt.sb; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; /** * 测试@EnableAutoConfig加载的流程(加载自定义的配置类,不在同一个目录中) */ @SpringBootApplication public class SBStarter{ public static void main(String[] args) { SpringApplication sb=new SpringApplication(SBStarter.class); ConfigurableApplicationContext run = sb.run(args); System.out.println(run.getBean("baigt",String.class)); } } spring.factories # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.baigt.autoconfig.BaigtAutoConfig 正题(源码) 我们只分析和EnableAutoConfiguration相关的源码。 new SpringApplication 初始化环境(是否是web),设置ApplicationContextInitializer、ApplicationListener,设置启动类的class到mainApplicationClass上。我们的例子中不是web环境。 //初始化入口 public SpringApplication(Object... sources) { initialize(sources); } private void initialize(Object[] sources) { if (sources != null && sources.length > 0) { this.sources.addAll(Arrays.asList(sources)); } this.webEnvironment = deduceWebEnvironment(); setInitializers((Collection) getSpringFactoriesInstances( ApplicationContextInitializer.class)); setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = deduceMainApplicationClass(); } SpringApplication 启动SpringBoot项目,我们这里只关注Context创建和实例化AutoConfig相关的逻辑。注意我们的示例不是Web项目,只是个普通的java项目。 run 这里主要有三处,一个是createApplicationContext,一个是prepareContext,一个是refreshContext。 public ConfigurableApplicationContext run(String... args) { //... ConfigurableApplicationContext context = null; //。。。 listeners.starting(); try { //.... //注意这部分 创建context context = createApplicationContext(); analyzers = new FailureAnalyzers(context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); //刷新context(实例化各种post以及Bean) refreshContext(context); afterRefresh(context, applicationArguments); // ... return context; } catch (Throwable ex) { } } 后边再讲refreshContext。 createApplicationContext 创建Context,我们不是web项目哦。所以我们Context是AnnotationConfigApplicationContext类型。 public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context." + "annotation.AnnotationConfigApplicationContext"; protected ConfigurableApplicationContext createApplicationContext() { Class<?> contextClass = this.applicationContextClass; if (contextClass == null) { try { //前边我们分析到,不是web 环境!! 所以我们Context是AnnotationConfigApplicationContext类型。 contextClass = Class.forName(this.webEnvironment ? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS); } catch (ClassNotFoundException ex) { // } }//这里实例化的是 AnnotationConfigApplicationContext类(无参构造) return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass); } AnnotationConfigApplicationContext 类图 我们先看下类图。 是BeanDefinitionRegistry 是BeanFactory 是Resource AnnotationConfigApplicationContext() 从前边我们了解到,我们的context是AnnotationConfigApplicationContext,无参构造会实例化AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner。因为Autoconfig相关的都会被@Configuration修饰,所以我们只关注AnnotatedBeanDefinitionReader,它是注解BeanDefinition读取器。我们主要分析说明的是这个。 public AnnotationConfigApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); } AnnotatedBeanDefinitionReader AnnotatedBeanDefinitionReader(BeanDefinitionRegistry) AnnotationConfigApplicationContext就是一个BeanDefinitionRegistry实例。将AnnotationConfigApplicationContext的实例传递到AnnotatedBeanDefinitionReader中使用。下边我们分析这个AnnotatedBeanDefinitionReader类实例化过程中都做了什么。 public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) { this(registry, getOrCreateEnvironment(registry)); } public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); Assert.notNull(environment, "Environment must not be null"); this.registry = registry; this.conditionEvaluator = new ConditionEvaluator(registry, environment, null); AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); } AnnotationConfigUtils registerAnnotationConfigProcessors 注册注解相关的后置处理器,比如ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor、EventListenerMethodProcessor、DefaultEventListenerFactory等。我们这里只关注配置类相关的源码部分。 public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) { registerAnnotationConfigProcessors(registry, null); } public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, Object source) { DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4); // 注册ConfigurationClassPostProcessor处理器 if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } return beanDefs; } ConfigurationClassPostProcessor 类图 是BeanDefinitionRegistryPostProcessor 是BeanFactoryPostProcessor 是PriorityOrdered 上边两个接口,是关键,后边要用到!!!! registerPostProcessor 注册ConfigurationClassPostProcessor处理器到BeanFactory中。 private static BeanDefinitionHolder registerPostProcessor( BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) { definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(beanName, definition); return new BeanDefinitionHolder(definition, beanName); } BeanDefinitionRegistry 从入口处我们知道,registry是AnnotationConfigApplicationContext的实例,被传递过来。它的父类是GenericApplicationContext。在无参实例化时,GenericApplicationContext会持有一个DefaultListableBeanFactory对象。 结构图 BeanFactory GenericApplicationContext的实例化BeanFactory过程 private final DefaultListableBeanFactory beanFactory; public GenericApplicationContext() { this.beanFactory = new DefaultListableBeanFactory(); } public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { this.beanFactory.registerBeanDefinition(beanName, beanDefinition); } DefaultListableBeanFactory registerBeanDefinition 将BeanDefinition定义交给BeanFactory管理。主要在beanDefinitionMap、beanDefinitionNames这几个map对象中存储。 public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { Assert.hasText(beanName, "Bean name must not be empty"); Assert.notNull(beanDefinition, "BeanDefinition must not be null"); if (beanDefinition instanceof AbstractBeanDefinition) { try { ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex); } } BeanDefinition oldBeanDefinition; oldBeanDefinition = this.beanDefinitionMap.get(beanName); if (oldBeanDefinition != null) { if (!isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound."); } else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) { // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE if (this.logger.isWarnEnabled()) { this.logger.warn("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } else if (!beanDefinition.equals(oldBeanDefinition)) { if (this.logger.isInfoEnabled()) { this.logger.info("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } else { if (this.logger.isDebugEnabled()) { this.logger.debug("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } this.beanDefinitionMap.put(beanName, beanDefinition); } else { if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) synchronized (this.beanDefinitionMap) { this.beanDefinitionMap.put(beanName, beanDefinition); List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; if (this.manualSingletonNames.contains(beanName)) { Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames); updatedSingletons.remove(beanName); this.manualSingletonNames = updatedSingletons; } } } else { // Still in startup registration phase this.beanDefinitionMap.put(beanName, beanDefinition); this.beanDefinitionNames.add(beanName); this.manualSingletonNames.remove(beanName); } this.frozenBeanDefinitionNames = null; } if (oldBeanDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } } 至此ConfigurationClassPostProcessor已经被BeanFactory管理起来。下边我们再来分析后边这个对象是怎么使用。那么我们再次回到SpringApplication的Run方法中prepareContext和**refreshContext(context);**部分。 SpringApplication prepareContext 我们重点关注下load部分,传入的是当前启动类。source是new SpringApplication时传入的Class对象,也就是SBStarter.class。 private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { //。。。。。 // Load the sources Set<Object> sources = getSources(); Assert.notEmpty(sources, "Sources must not be empty"); load(context, sources.toArray(new Object[sources.size()])); // 。。。。 } load 加载bean到ApplicationContext中.BeanDefinitionLoader是持有Context对象的。Context本身就是个registry. protected void load(ApplicationContext context, Object[] sources) { if (logger.isDebugEnabled()) { logger.debug( "Loading source " + StringUtils.arrayToCommaDelimitedString(sources)); } BeanDefinitionLoader loader = createBeanDefinitionLoader( getBeanDefinitionRegistry(context), sources); if (this.beanNameGenerator != null) { loader.setBeanNameGenerator(this.beanNameGenerator); } if (this.resourceLoader != null) { loader.setResourceLoader(this.resourceLoader); } if (this.environment != null) { loader.setEnvironment(this.environment); } loader.load(); } BeanDefinitionLoader load 我们的source就是SBStarter.class,也就是会执行load((Class<?>) source)。最后注册成类型AnnotatedBeanDefinition的BeanDefinition。 public int load() { int count = 0; for (Object source : this.sources) { count += load(source); } return count; } private int load(Object source) { Assert.notNull(source, "Source must not be null"); if (source instanceof Class<?>) { return load((Class<?>) source); } if (source instanceof Resource) { return load((Resource) source); } if (source instanceof Package) { return load((Package) source); } if (source instanceof CharSequence) { return load((CharSequence) source); } throw new IllegalArgumentException("Invalid source type " + source.getClass()); } private int load(Class<?> source) { if (isGroovyPresent()) { // Any GroovyLoaders added in beans{} DSL can contribute beans here if (GroovyBeanDefinitionSource.class.isAssignableFrom(source)) { GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class); load(loader); } } //如果SBStarter是个组件的话,会注册到beanDefinition上去。 if (isComponent(source)) { //AnnotatedBeanDefinitionReader是前边实例化时创建。目的是注册一个类型AnnotatedBeanDefinition的BeanDefinition this.annotatedReader.register(source); return 1; } return 0; } isComponent @SpringBootApplication是SpringBootConfiguration类型的。 SpringBootConfiguration是Configuration类型的。 Configuration是Component类型的 最后SBStarter也就是个Component类型的 AnnotatedBeanDefinitionReader register //annotatedClasses=com.baigt.sb.SBStarter public void register(Class<?>... annotatedClasses) { for (Class<?> annotatedClass : annotatedClasses) { registerBean(annotatedClass); } } registerBean 这里我们要注意的是我们是创建了一个AnnotatedGenericBeanDefinition类型的BeanDefinition对象通过BeanDefinitionReaderUtils工具进行注册的。 public void registerBean(Class<?> annotatedClass) { registerBean(annotatedClass, null, (Class<? extends Annotation>[]) null); } public void registerBean(Class<?> annotatedClass, Class<? extends Annotation>... qualifiers) { registerBean(annotatedClass, null, qualifiers); } public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) { //注意这里,我是一个AnnotatedGenericBeanDefinition类型的BeanDefinition实例 AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass); if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { return; } ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); abd.setScope(scopeMetadata.getScopeName()); String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); if (qualifiers != null) { for (Class<? extends Annotation> qualifier : qualifiers) { if (Primary.class == qualifier) { abd.setPrimary(true); } else if (Lazy.class == qualifier) { abd.setLazyInit(true); } else { abd.addQualifier(new AutowireCandidateQualifier(qualifier)); } } } BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); //我是在这里和context关联上的 BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); } BeanDefinitionReaderUtils registerBeanDefinition 注意传入的registry,AnnotationConfigApplicationContext本身就是个BeanDefinitionRegistry。而这个部分最后调用的是AnnotationConfigApplicationContext在实例化中隐式实例化父类GenericApplicationContext时创建的一个DefaultListableBeanFactory对象的registerBeanDefinition方法。这就又回到了ConfiguationClassPostProcessor时registerBeanDefinition的过程。因此这里就不再继续深入分析。最终的结果是交给了BeanFactory统一管理BeanDefinition!! public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // Register bean definition under primary name. String beanName = definitionHolder.getBeanName(); registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // Register aliases for bean name, if any. String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { registry.registerAlias(beanName, alias); } } } SpringApplication refreshContext 刷新Context和注册关机钩子;注意传入的是一个AnnotationConfigApplicationContext实例。我们主要分析refresh private void refreshContext(ConfigurableApplicationContext context) { refresh(context); if (this.registerShutdownHook) { try { context.registerShutdownHook(); } catch (AccessControlException ex) { // Not allowed in some environments. } } } protected void refresh(ApplicationContext applicationContext) { Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext); ((AbstractApplicationContext) applicationContext).refresh(); } 刷新用的是AbstractApplicationContext中的refresh方法。 AbstractApplicationContext org.springframework.context.support.AbstractApplicationContext refresh 在ConfigurationClassPostProcessor那一部分,我们知道它是一个BeanFactoryPostProcessor。所以我们一定要看的是invokeBeanFactoryPostProcessors部分的逻辑,其次因为Configuration注解类中相关的如@Bean修饰的方法也是要实例化的,所以我们还要看的是finishBeanFactoryInitialization中的逻辑。 public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // refresh的前置准备,比如设置startTime,开启激活状态、关闭close状态等等等 prepareRefresh(); //告诉子类去刷新内容Bean工厂(从类图中可以明显看出来入口类实例也是个bean工厂) // 观察和刷新BeanFactory ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); //提前设置一些在该context中使用的属性,比如Classloader、Callback、environment等 prepareBeanFactory(beanFactory); try { // 通知context子类,后置处理beanFactory。比如用一系列的Webcontext子类 postProcessBeanFactory(beanFactory); // 将BeanFactoryPostProcessor在当前Context中注册为Bean invokeBeanFactoryPostProcessors(beanFactory); // 注册BeanPostProcessor来拦截Bean创建的后置处理。 registerBeanPostProcessors(beanFactory); // 为当前Context初始化MessageSource initMessageSource(); // 为当前context初始化应用事件广播 initApplicationEventMulticaster(); // 初始化其他特殊的bean对象 比如webcontext onRefresh(); // 检查监听Bean 并发布他们(ApplicationListener) registerListeners(); // 实例化BeanFactory中所有的其他的单例对象集合(非延迟的) finishBeanFactoryInitialization(beanFactory); // 最后发布LifecycleProcessor和ContextRefreshedEvent事件 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // 失败销毁bean 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(); } } } invokeBeanFactoryPostProcessors 使用委托模式来执行BeanFactoryPostProcessors。注意委托类PostProcessorRegistrationDelegate接收的beanFactory是我们的Context实例(是个BeanFactory,同时它也持有ConfigurationClassPostProcessor的BeanDefinition信息)。getBeanFactoryPostProcessors部分中的BeanFactoryPostProcessors是其他步骤中注入的后置器,我们这里不关注。直接进委托类中继续 分析。 protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor) if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } } PostProcessorRegistrationDelegate org.springframework.context.support.PostProcessorRegistrationDelegate invokeBeanFactoryPostProcessors 我们不关注beanFactoryPostProcessors部分传入的参数,因为ConfigurationClassPostProcessor不在此。前边我们分析到ConfigurationClassPostProcessor同时是一个BeanDefinitionRegistryPostProcessor,invokeBeanFactoryPostProcessors中与此有关的逻辑我们重点看下!!! 首先执行实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor 其次执行实现Ordered接口的BeanDefinitionRegistryPostProcessor 最后执行其他所有的BeanDefinitionRegistryPostProcessor对象 public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any. Set<String> processedBeans = new HashSet<String>(); if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>(); List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>(); for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { //省略 } List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>(); // 首先执行一个实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessors!!! 这不就是我们的ConfigurationClassPostProcessor嘛!!! String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // 其次执行一个实现Ordered接口的BeanDefinitionRegistryPostProcessors!!! 且没有在processedBeans中 postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // 最后执行其他 BeanDefinitionRegistryPostProcessor boolean reiterate = true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); reiterate = true; } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); } // Now, invoke the postProcessBeanFactory callback of all processors handled so far. invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // Invoke factory processors registered with the context instance. invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, // Ordered, and the rest. List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>(); List<String> orderedPostProcessorNames = new ArrayList<String>(); List<String> nonOrderedPostProcessorNames = new ArrayList<String>(); for (String ppName : postProcessorNames) { if (processedBeans.contains(ppName)) { // skip - already processed in first phase above } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. sortPostProcessors(priorityOrderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // Next, invoke the BeanFactoryPostProcessors that implement Ordered. List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>(); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } sortPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // Finally, invoke all other BeanFactoryPostProcessors. List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>(); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); // Clear cached merged bean definitions since the post-processors might have // modified the original metadata, e.g. replacing placeholders in values... beanFactory.clearMetadataCache(); } 我们只关注第一个,因为ConfigurationClassPostProcessor实现了PriorityOrdered接口!!!! invokeBeanDefinitionRegistryPostProcessors 传入的postProcessors是ConfigurationClassPostProcessor,传入的registry则是我们的AnnotationConfigApplicationContext(前边也提到了他也是个BeanDefinitionRegistry)。哇偶!终于到了我们ConfigurationClassPostProcessor的源码部分了(postProcessBeanDefinitionRegistry) private static void invokeBeanDefinitionRegistryPostProcessors( Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) { for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) { postProcessor.postProcessBeanDefinitionRegistry(registry); } } ConfigurationClassPostProcessor postProcessBeanDefinitionRegistry 这个方法比较简单,有些检查,核心方法是processConfigBeanDefinitions。我们跟进去看下。 public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { int registryId = System.identityHashCode(registry); if (this.registriesPostProcessed.contains(registryId)) { throw new IllegalStateException( "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry); } if (this.factoriesPostProcessed.contains(registryId)) { throw new IllegalStateException( "postProcessBeanFactory already called on this post-processor against " + registry); } this.registriesPostProcessed.add(registryId); processConfigBeanDefinitions(registry); } processConfigBeanDefinitions 类的Doc说明是构建和验证由Configuration注解修饰的Class对象。注意注入的BeanDefinitionRegistry是一个DefaultListableBeanFactory实例,因此也是一个SingletonBeanRegistry对象。具体可自行分析类图的继承关系。这里会加载我们启动类SBStarter这个配置类。 启动类SBStarter是我们自定义的类,是在org.springframework.boot.SpringApplication#prepareContext步骤中注入的。 /** * Build and validate a configuration model based on the registry of * {@link Configuration} classes. */ public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>(); String[] candidateNames = registry.getBeanDefinitionNames(); for (String beanName : candidateNames) { BeanDefinition beanDef = registry.getBeanDefinition(beanName); //是否已经加载过 if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) || ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) { } //没有加载过 就放入configCandidates集合中 这里只有我们手写的启动类SBStarter是没有被加载过的。具体加载过程上边我们已经说过了 我们这里看下SBStarter的后续操作。 else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); } } // 没有就快速返回 if (configCandidates.isEmpty()) { return; } // 根据Order排序 Collections.sort(configCandidates, new Comparator<BeanDefinitionHolder>() { @Override public int compare(BeanDefinitionHolder bd1, BeanDefinitionHolder bd2) { int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0; } }); // 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 && sbr.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) { BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR); this.componentScanBeanNameGenerator = generator; this.importBeanNameGenerator = generator; } } // 解析每一个 @Configuration class 这里只解析到我们开启SpringBootApplication注解的SBStarter类是Configuration class,我们写的那个不在扫描路径中。 ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates); Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size()); do { //从SBStarter为入口解析Configuration相关Class parser.parse(candidates); parser.validate(); Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(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()); } // 在这里加载成BeanDefinition 并交给BeanFactory管理。 this.reader.loadBeanDefinitions(configClasses); alreadyParsed.addAll(configClasses); candidates.clear(); if (registry.getBeanDefinitionCount() > candidateNames.length) { String[] newCandidateNames = registry.getBeanDefinitionNames(); Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames)); Set<String> alreadyParsedClasses = new HashSet<String>(); 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; } } while (!candidates.isEmpty()); // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes if (sbr != null) { if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) { sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry()); } } if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) { ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache(); } } ConfigurationClassParser parse(set) 这里主要分析两个部分,一个是再次Parse(不同入参),一个是完整流程(processDeferredImportSelectors()) SBStarter注入的BeanDefiniton是个AnnotatedBeanDefinition 触发parse(AnnotationMetadata metadata, String beanName)调用 public void parse(Set<BeanDefinitionHolder> configCandidates) { this.deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>(); for (BeanDefinitionHolder holder : configCandidates) { BeanDefinition bd = holder.getBeanDefinition(); try { if (bd instanceof AnnotatedBeanDefinition) { parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName()); } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) { parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName()); } else { parse(bd.getBeanClassName(), holder.getBeanName()); } } catch (BeanDefinitionStoreException ex) { throw ex; } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex); } } processDeferredImportSelectors(); } parse(AnnotationMetadata, String) protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException { processConfigurationClass(new ConfigurationClass(metadata, beanName)); } processConfigurationClass 处理ConfigurationClass对象。主要是doProcessConfigurationClass部分。 protected void processConfigurationClass(ConfigurationClass configClass) throws IOException { if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) { return; } ConfigurationClass existingClass = this.configurationClasses.get(configClass); if (existingClass != null) { if (configClass.isImported()) { if (existingClass.isImported()) { existingClass.mergeImportedBy(configClass); } // Otherwise ignore new imported config class; existing non-imported class overrides it. return; } else { // Explicit bean definition found, probably replacing an import. // Let's remove the old one and go with the new one. this.configurationClasses.remove(configClass); for (Iterator<ConfigurationClass> it = this.knownSuperclasses.values().iterator(); it.hasNext();) { if (configClass.equals(it.next())) { it.remove(); } } } } // Recursively process the configuration class and its superclass hierarchy. SourceClass sourceClass = asSourceClass(configClass); do { sourceClass = doProcessConfigurationClass(configClass, sourceClass); } while (sourceClass != null); this.configurationClasses.put(configClass, configClass); } doProcessConfigurationClass 这里很重要了,也是很复杂的一部分。不过也是SpringBoot可以不使用Xml就能扫描注解相关类的关键部分。下边大概涉及到@PropertySources,@PropertySource,@ComponentScans.class, @ComponentScan.class,@Import,@ImportSource等等。我们主要关注的是@Import部分。为什么?因为我们还是目的就是想看@EnableAutoConfiguration是怎么加载不同目录下的配置类,并实例化的!!! 而在@EnableAutoConfiguration中有使用了@Import,@Import(EnableAutoConfigurationImportSelector.class) protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) throws IOException { // 处理成员class 比如内部class 静态class processMemberClasses(configClass, sourceClass); // 处理 @PropertySource annotations for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) { if (this.environment instanceof ConfigurableEnvironment) { processPropertySource(propertySource); } else { logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment"); } } // 处理 @ComponentScan annotations Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class); if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) { for (AnnotationAttributes componentScan : componentScans) { // The config class is annotated with @ComponentScan -> perform the scan immediately Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); // Check the set of scanned definitions for any further config classes and parse recursively if needed for (BeanDefinitionHolder holder : scannedBeanDefinitions) { BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition(); if (bdCand == null) { bdCand = holder.getBeanDefinition(); } if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { parse(bdCand.getBeanClassName(), holder.getBeanName()); } } } } // 处理 any @Import annotations 我们Spring.factories就是在这一部分 会解析出org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelector processImports(configClass, sourceClass, getImports(sourceClass), true); // 处理 any @ImportResource annotations 如果手动引入了xml配置文件 基本是这种的 if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) { AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class); String[] resources = importResource.getStringArray("locations"); Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader"); for (String resource : resources) { String resolvedResource = this.environment.resolveRequiredPlaceholders(resource); configClass.addImportedResource(resolvedResource, readerClass); } } // Process individual @Bean methods Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); for (MethodMetadata methodMetadata : beanMethods) { configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); } // Process default methods on interfaces processInterfaces(configClass, sourceClass); // Process superclass, if any if (sourceClass.getMetadata().hasSuperClass()) { String superclass = sourceClass.getMetadata().getSuperClassName(); if (!superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) { this.knownSuperclasses.put(superclass, configClass); // Superclass found, return its annotation metadata and recurse return sourceClass.getSuperClass(); } } // No superclass -> processing is complete return null; } processImports 从EnableAutoConfigurationImportSelector中获取Spring.factories中key=org.springframework.boot.autoconfigure.EnableAutoConfiguration的需要自动化加载的配置类。最后存放在deferredImportSelectors集合中。 private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass, Collection<SourceClass> importCandidates, boolean checkForCircularImports) { if (importCandidates.isEmpty()) { return; } if (checkForCircularImports && isChainedImportOnStack(configClass)) { this.problemReporter.error(new CircularImportProblem(configClass, this.importStack)); } else { this.importStack.push(configClass); try { for (SourceClass candidate : importCandidates) { if (candidate.isAssignable(ImportSelector.class)) { // Candidate class is an ImportSelector -> delegate to it to determine imports Class<?> candidateClass = candidate.loadClass(); //实例化EnableAutoConfigurationImportSelector 存放在deferredImportSelectors中 ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class); ParserStrategyUtils.invokeAwareMethods( selector, this.environment, this.resourceLoader, this.registry); if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) { this.deferredImportSelectors.add( new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector)); } else { String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata()); Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames); processImports(configClass, currentSourceClass, importSourceClasses, false); } } else { //省略代码 } } } catch (BeanDefinitionStoreException ex) { // } finally { this.importStack.pop(); } } } parse(Set<BeanDefinitionHolder> configCandidates) 返回到此处,执行 processDeferredImportSelectors方法。处理刚才存放在deferredImportSelectors中的import对象。 public void parse(Set<BeanDefinitionHolder> configCandidates) { this.deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>(); for (BeanDefinitionHolder holder : configCandidates) { BeanDefinition bd = holder.getBeanDefinition(); try { if (bd instanceof AnnotatedBeanDefinition) { parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName()); } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) { parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName()); } else { parse(bd.getBeanClassName(), holder.getBeanName()); } } catch (BeanDefinitionStoreException ex) { throw ex; } } //处理我们刚才存放在这里的deferredImportSelectors processDeferredImportSelectors(); } processDeferredImportSelectors 调用ImportSelector类的selectImports方法,最后递归调用processImports来处理其他Configuration类。这里我们来看下EnableAutoConfigurationImportSelector的selectImports方法。 private void processDeferredImportSelectors() { List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors; this.deferredImportSelectors = null; Collections.sort(deferredImports, DEFERRED_IMPORT_COMPARATOR); for (DeferredImportSelectorHolder deferredImport : deferredImports) { ConfigurationClass configClass = deferredImport.getConfigurationClass(); try { String[] imports = deferredImport.getImportSelector().selectImports(configClass.getMetadata()); processImports(configClass, asSourceClass(configClass), asSourceClasses(imports), false); } catch (BeanDefinitionStoreException ex) { } } } EnableAutoConfigurationImportSelector @EnableAutoConfiguration 中@Import引入的ImportSelector。我们Ctrl+F12来看下selectImports方法在哪? AutoConfigurationImportSelector EnableAutoConfigurationImportSelector 的父类。selectImports方法所在的类。我们重点关注getCandidateConfigurations方法的源码。通过SpringFactoriesLoader.loadFactoryNames来加载spring.factories中对应key为EnableAutoConfiguration的ConfigClass集合。 public String[] selectImports(AnnotationMetadata annotationMetadata) { //如果不是EnableAutoConfigurationImportSelector的时候 isEnabled==true 默认AutoConfigurationImportSelector的isEnable==true ,走后边的逻辑 if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } try { AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader .loadMetadata(this.beanClassLoader); AnnotationAttributes attributes = getAttributes(annotationMetadata); //获取需要自动化加载配置类 这个是核心类。我们下边分析 List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); //删除重复的configClass configurations = removeDuplicates(configurations); //排序 configurations = sort(configurations, autoConfigurationMetadata); Set<String> exclusions = getExclusions(annotationMetadata, attributes); //删除exclue掉的Class checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); //处理AutoConfigurationImportFilter configurations = filter(configurations, autoConfigurationMetadata); //处理AutoConfigurationImportListener fireAutoConfigurationImportEvents(configurations, exclusions); return configurations.toArray(new String[configurations.size()]); } catch (IOException ex) { throw new IllegalStateException(ex); } } // 通过SpringFactoriesLoader加载EnableAutoConfiguration相关的配置类 protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames( getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you " + "are using a custom packaging, make sure that file is correct."); return configurations; } // 要通过SpringFactories来加载的类 protected Class<?> getSpringFactoriesLoaderFactoryClass() { return EnableAutoConfiguration.class; } SpringFactoriesLoader loadFactoryNames //从META-INF/spring.factories的文件中解析内容(所有的spring.factories。包括spring-boot-1.5.14.RELEASE.jar中的)。从中拿到org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的配置类,比如我们自己定义的BaigtAutoConfig类。 public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"; public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) { //factoryClassName=org.springframework.boot.autoconfigure.EnableAutoConfiguration String factoryClassName = factoryClass.getName(); try { //从META-INF/spring.factories的文件中解析内容(所有的spring.factories。包括spring-boot-1.5.14.RELEASE.jar中的) Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); List<String> result = new ArrayList<String>(); while (urls.hasMoreElements()) { URL url = urls.nextElement(); //转换为Properties Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url)); //从properties中获取EnableAutoConfiguration对应的Value 比如我们的com.baigt.autoconfig.BaigtAutoConfig String factoryClassNames = properties.getProperty(factoryClassName); result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames))); } return result; } catch (IOException ex) { } } 接下来我们返回到ConfigurationClassPostProcessor的processConfigBeanDefinitions方法。 ConfigurationClassPostProcessor processConfigBeanDefinitions 接下来我们来看下**this.reader.loadBeanDefinitions(configClasses);**加载我们配置类,交给beanFactory管理。 public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>(); String[] candidateNames = registry.getBeanDefinitionNames(); //。。。。 // Parse each @Configuration class ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates); Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size()); do { parser.parse(candidates); parser.validate(); Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(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()); } this.reader.loadBeanDefinitions(configClasses); alreadyParsed.addAll(configClasses); } ConfigurationClassBeanDefinitionReader loadBeanDefinitions 我们只关注我们定义的配置类(BaigtAutoConfig) public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) { TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator(); for (ConfigurationClass configClass : configurationModel) { loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator); } } loadBeanDefinitionsForConfigurationClass 处理配置类中上的注解(比如Import),以及@Bean方法 private void loadBeanDefinitionsForConfigurationClass( ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) { if (trackedConditionEvaluator.shouldSkip(configClass)) { String beanName = configClass.getBeanName(); if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) { this.registry.removeBeanDefinition(beanName); } this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName()); return; } // BaigtAutoConfig是通过Import(SelectImports)来创建的ConfigClass 所以这里是true if (configClass.isImported()) { //将该配置类注册为BeanDefinition registerBeanDefinitionForImportedConfigurationClass(configClass); } // BaigtAutoConfig中有个@Bean修饰的方法 也会执行这个方法 for (BeanMethod beanMethod : configClass.getBeanMethods()) { loadBeanDefinitionsForBeanMethod(beanMethod); } //配置类中如果使用了ImportSource注解和ImportBeanDefinitionRegistrar。则去加载相关内容成BeanDefinition loadBeanDefinitionsFromImportedResources(configClass.getImportedResources()); loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars()); } registerBeanDefinitionForImportedConfigurationClass 将BaigtAutoConfig配置类注册为BeanDefinition private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) { AnnotationMetadata metadata = configClass.getMetadata(); AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata); ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef); configBeanDef.setScope(scopeMetadata.getScopeName()); String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry); AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata); BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); // 注册我们的BaigtAutoConfig this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition()); configClass.setBeanName(configBeanName); } loadBeanDefinitionsForBeanMethod 解析@Bean方法中相关的属性,比如设置factoryMethod、InitMethod、DestroyMethod、beanName、alias等。也设置lazy、dependOn等等。最后this.registry.registerBeanDefinition(beanName, beanDefToRegister); 完成配置类中@Bean方法的注册。this.registry又是我们前边提到的DefaultListableBeanFactory。交给BeanFactory管理。 private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) { ConfigurationClass configClass = beanMethod.getConfigurationClass(); MethodMetadata metadata = beanMethod.getMetadata(); String methodName = metadata.getMethodName(); // 这一步(shouldSkip)会设置mergedBeanDefinitions中该name的scope为单例。即使没有这个在最后判断的时候scope=""时也等价于单例 if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) { configClass.skippedBeanMethods.add(methodName); return; } if (configClass.skippedBeanMethods.contains(methodName)) { return; } // Consider name and any aliases AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class); List<String> names = new ArrayList<String>(Arrays.asList(bean.getStringArray("name"))); String beanName = (!names.isEmpty() ? names.remove(0) : methodName); // Register aliases even when overridden 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())) { throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(), beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() + "' clashes with bean name for containing configuration class; please make those names unique!"); } return; } ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata); beanDef.setResource(configClass.getResource()); beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource())); if (metadata.isStatic()) { // static @Bean method beanDef.setBeanClassName(configClass.getMetadata().getClassName()); beanDef.setFactoryMethodName(methodName); } else { // instance @Bean method beanDef.setFactoryBeanName(configClass.getBeanName()); beanDef.setUniqueFactoryMethodName(methodName); } beanDef.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR); beanDef.setAttribute(RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE); AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata); Autowire autowire = bean.getEnum("autowire"); if (autowire.isAutowire()) { beanDef.setAutowireMode(autowire.value()); } String initMethodName = bean.getString("initMethod"); if (StringUtils.hasText(initMethodName)) { beanDef.setInitMethodName(initMethodName); } String destroyMethodName = bean.getString("destroyMethod"); if (destroyMethodName != null) { 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; } } // Replace the original bean definition with the target one, if necessary 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); } if (logger.isDebugEnabled()) { logger.debug(String.format("Registering bean definition for @Bean method %s.%s()", configClass.getMetadata().getClassName(), beanName)); } this.registry.registerBeanDefinition(beanName, beanDefToRegister); } 接下来,我们回到 AbstractApplicationContext#refresh AbstractApplicationContext refresh finishBeanFactoryInitialization(beanFactory); finishBeanFactoryInitialization 通过beanFactory来实例化我们之前交给它管理的BeanDefinition。 protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { //省略一些代码 // 实例化一些单例(non-lazyinit) beanFactory.preInstantiateSingletons(); } DefaultListableBeanFactory preInstantiateSingletons 实例化beanDefinitionNames中定义BeanDefinition的单例。当然也包含我们的BaigtAutoConfig中对应的@Bean(name="baigt")方法的BeanDefinition public void preInstantiateSingletons() throws BeansException { // 从我们放入到beanDefinitionNames中来遍历进行实例化。 List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans... for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName); boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { @Override public Boolean run() { return ((SmartFactoryBean<?>) factory).isEagerInit(); } }, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } else { // 最后执行这个方法进行实例化 getBean(beanName); } } } // SmartInitializingSingleton的处理 } AbstractBeanFactory getBean public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); } doGetBean 这里我们就是要创建单例的实例(有就从缓存中取)。创建的方式是通过ObjectFactory内部类实现中的createBean方法来完成。我们先看下getSingleton的逻辑。 // 首次进来为空 最后会走下边的逻辑 Object sharedInstance = getSingleton(beanName); // 通过this.beanDefinitionMap得到的 具体可自行查看源码。这里不太花篇幅讲述。 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); //... if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { try { //最终创建Bean的逻辑 return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } //.... // 注意这里,会把单例cache起来,在后边可以直接使用 if (newSingleton) { addSingleton(beanName, singletonObject); } DefaultSingletonBeanRegistry getSingleton 这里我们要分析的核心逻辑(instance singleton)是调用的了ObjectFactory.getObject,即我们上边的内部类,而内部类的实现则是通过createBean完成。我们再来看下createBean的逻辑。 try { //回到了AbstractBeanFactory#doGetBean的ObjectFactory的getObject方法,执行其中的createBean方法 singletonObject = singletonFactory.getObject(); newSingleton = true; } AbstractAutowireCapableBeanFactory createBean AbstractBeanFactory的子类实现方法 AbstractAutowireCapableBeanFactory#createBean(java.lang.Class<T>) public <T> T createBean(Class<T> beanClass) throws BeansException { // Use prototype bean definition, to avoid registering bean as dependent bean. RootBeanDefinition bd = new RootBeanDefinition(beanClass); bd.setScope(SCOPE_PROTOTYPE); bd.allowCaching = ClassUtils.isCacheSafe(beanClass, getBeanClassLoader()); return (T) createBean(beanClass.getName(), bd, null); } // 接上 protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException { RootBeanDefinition mbdToUse = mbd; Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { } try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { } // 普通Bean的实例创建 Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isDebugEnabled()) { logger.debug("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } doCreateBean 核心关注instanceWrapper和exposedObject对象的处理过程 BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { //创建bean实例的Wrapper对象 instanceWrapper = createBeanInstance(beanName, mbd, args); } // bean实例在wrapper中已经创建了(不完整) final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); //省略一些代码。。。 // Initialize the bean instance. Object exposedObject = bean; try { // 注入property到Bean中 populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) { exposedObject = initializeBean(beanName, exposedObject, mbd); } } //省略一些代码。。。 return exposedObject; createBeanInstance instanceWrapper = createBeanInstance(beanName, mbd, args); 该方法是给指定的name的Class创建Bean对象,支持无参、factoryMethod、AutoWireConstructor三种策略。默认执行无参的"instantiateBean"。而我们的BaigtAutoConfig中的@Bean则设置的有FactoryMethodName(我们定义的@Bean的方法名="env") protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { // Make sure bean class is actually resolved at this point. Class<?> beanClass = resolveBeanClass(mbd, beanName); if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName()); } //配置类中的@Bean方法是通过下边这种方式实例化的。 if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); } // Shortcut when re-creating the same bean... boolean resolved = false; boolean autowireNecessary = false; if (args == null) { synchronized (mbd.constructorArgumentLock) { if (mbd.resolvedConstructorOrFactoryMethod != null) { resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; } } } // 一般我们不是FactoryMethod和有参构造(也可以有哈) if (resolved) { if (autowireNecessary) { return autowireConstructor(beanName, mbd, null, null); } else { return instantiateBean(beanName, mbd); } } // Need to determine the constructor... Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); } //没有特殊处理就使用无参构造实例 // No special handling: simply use no-arg constructor. return instantiateBean(beanName, mbd); } instantiateUsingFactoryMethod protected BeanWrapper instantiateUsingFactoryMethod( String beanName, RootBeanDefinition mbd, Object[] explicitArgs) { return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs); } ConstructorResolver instantiateUsingFactoryMethod BeanWrapperImpl bw = new BeanWrapperImpl(); this.beanFactory.initBeanWrapper(bw); //。。。。 Object beanInstance; beanInstance = this.beanFactory.getInstantiationStrategy().instantiate( mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse); bw.setBeanInstance(beanInstance); return bw; SimpleInstantiationStrategy instantiate 最后调用@Bean对应的方法的invoke方法。到此配置类中的@Bean已经实例化完成。 public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner, Object factoryBean, final Method factoryMethod, Object... args) { try { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { ReflectionUtils.makeAccessible(factoryMethod); return null; } }); } else { ReflectionUtils.makeAccessible(factoryMethod); } Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get(); try { currentlyInvokedFactoryMethod.set(factoryMethod); //执行方法 return factoryMethod.invoke(factoryBean, args); } finally { if (priorInvokedFactoryMethod != null) { currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod); } else { currentlyInvokedFactoryMethod.remove(); } } } catch (IllegalArgumentException ex) { throws ex; } } AbstractAutowireCapableBeanFactory 返回到doCreateBean方法 doCreateBean 我们继续看exposedObject处理的内容。装载Bean的Property属性,initBean对象。我们着重看下initializeBean方法。 final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); Object exposedObject = bean; try { //装载比如Property属性 可以是其他Bean对象,也可能是String等基本属性。 具体见populateBean中的applyPropertyValues方法 populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) { //初始化Bean对象 exposedObject = initializeBean(beanName, exposedObject, mbd); } } initializeBean org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition) 初始化给定的Bean,(RootBeanDefinition为空时,执行BeanPost)执行wired的相关方法((BeanNameAware、BeanClassLoaderAware、BeanFactoryAware))、执行initMethod。比如InitializingBean#afterPropertiesSet();或者是自定义的init方法。 protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { invokeAwareMethods(beanName, bean); return null; } }, getAccessControlContext()); } else { //执行wire的method(BeanNameAware、BeanClassLoaderAware、BeanFactoryAware) invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { //执行init方法 invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; } invokeInitMethods org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods。执行afterPropertiesSet方法。如果是自定义的init方法,就调用invokeCustomInitMethod。 protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isDebugEnabled()) { logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws Exception { ((InitializingBean) bean).afterPropertiesSet(); return null; } }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { ((InitializingBean) bean).afterPropertiesSet(); } } if (mbd != null) { String initMethodName = mbd.getInitMethodName(); if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { invokeCustomInitMethod(beanName, bean, mbd); } } } AbstractApplicationContext 返回到refresh方法 refresh 至此配置类相关的Bean实例化完成。 // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); 其他Bean 我们这里只关注的是配置类的加载,普通Bean的加载可以看我的另外一篇文章 彻底弄懂Spring中Bean的解析、创建和使用 结语 分析使用的Spring版本为4.3.18。代码上如有出入,请自行区分。最后如有不对,欢迎指正。 作者:ricky QQ交流群:244930845。

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册