由一个简单的例子引出本文代码如下：user.java @Data public class User { private String username; private int id; } userbean.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean name="user" class="com.mryan.springcore.demo.User"> <property name="username" value="MRyan"></property> <property name="id" value="666"></property> </bean> </beans> 启动类，并实现了ApplicationRunner方法 @SpringBootApplication public class DemoApplication implements CommandLineRunner { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @Override public void run(String... args) throws Exception { ApplicationContext context = new ClassPathXmlApplicationContext("userbean.xml"); User user = (User) context.getBean("user"); System.out.println(user.toString()); } } xml配置文件向spring ioc容器中注册一个bean，并运行程序打印bean信息。成功打印结果。我们会发现貌似我们什么都不用知道，spring框架都替我们想到了，我们几乎不用做什么，spring框架替我们做了，那么问题来了，它是怎么做到的呢？对象到底是怎么创建的呢？在阅读源码之前我们先补一下知识知识小课堂1. 我们可以用XML，配置类，注解等方式来定义bean信息，容器会读取bean信息，那容器如何能兼容读取这些不同方式定义的bean信息？spring为我们定义了一个BeanDefinitionReader的统一抽象层，专门读取bean信息2. 获得了bean信息我们可以直接用反射的方式获取对象这是我们的线性思维,显然是不合理的。spring中引用了工厂模式为我们创建bean的实例，工厂类名为BeanFactory3. 对象的创建过程分为实例化分配内存，和初始化。 spring中对象的创建也不例外，除了bean的实例化还需要对属性进行填充值，当然还需要执行自定义初始方法init-method（源码中见）4. 在不同的阶段如果要做不同的操作怎么办？ spring中为我们创建了观察者模式：包括监听器，事件发布，当发布不同的事件之后，监听器接受到之后开始做相应的处理工作源码分析启动类ApplicationContext 处打断点一步一步调试 @SpringBootApplication public class DemoApplication implements CommandLineRunner { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @Override public void run(String... args) throws Exception { ApplicationContext context = new ClassPathXmlApplicationContext("userbean.xml");//断点处 User user = (User) context.getBean("user"); System.out.println(user.toString()); } } 进入ClassPathXmlApplicationContext中 public ClassPathXmlApplicationContext(String configLocation) throws BeansException { this(new String[] {configLocation}, true, null); } public ClassPathXmlApplicationContext( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { //使用给定的父上下文创建一个新的AbstractXmlApplicationContext super(parent); //设置此应用程序上下文的配置位置 setConfigLocations(configLocations); if (refresh) { //核心 refresh(); } } 继续debug进入refresh方法，下面对于一些非核心的方法选择性跳过，只分析核心代码，对于refresh方法也可以看之前我写的文章《SpringBoot源码分析》 Context初始化流程 @Override public void refresh() throws BeansException, IllegalStateException { //1 加锁，确保了同一时间startupShutdownMonitor的状态不发生改变。 synchronized (this.startupShutdownMonitor) { //2 为刷新做准备 设置启动日期和活跃状态等 prepareRefresh(); //3 ****核心**** ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); //4 准备BeanFactory 各种设置 各种register这里不做叙述 prepareBeanFactory(beanFactory); try { //5 ****核心**** postProcessBeanFactory(beanFactory); //6 执行BeanFactoryPostProcessors 实例化并且执行已经注册了的BeanFactoryPostProcessors invokeBeanFactoryPostProcessors(beanFactory); //7 实例化并且注册所有BeanPostProcessor的Beans registerBeanPostProcessors(beanFactory); //8 国际化配置 initMessageSource(); //9 初始化应用事件广播器。事件广播器用来向 ApplicationListener 通知各种应用产生的事件，是一个标准的观察者模式。 initApplicationEventMulticaster(); //10 是留给子类的扩展步骤，用来让特定的 Context 子类初始化其他的 Bean。 onRefresh(); //11 把实现了 ApplicationListener 的 Bean 注册到事件广播器，并对广播器中的早期未广播事件进行通知。观察者模式：包括监听器，事件发布，当发布不同的事件之后，监听器接受到之后开始做相应的处理工作 registerListeners(); // 12 ****核心**** finishBeanFactoryInitialization(beanFactory); // 13 完成上下文的刷新工作，调用 LifecycleProcessor 的 onFresh() 方法以及发布 ContextRefreshedEvent 事件。 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } destroyBeans(); cancelRefresh(ex); throw ex; } finally { //14 resetCommonCaches(); } } } 在3处 根据代码命名我们很容易猜到obtainFreshBeanFactory方法作用是获取BeanFactory，并加载bean定义信息进入方法 protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { //判断当前容器中是否由BeanFactory，如果由就销毁，没有则创建 refreshBeanFactory(); //返回BeanFactory return getBeanFactory(); } 进入refreshBeanFactory方法 @Override protected final void refreshBeanFactory() throws BeansException { //判断当前的beanFactory是否为空，不为空则证明当前容器中存在BeanFactory进行销毁，否则创建BeanFactory if (hasBeanFactory()) {// return (this.beanFactory != null); destroyBeans(); closeBeanFactory(); } try { //创建BeanFactory DefaultListableBeanFactory beanFactory = createBeanFactory(); //设置序列号ID beanFactory.setSerializationId(getId()); //自定义BeanFactory customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); this.beanFactory = beanFactory; } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } } 可以发现此时beanDefiinitionMap中就存在了之前定义的bean信息在5处：进入postProcessBeanFactory方法 protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { } 空的方法，这其实是Spring为我们提供让我们自行扩展的方法，在上面我们获取了BeanDefinition，在放入BeanFactory之前我们可以对bean信息进行修改等操作，我们就可以实现BeanFactoryPostProcessor并重写postProcessBeanFactory方法在其中添加逻辑代码。在第12处开始就进入最最最核心的地方。进入finishBeanFactoryInitialization内部 protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // 为此上下文初始化转换服务。 if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } // 如果之前没有任何bean后处理器（例如，PropertyPlaceholderConfigurer Bean）进行注册，请注册默认的嵌入式值解析器：此时，主要用于解析注释属性值。 if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); } // 尽早初始化LoadTimeWeaverAware Bean，以便尽早注册其转换器。 String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // 停止使用临时ClassLoader进行类型匹配。 beanFactory.setTempClassLoader(null); // 允许缓存所有bean定义元数据，而不期望进一步的更改。 beanFactory.freezeConfiguration(); // ****核心**** 实例化所有剩余的（非延迟初始化）单例。 beanFactory.preInstantiateSingletons(); } 我们可以看到最后一行标注核心的代码，我们继续进入方法 @Override public void preInstantiateSingletons() throws BeansException { ****省略之前 List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // 触发所有非惰性单例bean的初始化... for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); //如果它不是抽象的并且是单例是懒加载的才进入此判断语句 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { //如果FactoryBean中存在该beanName走此判断语句 if (isFactoryBean(beanName)) { Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); if (bean instanceof FactoryBean) { FactoryBean<?> factory = (FactoryBean<?>) bean; boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged( (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } } //以上不符合条件 显然跳到了这里 else { getBean(beanName); } } } ***省略之后 首先核心代码处for循环，从beanDefinitionNames中获取BeanName，显而易见本例中只有一个beanName=user进入getBean方法 @Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); } 在进入doGetBean方法 protected <T> T doGetBean( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { ***省略以上代码 // Create bean instance. if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { //断点 return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } ***省略以下代码 如果是单例的话进入判断，进入createBean方法 此时完成对bean的创建 @Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { ***省略以上代码 try { //doCreateBean 实际创建指定的bean Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); } } 进入doCreateBean方法 此时才进行Bean的实例化 protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { // 实例化bean BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { //*****核心***** 使用适当的实例化策略为指定的bean创建一个新实例 instanceWrapper = createBeanInstance(beanName, mbd, args); } Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } 来看看createBeanInstance做了什么吧 使用适当的实例化策略为指定的bean创建一个新实例， protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable 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()); } Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier != null) { return obtainFromSupplier(instanceSupplier, beanName); } 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; } } } if (resolved) { if (autowireNecessary) { return autowireConstructor(beanName, mbd, null, null); } else { return instantiateBean(beanName, mbd); } } // Candidate constructors for autowiring? Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); } //默认构造的首选构造函数 案例中没有给定构造器 ctors = mbd.getPreferredConstructors(); if (ctors != null) { return autowireConstructor(beanName, mbd, ctors, null); } //无需特殊处理：只需使用no-arg构造函数 return instantiateBean(beanName, mbd); } 上述流程进入到instantiateBean方法 此时才会使用其默认构造函数实例化给定的bean protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) { try { Object beanInstance; if (System.getSecurityManager() != null) { beanInstance = AccessController.doPrivileged( //核心 在此工厂中以给定名称返回Bean的实例 (PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this), getAccessControlContext()); } else { beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this); } BeanWrapper bw = new BeanWrapperImpl(beanInstance); initBeanWrapper(bw); return bw; } catch (Throwable ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); } } 进入instantiate方法中此时在此工厂中以给定名称返回Bean的实例，并且过程中调用ctor.newInstance(argsWithDefaultValues); 完成了实例化 @Override public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { // Don't override the class with CGLIB if no overrides. if (!bd.hasMethodOverrides()) { Constructor<?> constructorToUse; synchronized (bd.constructorArgumentLock) { constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod; if (constructorToUse == null) { final Class<?> clazz = bd.getBeanClass(); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { if (System.getSecurityManager() != null) { constructorToUse = AccessController.doPrivileged( (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor); } else { constructorToUse = clazz.getDeclaredConstructor(); } bd.resolvedConstructorOrFactoryMethod = constructorToUse; } catch (Throwable ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex); } } } //此处执行ctor.newInstance(argsWithDefaultValues); 真正的完成对象的实例化 return BeanUtils.instantiateClass(constructorToUse); } else { // Must generate CGLIB subclass. return instantiateWithMethodInjection(bd, beanName, owner); } } 继续step over结果逐层返回直到到AbstractAutowireCapableBeanFactory类的doCreateBean方法可以看到当前bean对象已经被实例化出来了，但是还没有设置属性值。下方有段核心代码 //填充bean 其实就是填充属性值 populateBean(beanName, mbd, instanceWrapper); 结果逐层返回，我们发现属性值填充成功接着流程走到initializeBean方法 protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { //BeanPostProcessor(前置方法） wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { //bean初始化用户自定义初始方法init-method 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()) { //BeanPostProcessor（后置方法） wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; } 到此为止完成了bean对象的读取，创建，实例化，执行用户自定义初始方法init-method。可能源码不好理解，没关系，我画了个图，方便过下流程
由示例引出本文的主角首先新建两个Pojo，分别是People和Company /** * @description： People * @Author MRyan * @Date 2020/12/5 14:20 * @Version 1.0 */ @Data @ToString @NoArgsConstructor @AllArgsConstructor public class People { /** * 姓名 */ private String name; /** * 年龄 */ private Integer age; /** * 所在公司 */ private Company city; } /** * @description： Company * @Author MRyan * @Date 2020/12/5 14:20 * @Version 1.0 */ @Data @ToString @AllArgsConstructor @NoArgsConstructor public class Company { /** * 公司名称 */ private String companyName; /** * 公司所在城市 */ private String companyCity; } 有了这两个Pojo我们可以开始搞事情了定义一个ConditionText类，将Company作为bean注入IOC容器中并返回对象，并同样创建People作为bean依赖Company。/** * @description： 《SpringBoot源码分析》ConditionText * @Author MRyan * @Date 2020/12/5 14:21 * @Version 1.0 */ @Configuration public class ConditionText { @Bean public Company loadCompany() { Company company = new Company(); company.setCompanyName("Google"); return company; } @Bean public People people(Company company) { company.setCompanyCity("USA"); return new People("MRyan", 21, company); } }然后我们在测试类中注入People并输出people信息@Slf4j @SpringBootTest class DemoApplicationTests { @Autowired(required = false) private People people; @Test void contextLoads() { System.out.println("people = " + people); } }发现正常输出没有毛病，也符合实际开发的需求。那么问题来了，如果上面的Company没有注入成功，会出现什么事情（将Company注释掉模拟没有注入成功的场景） /** * @description： 《SpringBoot源码分析》ConditionText * @Author MRyan * @Date 2020/12/5 14:21 * @Version 1.0 */ @Configuration public class ConditionText { /* @Bean public Company loadCompany() { Company company = new Company(); company.setCompanyName("Google"); return company; }*/ @Bean public People people(Company company) { company.setCompanyCity("USA"); return new People("MRyan", 21, company); } }启动直接空指针爆红了，这显然不是我们想要的结果，我们是要当Company已经注入成功那么实例化People，如果没有注入成功那么不实例化People。那么我们该怎么做呢？本文的重点来了：@ConditionalOnBean注解的作用将上述测试代码修改如下：/** * @description： 《SpringBoot源码分析》ConditionText * @Author MRyan * @Date 2020/12/5 14:21 * @Version 1.0 */ @Configuration public class ConditionText { /* @Bean public Company loadCompany() { Company company = new Company(); company.setCompanyName("Google"); return company; }*/ /*** *这里加了ConditionalOnBean注解，就代表如果Company存在才实例化people */ @ConditionalOnBean(name = "Company") @Bean public People people(Company company) { company.setCompanyCity("USA"); return new People("MRyan", 21, company); } } 运行测试，发现这次没爆红，而且People如我们所愿没有实例化ConditionalOnBean的作用是什么，它是怎么实现的呢？注解ConditionalOnBean是什么源码如下： /** * {@link Conditional @Conditional} that only matches when beans meeting all the specified * requirements are already contained in the {@link BeanFactory}. All the requirements * must be met for the condition to match, but they do not have to be met by the same * bean. * * When placed on a {@code @Bean} method, the bean class defaults to the return type of * the factory method: * * * @Configuration * public class MyAutoConfiguration { * * @ConditionalOnBean * @Bean * public MyService myService() { * ... * } * * } * * In the sample above the condition will match if a bean of type {@code MyService} is * already contained in the {@link BeanFactory}. * * The condition can only match the bean definitions that have been processed by the * application context so far and, as such, it is strongly recommended to use this * condition on auto-configuration classes only. If a candidate bean may be created by * another auto-configuration, make sure that the one using this condition runs after. * * @author Phillip Webb * @since 1.0.0 */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional(OnBeanCondition.class) //当给定的在bean存在时,则实例化当前Bean public @interface ConditionalOnBean { /** * The class types of beans that should be checked. The condition matches when beans * of all classes specified are contained in the {@link BeanFactory}. * @return the class types of beans to check */ //需要作为条件的类的Class对象数组 Class<?>[] value() default {}; /** * The class type names of beans that should be checked. The condition matches when * beans of all classes specified are contained in the {@link BeanFactory}. * @return the class type names of beans to check */ //需要作为条件的类的Name,Class.getName() String[] type() default {}; /** * The annotation type decorating a bean that should be checked. The condition matches * when all of the annotations specified are defined on beans in the * {@link BeanFactory}. * @return the class-level annotation types to check */ //(用指定注解修饰的bean)条件所需的注解类 Class<? extends Annotation>[] annotation() default {}; /** * The names of beans to check. The condition matches when all of the bean names * specified are contained in the {@link BeanFactory}. * @return the names of beans to check */ //spring容器中bean的名字 String[] name() default {}; /** * Strategy to decide if the application context hierarchy (parent contexts) should be * considered. * @return the search strategy */ //搜索容器层级,当前容器,父容器 SearchStrategy search() default SearchStrategy.ALL; /** * Additional classes that may contain the specified bean types within their generic * parameters. For example, an annotation declaring {@code value=Name.class} and * {@code parameterizedContainer=NameRegistration.class} would detect both * {@code Name} and {@code NameRegistration<Name>}. * @return the container types * @since 2.1.0 */ //可能在其泛型参数中包含指定bean类型的其他类 Class<?>[] parameterizedContainer() default {}; } 其中我们看@Conditional(OnBeanCondition.class)是Spring4新提供的注解，它的作用是按照一定的条件进行判断，满足条件的才给容器注册Bean（有关于这个注解会另起一篇文章分析）而@ConditionalOnBean作用是当给定的在bean存在时,则实例化当前Bean需要注意配合上@Autowired(required = false)使用 required=false 的意思就是允许当前的Bean对象为null。其实类似@ConditionalOnBean有很多注解例如：@ConditionalOnBean // 当给定的在bean存在时,则实例化当前Bean @ConditionalOnMissingBean // 当给定的在bean不存在时,则实例化当前Bean @ConditionalOnClass // 当给定的类名在类路径上存在，则实例化当前Bean @ConditionalOnMissingClass // 当给定的类名在类路径上不存在，则实例化当前Bean原理大致相同。
CommandLineRunner有什么用在使用SpringBoot构建项目时，我们通常有一些预先数据的加载。那么SpringBoot提供了一个简单的方式来实现那就是CommandLineRunner。什么是CommandLineRunner?直奔主题：根据源码说明 我们可以通过实现CommandLineRunner接口并重写run方法来达到SpringBoot运行启动之后自动加载实现CommandLineRunner的类，同时我们可以定义多个类同时实现CommandLineRunner接口，通过@Order注解可以让它们排序执行，@Order（）参数越小越先执行。/** * Interface used to indicate that a bean should run when it is contained within * a {@link SpringApplication}. Multiple {@link CommandLineRunner} beans can be defined * within the same application context and can be ordered using the {@link Ordered} * interface or {@link Order @Order} annotation. * * If you need access to {@link ApplicationArguments} instead of the raw String array * consider using {@link ApplicationRunner}. * * @author Dave Syer * @since 1.0.0 * @see ApplicationRunner */ @FunctionalInterface public interface CommandLineRunner { /** * Callback used to run the bean. * @param args incoming main method arguments * @throws Exception on error */ void run(String... args) throws Exception; }示例演示需求：在启动SpringBoot之后，我们需要从数据库中预加载指定数据，并将输出信息按照指定顺序排序。（不要在意这个并不合理存在的例子）实现：定义两个类分别实现CommandLineRunner并重写run方法，分别在run方法中处理业务逻辑即可。 /** * @description： CommandLineRunner源码分析 * @Author MRyan * @Date 2020/12/3 15:53 * @Version 1.0 */ @SpringBootApplication @Order(1) @Slf4j public class DataSourceBackup implements CommandLineRunner { @Autowired private JdbcTemplate jdbcTemplate; @Override public void run(String... args) { showData(); } public void showData() { jdbcTemplate.queryForList("select * from user").forEach(row -> { log.info("LOG1 " + row.toString()); }); } } @SpringBootApplication @Order(2) @Slf4j class DataSourceBackup2 implements CommandLineRunner { @Autowired private JdbcTemplate jdbcTemplate; @Override public void run(String... args) { showData(); } public void showData() { jdbcTemplate.queryForList("select * from TAG").forEach(row -> { log.info("LOG2 " + row.toString()); }); } }运行输出：成功了，让我们来看看SpringBoot底层究竟是怎么实现的源码分析启动SpringBoot（这块涉及到SpringBoot启动流程分析 之前分析过这里不再详述 可以看之前的文章）《SpringBoot源码分析》启动流程@SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }单点步步调试执行run方法定位到public ConfigurableApplicationContext run(String… args)方法，开始分析吧public ConfigurableApplicationContext run(String... args) { // 创建并启动计时监控类 StopWatch stopWatch = new StopWatch(); stopWatch.start(); // 声明应用上下文对象和异常报告集合 ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList(); // 设置系统属性 headless 的值 this.configureHeadlessProperty(); // 创建所有 Spring 运行监听器并发布应用启动事件 SpringApplicationRunListeners listeners = this.getRunListeners(args); listeners.starting(); Collection exceptionReporters; try { // 处理 args 参数 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); // 准备环境 ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments); this.configureIgnoreBeanInfo(environment); // 创建 Banner 的打印类 Banner printedBanner = this.printBanner(environment); // 创建应用上下文 context = this.createApplicationContext(); // 实例化异常报告器 exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context); // 准备应用上下文 this.prepareContext(context, environment, listeners, applicationArguments, printedBanner); // 刷新应用上下文 this.refreshContext(context); // 应用上下文刷新之后的事件的处理 this.afterRefresh(context, applicationArguments); // 停止计时监控类 stopWatch.stop(); // 输出日志记录执行主类名、时间信息 if (this.logStartupInfo) { (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch); } // 发布应用上下文启动完成事件 listeners.started(context); // 执行所有 Runner 运行器 this.callRunners(context, applicationArguments); } catch (Throwable var10) { this.handleRunFailure(context, var10, exceptionReporters, listeners); throw new IllegalStateException(var10); } try { // 发布应用上下文就绪事件 listeners.running(context); // 返回应用上下文对象 return context; } catch (Throwable var9) { this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null); throw new IllegalStateException(var9); } }其中关键步骤 // ************执行所有 Runner 运行器********* this.callRunners(context, applicationArguments);进入callRunners方法内部private void callRunners(ApplicationContext context, ApplicationArguments args) { //将实现ApplicationRunner和CommandLineRunner接口的类，存储到集合中 List<Object> runners = new ArrayList<>(); runners.addAll(context.getBeansOfType(ApplicationRunner.class).values()); runners.addAll(context.getBeansOfType(CommandLineRunner.class).values()); //按照加载先后顺序排序 AnnotationAwareOrderComparator.sort(runners); for (Object runner : new LinkedHashSet<>(runners)) { if (runner instanceof ApplicationRunner) { callRunner((ApplicationRunner) runner, args); } if (runner instanceof CommandLineRunner) { callRunner((CommandLineRunner) runner, args); } } }紧接着调用callRunner方法来处理各个实现类的逻辑private void callRunner(CommandLineRunner runner, ApplicationArguments args) { try { //调用各个实现类中的逻辑实现 (runner).run(args.getSourceArgs()); } catch (Exception ex) { throw new IllegalStateException("Failed to execute CommandLineRunner", ex); } } 到这里关于CommandLineRunner部分的源码分析就到这里结束了，我们也了解了它的作用和实现原理应用场景了。
起因：配置一个数据源我们知道可以在yml文件或者properties中编写配置，利用SpringBoot自动配置的特性完成绑定，但如果我们需要依赖一个以上的多个数据源这该怎么办呢？解决方案：不同的数据源配置要分开,避免混在一起，一定要注意正在操作的数据源是哪个。首先我们需要排除SpringBoot对数据源的自动配置，利用exclude属性将DataSourceAutoConfiguration，DataSourceTransactionManagerAutoConfiguration，JdbcTemplateAutoConfiguration排除。如下：@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, JdbcTemplateAutoConfiguration.class }) @Slf4j public class MultiDataSourceApplication { public static void main(String[] args) { SpringApplication.run(MultiDataSourceApplication.class, args); } }这样做消除了框架对数据源一系列的自动配置，我们可以手动去控制它们。先来看下properties配置文件,声明两种数据源url分别是default和text。management.endpoints.web.exposure.include=* spring.output.ansi.enabled=ALWAYS default.datasource.url=jdbc:h2:file:~/default default.datasource.username=MRyan default.datasource.password=123456 text.datasource.url=jdbc:h2:file:~/text text.datasource.username= text.datasource.password=然后我们手动配置一个数据源创建一个配置类DataSourceProperties绑定Properties配置文件，数据源我们采用配置文件中声明的default url。 /** * default数据源 * 利用@ConfigurationProperties为DataSourceProperties赋值 获取application.properties配置文件 */ @Bean @ConfigurationProperties("default.datasource") public DataSourceProperties defaultSourceProperties() { return new DataSourceProperties(); }接着创建DataSource的bean并且输出log日志查看数据源url。 /** * 创建DataSource的bean */ @Bean public DataSource defaultDataSource() { DataSourceProperties dataSourceProperties = defaultSourceProperties(); log.info("default datasource:{}", dataSourceProperties.getUrl()); return dataSourceProperties.initializeDataSourceBuilder().build(); }然后为上述创建的DataSource的Bean创建对应的事务管理器 /** * 为上述创建的DataSource的Bean创建对应的事务管理器 */ @Bean @Resource public PlatformTransactionManager defaultManager(DataSource defaultDataSource) { return new DataSourceTransactionManager(defaultDataSource); }这个时候我们就配置好一个数据源了，可以运行输出下没什么问题。用同样的方法我们配置第二个数据源text//****************************************************** /** * text数据源 * 利用@ConfigurationProperties为DataSourceProperties赋值 获取application.properties配置文件 */ @Bean @ConfigurationProperties("text.datasource") public DataSourceProperties textSourceProperties() { return new DataSourceProperties(); } /** * 创建DataSource的bean */ @Bean public DataSource textDataSource() { DataSourceProperties dataSourceProperties = textSourceProperties(); log.info("text datasource:{}", dataSourceProperties.getUrl()); return dataSourceProperties.initializeDataSourceBuilder().build(); } /** * 为上述创建的DataSource的Bean创建对应的事务管理器 */ @Bean @Resource public PlatformTransactionManager textManager(DataSource textDataSource) { return new DataSourceTransactionManager(textDataSource); }最终的代码如下： /** * @description： SpringBoot如何配置多个数据源 * @Author MRyan * @Date 2020/10/8 15:53 * @Version 1.0 */ @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, JdbcTemplateAutoConfiguration.class }) @Slf4j public class MultiDataSourceApplication { public static void main(String[] args) { SpringApplication.run(MultiDataSourceApplication.class, args); } /** * default数据源 * 利用@ConfigurationProperties为DataSourceProperties赋值 获取application.properties配置文件 */ @Bean @ConfigurationProperties("default.datasource") public DataSourceProperties defaultSourceProperties() { return new DataSourceProperties(); } /** * 创建DataSource的bean */ @Bean public DataSource defaultDataSource() { DataSourceProperties dataSourceProperties = defaultSourceProperties(); log.info("default datasource:{}", dataSourceProperties.getUrl()); return dataSourceProperties.initializeDataSourceBuilder().build(); } /** * 为上述创建的DataSource的Bean创建对应的事务管理器 */ @Bean @Resource public PlatformTransactionManager defaultManager(DataSource defaultDataSource) { return new DataSourceTransactionManager(defaultDataSource); } //****************************************************** /** * text数据源 * 利用@ConfigurationProperties为DataSourceProperties赋值 获取application.properties配置文件 */ @Bean @ConfigurationProperties("text.datasource") public DataSourceProperties textSourceProperties() { return new DataSourceProperties(); } /** * 创建DataSource的bean */ @Bean public DataSource textDataSource() { DataSourceProperties dataSourceProperties = textSourceProperties(); log.info("text datasource:{}", dataSourceProperties.getUrl()); return dataSourceProperties.initializeDataSourceBuilder().build(); } /** * 为上述创建的DataSource的Bean创建对应的事务管理器 */ @Bean @Resource public PlatformTransactionManager textManager(DataSource textDataSource) { return new DataSourceTransactionManager(textDataSource); } } 运行并输出日志正常运行，并没有什么问题。查看actuator中beans发现却在其中
不管是XML配置的Context，还是Spring Boot的Context，还是Web服务中的Context，创建后都会调用AbstractApplicationContext类的refresh()方法。定位到AbstractApplicationContext下的refresh()方法，开始分析。整体流程如下： @Override public void refresh() throws BeansException, IllegalStateException { //1 synchronized (this.startupShutdownMonitor) { //2 prepareRefresh(); //3 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); //4 prepareBeanFactory(beanFactory); try { //5 postProcessBeanFactory(beanFactory); //6 invokeBeanFactoryPostProcessors(beanFactory); //7 registerBeanPostProcessors(beanFactory); //8 initMessageSource(); //9 initApplicationEventMulticaster(); //10 onRefresh(); //11 registerListeners(); // 12 finishBeanFactoryInitialization(beanFactory); // 13 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } destroyBeans(); cancelRefresh(ex); throw ex; } finally { //14 resetCommonCaches(); } } }分为14步，接下来我们一步一步来进行分析。1. synchronized (this.startupShutdownMonitor) 加锁，确保了同一时间startupShutdownMonitor的状态不发生改变。2. prepareRefresh() 为刷新做准备，进入方法查看：/** *准备此上下文以进行刷新，设置其启动日期和活动标记以及执行属性源的任何初始化 */ protected void prepareRefresh() { // 设置开始时间 this.startupDate = System.currentTimeMillis(); //设置激活状态 this.closed.set(false); this.active.set(true); if (logger.isDebugEnabled()) { if (logger.isTraceEnabled()) { logger.trace("Refreshing " + this); } else { logger.debug("Refreshing " + getDisplayName()); } } //初始化Context环境占位符 initPropertySources(); // 动作根据子类的自求由子类执行，然后验证是否缺失必要的properties getEnvironment().validateRequiredProperties(); // 存储预刷新的ApplicationListeners if (this.earlyApplicationListeners == null) { this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners); } else { // 将本地应用程序侦听器重置为预刷新状态。 this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } //允许收集早期的ApplicationEvent 一旦多播器可用时就发布 this.earlyApplicationEvents = new LinkedHashSet<>(); }3. 刷新并获得内部的 Bean Factory4. 进入方法prepareBeanFactory（）/** * 配置工厂的标准上下文特征，例如上下文的ClassLoader和后处理器 * @param beanFactory the BeanFactory to configure */ protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // 告诉内部bean工厂使用上下文的类加载器等 beanFactory.setBeanClassLoader(getClassLoader()); beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // 使用上下文回调配置Bean工厂 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); //BeanFactory接口未在普通工厂中注册为可解析类型 //MessageSource注册为Bean（并发现用于自动装配） beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); //注册早期的后处理器以将内部bean检测为ApplicationListeners。 beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); //检测LoadTimeWeaver并准备编织（如果找到） if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); //设置一个临时的ClassLoader以进行类型匹配。 beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } //注册默认环境bean if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } }对 BeanFactory 进行准备工作，比如设置类加载器和后置处理器、配置不进行自动装配的类型、注册默认的环境 Bean。5. postProcessBeanFactory方法源码如下/** * Modify the application context's internal bean factory after its standard * initialization. All bean definitions will have been loaded, but no beans * will have been instantiated yet. This allows for registering special * BeanPostProcessors etc in certain ApplicationContext implementations. * @param beanFactory the bean factory used by the application context */ protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { }为 Context 的子类提供后置处理 BeanFactory 的扩展能力。如果子类想在 Bean 定义加载完成后，开始初始化上下文之前做一些特殊逻辑，可以复写这个方法。6. invokeBeanFactoryPostProcessors()方法源码如下： /** * Instantiate and invoke all registered BeanFactoryPostProcessor beans, * respecting explicit order if given. * Must be called before singleton instantiation. */ protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { //传入Bean工厂并获取容器中的Bean工厂后置处理器(注意这里Bean工厂后置处理器还没有初始化) 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())); } }执行 Context 中注册的 Bean Factory 后缀处理器。这里有两种后置处理器，一种是可以注册 Bean 的后缀处理器，另一种是针对 BeanFactory 进行处理的后置处理器。执行的顺序是，先按优先级执行可注册 Bean 的处理器，在按优先级执行针对 BeanFactory的处理器。由 ConfigurationClassPostProcessor 触发、由ClassPathBeanDefinitionScanner 解析并注册到 BeanFactory。7. registerBeanPostProcessors方法源码如下 /** * Instantiate and register all BeanPostProcessor beans, * respecting explicit order if given. * Must be called before any instantiation of application beans. */ protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this); }按优先级指定顺序在 BeanFactory 中注册 Bean的后缀处理器，Bean 后置处理器可以在 Bean 初始化前、后执行处理。8. initMessageSource方法源码如下： /** * 实例化消息源 * 如果在此上下文中未定义父项，则使用父项 */ protected void initMessageSource() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) { this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class); // Make MessageSource aware of parent MessageSource. if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) { HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource; if (hms.getParentMessageSource() == null) { // Only set parent context as parent MessageSource if no parent MessageSource // registered already. hms.setParentMessageSource(getInternalParentMessageSource()); } } if (logger.isTraceEnabled()) { logger.trace("Using MessageSource [" + this.messageSource + "]"); } } else { // Use empty MessageSource to be able to accept getMessage calls. DelegatingMessageSource dms = new DelegatingMessageSource(); dms.setParentMessageSource(getInternalParentMessageSource()); this.messageSource = dms; beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource); if (logger.isTraceEnabled()) { logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]"); } } }初始化消息源，消息源用来支持消息的国际化9. /** *初始化应用事件广播器 *如果上下文中未定义则用简单的应用事件广播器 * @see org.springframework.context.event.SimpleApplicationEventMulticaster */ protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); if (logger.isTraceEnabled()) { logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); } } else { this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); if (logger.isTraceEnabled()) { logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " + "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]"); } } } 初始化应用事件广播器。事件广播器用来向 ApplicationListener 通知各种应用产生的事件，是一个标准的观察者模式。10. onRefresh方法源码如下 /** * Template method which can be overridden to add context-specific refresh work. * Called on initialization of special beans, before instantiation of singletons. * This implementation is empty. * @throws BeansException in case of errors * @see #refresh() */ protected void onRefresh() throws BeansException { //对于子类：默认情况下不执行任何操作。 }是留给子类的扩展步骤，用来让特定的 Context 子类初始化其他的 Bean。11. registerListeners方法源码如下：/** * 添加将ApplicationListener实现为侦听器的bean * 不会影响其他侦听器，可以将它们添加为非bean. */ protected void registerListeners() { //首先注册静态指定的侦听器 for (ApplicationListener<?> listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } //不要在这里初始化FactoryBeans：我们需要保留所有常规bean //未初始化，以使后处理器适用于它们！ String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); for (String listenerBeanName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } //现在我们终于有了一个多播器，可以发布早期的应用程序事件 Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents; this.earlyApplicationEvents = null; if (earlyEventsToProcess != null) { for (ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); } } } 把实现了 ApplicationListener 的 Bean 注册到事件广播器，并对广播器中的早期未广播事件进行通知。12. finishBeanFactoryInitialization方法源码如下：/** *完成此上下文的Bean工厂的初始化 *初始化所有剩余的单例beans. */ protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { //为此上下文初始化转换服务 if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } //如果之前没有任何bean后处理器（例如PropertyPlaceholderConfigurer bean）注册过以下任何一个，则注册一个默认的嵌入式值解析器： //此时，主要是为了注释属性值中的解析。 if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); } //尽早初始化LoadTimeWeaverAware Bean，以便尽早注册其转换器。 String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } //停止使用临时ClassLoader进行类型匹配。 beanFactory.setTempClassLoader(null); //允许缓存所有bean定义元数据，而不期望进一步的更改。 beanFactory.freezeConfiguration(); //实例化所有剩余的（非延迟初始化）单例。 beanFactory.preInstantiateSingletons(); }冻结所有 Bean 描述信息的修改，实例化非延迟加载的单例 Bean。13. finishRefresh方法源码如下：/** *完成此上下文的刷新，调用LifecycleProcessor的 onRefresh（）方法并发布 * {@link org.springframework.context.event.ContextRefreshedEvent}. */ protected void finishRefresh() { //清除上下文级别的资源缓存（例如来自扫描的ASM元数据）。 clearResourceCaches(); // 为此上下文初始化生命周期处理器。 initLifecycleProcessor(); //首先将刷新传播到生命周期处理器。 getLifecycleProcessor().onRefresh(); //发布最终事件。 publishEvent(new ContextRefreshedEvent(this)); // 如果活动，请参加LiveBeansView MBean。 LiveBeansView.registerApplicationContext(this); }完成上下文的刷新工作，调用 LifecycleProcessor 的 onFresh() 方法以及发布 ContextRefreshedEvent 事件。14./** * Reset Spring's common reflection metadata caches, in particular the * {@link ReflectionUtils}, {@link AnnotationUtils}, {@link ResolvableType} * and {@link CachedIntrospectionResults} caches. * @since 4.2 * @see ReflectionUtils#clearCache() * @see AnnotationUtils#clearCache() * @see ResolvableType#clearCache() * @see CachedIntrospectionResults#clearClassLoader(ClassLoader) */ protected void resetCommonCaches() { ReflectionUtils.clearCache(); AnnotationUtils.clearCache(); ResolvableType.clearCache(); CachedIntrospectionResults.clearClassLoader(getClassLoader()); }重置公共的缓存，比如 ReflectionUtils 中的缓存、 AnnotationUtils ,ResolvableType中的缓存等等；到此文章就结束了。
源码分析在SpringApplication.run(SystemmanageApplication.class, args) 入口打个断点，debug进去。 继续Debug执行new SpringApplication() 调用了构造方法，进行初始化操作判断了当前类型是否web加载所有的初始化器加载所有的监听器设置程序运行的主类执行run方法定位到public ConfigurableApplicationContext run(String... args)方法，开始分析吧public ConfigurableApplicationContext run(String... args) { // 创建并启动计时监控类 StopWatch stopWatch = new StopWatch(); stopWatch.start(); // 声明应用上下文对象和异常报告集合 ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList(); // 设置系统属性 headless 的值 this.configureHeadlessProperty(); // 创建所有 Spring 运行监听器并发布应用启动事件 SpringApplicationRunListeners listeners = this.getRunListeners(args); listeners.starting(); Collection exceptionReporters; try { // 处理 args 参数 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); // 准备环境 ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments); this.configureIgnoreBeanInfo(environment); // 创建 Banner 的打印类 Banner printedBanner = this.printBanner(environment); // 创建应用上下文 context = this.createApplicationContext(); // 实例化异常报告器 exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context); // 准备应用上下文 this.prepareContext(context, environment, listeners, applicationArguments, printedBanner); // 刷新应用上下文 this.refreshContext(context); // 应用上下文刷新之后的事件的处理 this.afterRefresh(context, applicationArguments); // 停止计时监控类 stopWatch.stop(); // 输出日志记录执行主类名、时间信息 if (this.logStartupInfo) { (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch); } // 发布应用上下文启动完成事件 listeners.started(context); // 执行所有 Runner 运行器 this.callRunners(context, applicationArguments); } catch (Throwable var10) { this.handleRunFailure(context, var10, exceptionReporters, listeners); throw new IllegalStateException(var10); } try { // 发布应用上下文就绪事件 listeners.running(context); // 返回应用上下文对象 return context; } catch (Throwable var9) { this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null); throw new IllegalStateException(var9); } } 流程详解以上就是Springboot启动的流程，可以将其划分为18步。具体如下：1.创建并启动计时监控类org.springframework.util下的StopWatch类此计时器是为了监控并记录 Spring Boot 应用启动的时间的，它会记录当前任务的名称，然后开启计时器。2.声明应用上下文对象和异常报告集合此过程声明了应用上下文对象。同时声明了异常报告集合用于收集错误信息，用于向用户报告错误原因。3.设置系统属性 headless 的值源码如下：private void configureHeadlessProperty() { //此处调用的是：java.awt.headless System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless))); }系统赋值public static String setProperty(String key, String value) { //判断空操作 checkKey(key); //获取安全管理员 默认null SecurityManager sm = getSecurityManager(); if (sm != null) { sm.checkPermission(new PropertyPermission(key, SecurityConstants.PROPERTY_WRITE_ACTION)); } //返回 return (String) props.setProperty(key, value); }目的是设置 Java.awt.headless = true，其中 awt（Abstract Window Toolkit）的含义是抽象窗口工具集。设置为 true 表示运行一个 headless 服务器，可以用它来作一些简单的图像处理。4.创建所有 Spring 运行监听器并发布应用启动事件此过程用于获取配置的监听器名称并实例化所有的类。5.初始化默认应用的参数类也就是说声明并创建一个应用参数对象。6.准备环境创建配置并且绑定环境（通过 property sources 和 profiles 等配置文件）。7.创建 Banner 的打印类Spring Boot 启动时会打印 Banner 图片 此 banner 信息是在 SpringBootBanner 类中定义的，我们可以通过实现 Banner 接口来自定义 banner 信息，然后通过代码 setBanner() 方法设置 Spring Boot 项目使用自己自定义 Banner 信息，或者是在 resources 下添加一个 banner.txt，把 banner 信息添加到此文件中，就可以实现自定义 banner 的功能了。8.创建应用上下文根据不同的应用类型来创建不同的 ApplicationContext 上下文对象。9.实例化异常报告器它调用的是 getSpringFactoriesInstances() 方法来获取配置异常类的名称，并实例化所有的异常处理类。10.准备应用上下文此方法的主要作用是把上面已经创建好的对象，传递给 prepareContext 来准备上下文，例如将环境变量 environment 对象绑定到上下文中、配置 bean 生成器以及资源加载器、记录启动日志等操作。11.刷新应用上下文此方法用于解析配置文件，加载 bean 对象，并且启动内置的 web 容器等操作。12.应用上下文刷新之后的事件处理 /** * Called after the context has been refreshed. * @param context the application context * @param args the application arguments */ protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) { }这个方法的源码是空的，可以做一些自定义的后置处理操作。13.停止计时监控类停止此过程第一步中的程序计时器，并统计任务的执行信息。14.输出日志信息把相关的记录信息，如类名、时间等信息进行控制台输出。15.发布应用上下文启动完成事件触发所有 SpringApplicationRunListener 监听器的 started 事件方法。16.执行所有 Runner 运行器执行所有的 ApplicationRunner 和 CommandLineRunner 运行器。17.发布应用上下文就绪事件触发所有的 SpringApplicationRunListener 监听器的 running 事件。18.返回应用上下文对象到此为止 Spring Boot 的启动程序就结束了，我们就可以正常来使用 Spring Boot 框架了。