Spring5深度源码分析(三)之AnnotationConfigApplicationContext启动原理分析

代码地址:https://github.com/showkawa/spring-annotation/tree/master/src/main/java/com/brian

AnnotationConfigApplicationContext启动原理分析主要分析下面三点

1.@Qualifier与@Primary注解的使用
2.BeanFactory与ApplicationContext区别
3.AnnotationConfigApplicationContext启动原理分析

1.@Qualifier与@Primary注解的使用

下面是 @Qualifier 和 @Primary注解的官方解释

@Qualifier

This annotation may be used on a field or parameter as a qualifier for candidate beans when autowiring. It may also be used to annotate other custom annotations that can then in turn be used as qualifiers.这个注释可用于作为预备bean的字段或参数,也可以用在其他的自定义注释下 @Qualifier(“XXX”) Spring的Bean注入配置注解,该注解指定注入的Bean的名称,Spring框架使用byName方式寻找合格的bean,这样就消除了byType方式产生的歧义。

  qualifer字面意思合格者,一般情况下:代码里面需要注入其他依赖,一般用@Reource( 默认按名称装配,当找不到与名称匹配的bean才会按类型装配和@Autowired(默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用)

@Primary

Indicates that a bean should be given preference when multiple candidates are qualified to autowire a single-valued dependency. If exactly one ‘primary’ bean exists among the candidates, it will be the autowired value. This annotation is semantically equivalent to the {@code} element’s {@code primary} attribute 不难看出如果用primary注解其中一个bean就要优先于其他的Bean,当然这个对于这种三方jar包最好不要添加的,谁知道它会不会后期又出什么幺蛾子,只能改自己的代码了最后的方案是改成@qualifiel(“getMetricRegistry”),选取了其中一个bean注入

 primary字面意思最主要者,如果是有配置过多数据源,那一定会熟悉这个注解

 1.1 @Qualifier的使用

我们这里定义一个BookService接口

public interface BookService {

    void printBook();

}

两个实现类BookServiceImpl和OtherBookServiceImpl实现BookService接口的printBook()方法 

@Service
public class BookServiceImpl implements BookService {
    @Override
    public void printBook() {
        System.out.println("---BookServiceImpl---: spring5源码分析");
    }
}
@Service
public class OtherBookServiceImpl implements BookService {
    @Override
    public void printBook() {
        System.out.println("---OtherBookServiceImpl---: 天道酬勤,一步一个坑");
    }
}

我们在BookController注入BooKService

@Controller
public class BookController {

    @Autowiredprivate BookService bookService;

    private void printBook() {
        bookService.printBook();
    }

}

附上配置类MainConfig

@Configuration //告诉spring这是一个配置类
/*
* @ComponentScan
*   value:只当于扫描的的包
*   excludeFilters = 指定扫描的时候按照什么规则排除哪些组件
*   includeFilters = 指定扫描的时候只需要包含哪些组件
*   Filter.ANNOTATION:按照注解
*   Filter.ASSIGNABLE_TYPE: 按照给定的类型
* */

//@ComponentScans(value = {
//        @ComponentScan(value = "com.brian",includeFilters = {
//                @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class}),
//                @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,classes = {BookService.class}),
//                @ComponentScan.Filter(type = FilterType.CUSTOM,classes = {BrianTypeFilter.class})
//        },useDefaultFilters = false)
//})
@ComponentScan({"com.brian.service", "com.brian.controller"})
//@Import({Brian.class,Alan.class})
@Import({BrianSelector.class})
public class MainConfig {

    @Bean("person") //给容器中注册一个Bean;类型为返回值的类型;id默认是方法名作为id
    public Person person(){
        return new Person("Alan",18);
    }


    /*
    * @Conditional() 按照条件注册
    *
    * */
    @Conditional({BrianCondition.class})
    @Bean("person01")
    public Person person01() {
        return new Person("Brian",17);
    }

    @Conditional({BrianCondition.class})
    @Bean("person02")
    public Person person02() {
        return new Person("wenTao",19);
    }

    /*
    *
    *给容器中注册组件
    * 1,包扫描+ 组件标注注解(@Controller/@Service/@Repository/@Component)[自己写的方法]
    * 2, @Bean [导入的第三方包里面的组件]
    * 3,@Import [快速的给容器导入一个组件]
    *       1.@Import(要导入的组件class)
    *       2.ImportSelector:返回需要导入的组件的全类名数组
    *       3.ImportBeanDefinitionRegistrar: 手动注册bean到容器
    *  4. 使用Spring提供的FactoryBean
    * */
    @Bean
    public BrianBeanFactory brianBeanFactory() {
        return new BrianBeanFactory();
    }

}

在测试类MainTest类中测试该printBook()方法

public class MainTest {
    public static void main(String[] args) {
         ApplicationContext mainConfig =
                 new AnnotationConfigApplicationContext(MainConfig.class);

        System.out.println("MainConfig容器创建成功");

        BookController bookController = mainConfig.getBean(BookController.class);
        try {
            Method printBook = bookController.getClass().getDeclaredMethod("printBook");
            printBook.setAccessible(true);
            printBook.invoke(bookController);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
//         Alan alan1 =  acac.getBean(Alan.class);
//        System.out.println("--ALAN--:" + alan1);
        // Alan alan2 =  acac.getBean(Alan.class);
        //System.out.println("比较两个Alan实例: " + (alan1 == alan2));

//        Person person1 = (Person) acac.getBean("person01");
//        System.out.println("---main---test---person1---: " + person1.toString());
//        Person person2 = (Person) acac.getBean("person02");
//        System.out.println("---main---test---person2---: " + person2.toString());


       // MathCalculator mathCalculator = (MathCalculator) acac.getBean("mathCalculator");
       // System.out.println("----get--mathCalculator---: " + mathCalculator);

//        BrianBeanFactory beanFactory = acac.getBean(BrianBeanFactory.class);
//        WenTao wentao = null;
//        try {
//            wentao = beanFactory.getObject();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        System.out.println("----get--WenTao---: " + wentao);


        //关闭ioc容器
        ((AnnotationConfigApplicationContext) mainConfig).close();
    }
}

看到有报错No qualifying bean of type 'com.brian.service.BookService' available: expected single matching bean but found 2: bookServiceImpl,otherBookServiceImpl,就是因为默认按类型装配

OK,此时我在BookController注入BookSevice的时候加上@Qualifier指定beanName,再次测试

@Controller
public class BookController {

    @Autowired
    @Qualifier("bookServiceImpl")
    private BookService bookService;

    private void printBook() {
        bookService.printBook();
    }

}

1.2  @Primary的使用

继续返回到上面的报错时候的场景,因为此时BookService有两个实现类,此时我在OtherBookServiceImpl类上加上@Primary注解,再次测试

@Service
@Primary
public class OtherBookServiceImpl implements BookService {
    @Override
    public void printBook() {
        System.out.println("---OtherBookServiceImpl---: 天道酬勤,一步一个坑");
    }
}

这里顺便总结下常用的注解:

@Configuration把一个类作为一个IoC容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean。
@Scope注解 作用域
@Lazy(true) 表示延迟初始化
@Service用于标注业务层组件、 
@Controller用于标注控制层组件
@Repository用于标注数据访问组件,即DAO组件。
@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
@Scope用于指定scope作用域的(用在类上)
@PostConstruct用于指定初始化方法(用在方法上)
@PreDestory用于指定销毁方法(用在方法上)
@Resource 默认按名称装配,当找不到与名称匹配的bean才会按类型装配。
@DependsOn:定义Bean初始化及销毁时的顺序
@Primary:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
@Autowired 默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用
@Autowired @Qualifier("OtherBookServiceImpl") 存在多个实例配合使用

 

2.BeanFactory与ApplicationContext区别

 之前的源码分析有见过BeanFactory和FactoryBean接口的区别,FactoryBean是创建bean对象,而BeanFactory是获取对象。但ApplicationContext也可以获取对象,我上面的测试类getBean()方法就是的。同样都可以获取bean对象BeanFactory与ApplicationContext有什么区别?

 1. BeanFactory负责读取bean配置文档,管理bean的加载,实例化,维护bean之间的依赖关系,负责bean的声明周期。
2. ApplicationContext除了提供上述BeanFactory所能提供的功能之外,还提供了更完整的框架功能: a. 国际化支持 b. 资源访问:Resource rs = ctx. getResource(“classpath:config.properties”), “file:E:/config.properties” c. 事件传递:通过实现ApplicationContextAware接口 3. 常用的获取ApplicationContext的方法:
   AnnotationConfigApplicationContext 从@Configuration配置类创建容器 FileSystemXmlApplicationContext:从【文件系统】 或者 【classpath的xml配置文件】 创建,参数为配置文件名或文件名数组 ClassPathXmlApplicationContext:从【classpath的xml配置文件】创建,可以从【jar包】中读取配置文件 WebApplicationContextUtils:从web应用的根目录读取配置文件,需要先在web.xml中配置,可以配置监听器或者servlet来实现

Spring的IoC容器就是一个实现了BeanFactory接口的可实例化类。事实上, Spring提供了两种不同的容器:一种是最基本的BeanFactory,另一种是扩展的ApplicationContext。

BeanFactory 仅提供了最基本的依赖注入支持,而 ApplicationContext 则扩展了BeanFactory ,提供了更多的额外功能。
 ApplicationContext的初始化和BeanFactory有一个重大的区别:
BeanFactory在初始化容器时 并未实例化Bean, 直到第一次访问 某个Bean时才实例目标Bean;而ApplicationContext则在初始化应用上下文时就实例化所有的单实例的Bean。
因此ApplicationContext的初始化时间会比BeanFactory稍长一些.

3.AnnotationConfigApplicationContext启动原理分析

从AnnotationConfigApplicationContext的类图中可以看出:

AnnotationConfigApplicationContext继承GenericApplicationContext这个通用应用上下文,GenericApplicationContext内部定义了一个DefaultListableBeanFactory实例,
GenericApplicationContext实现了BeanDefinitionRegistry接口,所以可以通过AnnotationConfigApplicationContext实例注册beanDefinition,然后调用refresh()方法来初始化上下文。
AnnotationConfigApplicationContext继承AbstractApplicationContext,AbstractApplicationContext提供了ApplicationContext的抽象实现。

我这边就从MainTest这个测试类开始AnnotationConfigApplicationContext启动原理分析:

MainTest测试类:

public class MainTest {
    public static void main(String[] args) {
      // 1.读取配置类创建IOC容器   ApplicationContext mainConfig
= new AnnotationConfigApplicationContext(MainConfig.class); System.out.println("MainConfig容器创建成功"); BookController bookController = mainConfig.getBean(BookController.class); try { Method printBook = bookController.getClass().getDeclaredMethod("printBook"); printBook.setAccessible(true); printBook.invoke(bookController); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); }//关闭ioc容器 ((AnnotationConfigApplicationContext) mainConfig).close(); } }

AnnotationConfigApplicationContext点进去,我这边后面的源码都会附带官方注释的翻译

   /**
    *创建一个新的AnnotationConfigApplicationContext,派生bean定义
    *来自给定的带注释的类并自动刷新上下文。
    * @param annotatedClasses一个或多个带注释的类,
    *例如 {@link Configuration @Configuration}类
    */ 

    public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
      //1. 初始化bean读取器和扫描器;
      /** 调用父类GenericApplicationContext无参构造函数,初始化一个BeanFactory: this.beanFactory = new DefaultListableBeanFactory()*/
      this();
      // 2.注册bean配置类
      register(annotatedClasses);
      // 3.刷新上下文
      refresh();  

    }

 现在我们点进去this()这个方法;

   /**
      *创建一个需要填充的新AnnotationConfigApplicationContext
      *通过{@link #register}调用,然后手动{@linkplain #refresh刷新}。
     */

    public AnnotationConfigApplicationContext() {
     //在IOC容器中初始化注解bean读取器AnnotatedBeanDefinitionReader
this.reader = new AnnotatedBeanDefinitionReader(this);
     //在IOC容器中初始化按类路径扫描注解bean的扫描器
this.scanner = new ClassPathBeanDefinitionScanner(this); }

this()方法在调用自身的无参构造方法时会先走父类GenericApplicationContext的无参构造方法

     /**
      *创建一个新的GenericApplicationContext。
      * @see #registerBeanDefinition
      * @see #refresh
     */

    public GenericApplicationContext() {
     //初始化一个BeanFactory
this.beanFactory = new DefaultListableBeanFactory(); }

 现在我们再点进去看下register(annotatedClasses)这个方法,直接调用AnnotatedBeanDefinitionReader的register方法

/**
*注册一个或多个要处理的注释类。
* <p>对{@code register}的调用是幂等的; 添加相同的
*注释类不止一次没有额外的效果。
* @param annotatedClasses一个或多个带注释的类,
*例如 {@link Configuration @Configuration}类
*/
public void register(Class<?>... annotatedClasses) {
    for (Class<?> annotatedClass : annotatedClasses) {
        registerBean(annotatedClass);
    }
}


/**
*从给定的bean类注册bean,从中派生元数据
*类声明的注释。
* @param annotatedClass bean的类
*/
public void registerBean(Class<?> annotatedClass) {
    doRegisterBean(annotatedClass, null, null, null);
}



/**
*从给定的bean类注册bean,从中派生元数据
*类声明的注释。
* @param annotatedClass bean的类
* @param instanceSupplier用于创建bean实例的回调
*(可能是{@code null})
* @param命名bean的显式名称
* @param限定符特定限定符注释要考虑,如果有的话,
*除了bean类级别的限定符
* @param definition定制一个或多个用于自定义的回调
*工厂的{@link BeanDefinition},例如 设置lazy-init或主标志
* @since 5.0
*/
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
        @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
   /** 将Bean配置类信息转成容器中AnnotatedGenericBeanDefinition数据结构,
   * AnnotatedGenericBeanDefinition继承自BeanDefinition作用是定义一个bean的数据结构,
   * 下面的getMetadata可以获取到该bean上的注解信息 */ AnnotatedGenericBeanDefinition abd
= new AnnotatedGenericBeanDefinition(annotatedClass);

//@Conditional装配条件判断是否需要跳过注册
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { return; }
      //设置回调 @param instanceSupplier 用于创建bean实例的回调 abd.setInstanceSupplier(instanceSupplier);

//解析bean作用域(单例或者原型),如果有@Scope注解,则解析@Scope,没有则默认为singleton  ScopeMetadata scopeMetadata
= this.scopeMetadataResolver.resolveScopeMetadata(abd);

//作用域写回BeanDefinition数据结构, abd中缺损的情况下为空,将默认值singleton重新赋值到abd abd.setScope(scopeMetadata.getScopeName());

   //生成bean配置类beanName String beanName
= (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
   //通用注解解析到abd结构中,主要是处理Lazy, primary DependsOn, Role ,Description这五个注解 AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

// @Qualifier特殊限定符处理,@param  qualifiers 除了bean类级别的限定符之外,要考虑的限定符特定限定符注释(如果有)
if (qualifiers != null) { for (Class<? extends Annotation> qualifier : qualifiers) { if (Primary.class == qualifier) {
          // 如果配置@Primary注解,则设置当前Bean为自动装配autowire时首选bean abd.setPrimary(
true); } else if (Lazy.class == qualifier) {
          //设置当前bean为延迟加载 abd.setLazyInit(
true); } else {
          //其他注解,则添加到abd结构中 abd.addQualifier(
new AutowireCandidateQualifier(qualifier)); } } }

    /**自定义bean注册,通常用在applicationContext创建后,手动向容器中一lambda表达式的方式注册bean,
     * 比如:applicationContext.registerBean(BookService.class, () -> new BookService()); */

for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
     //自定义bean添加到BeanDefinition customizer.customize(abd); }
   //根据beanName和bean定义信息封装一个beanhold,heanhold其实就是一个 beanname和BeanDefinition的映射 BeanDefinitionHolder definitionHolder
= new BeanDefinitionHolder(abd, beanName);

   //创建代理对象 definitionHolder
= AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

   /** BeanDefinitionReaderUtils.registerBeanDefinition 内部通过
* DefaultListableBeanFactory.registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
   * 按名称将bean定义信息注册到容器中,实际上DefaultListableBeanFactory内部维护一个Map<String, BeanDefinition>类型变量beanDefinitionMap,
* 用于保存注bean定义信息(beanname 和 beandefine映射)*/ BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder,
this.registry); }

register方法重点完成了bean配置类本身的解析和注册,处理过程可以分为以下几个步骤:

1.根据bean配置类,使用BeanDefinition解析Bean的定义信息,主要是一些注解信息
2.Bean作用域的处理,没有@Scope注解默认解析成单例
3.借助AnnotationConfigUtils工具类解析通用注解
4.将bean定义信息已beanname,beandifine键值对的形式注册到ioc容器中

然后我们继续点进去refresh()方法

refresh方法在AbstractApplicationContext容器中实现,refresh()方法的作用加载或者刷新当前的配置信息,如果已经存在spring容器,则先销毁之前的容器,重新创建spring容器,载入bean定义,完成容器初始化工作,所以可以看出AnnotationConfigApplicationContext容器是通过调用其父类AbstractApplicationContext的refresh()函数启动整个IoC容器完成对Bean定义的载入。  

AbstractApplicationContext类的refresh()方法源代码如下:

@Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            //1.刷新前的预处理
            prepareRefresh();

            //2.获取刷新后的内部Bean工厂
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            //3.BeanFactory的预准备工作
            prepareBeanFactory(beanFactory);

            try {
                // BeanFactory准备工作完成后,可以做一些后置处理工作
          // 4.空方法,用于在容器的子类中扩展 postProcessBeanFactory(beanFactory); // 5. 执行BeanFactoryPostProcessor的方法,BeanFactory的后置处理器,在BeanFactory标准初始化之后执行的 invokeBeanFactoryPostProcessors(beanFactory); // 6. 注册BeanPostProcessor(Bean的后置处理器),用于拦截bean创建过程,实现对bean的增强 registerBeanPostProcessors(beanFactory); // 7. 初始化MessageSource组件(做国际化功能;消息绑定,消息解析) initMessageSource(); // 8. 初始化事件派发器 initApplicationEventMulticaster(); // 9.空方法,可以用于子类实现在容器刷新时自定义逻辑 onRefresh(); // 10. 注册事件监听器,将所有项目里面的ApplicationListener注册到容器中来 registerListeners(); // 11. 初始化所有剩下的单实例bean,单例bean在初始化容器时创建,原型bean在获取时(getbean)时创建 finishBeanFactoryInitialization(beanFactory); // 12. 完成BeanFactory的初始化创建工作,IOC容器就创建完成; finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } //销毁已经创建的单例,以避免挂起资源。 destroyBeans(); //重置“活动”标志。 cancelRefresh(ex); //向调用者传播异常。 throw ex; } finally { //在Spring的core中重置常见的内省缓存,因为我们可能不再需要单例bean的元数据了... resetCommonCaches(); } } }

接下来我们要分析refresh()里面的这些方法

3.1 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()); } } //空方法,用于子容器自定义个性化的属性设置方法 initPropertySources();      //检验属性的合法等 getEnvironment().validateRequiredProperties(); //存储预刷新应用程序监听器… if (this.earlyApplicationListeners == null) { this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners); } else { //将本地应用程序侦听器重置为预刷新状态。 this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } //保存容器中的一些早期的事件 this.earlyApplicationEvents = new LinkedHashSet<>(); }

 3.2 obtainFreshBeanFactory()方法

该方法获取刷新后的内部Bean工厂,obtainFreshBeanFactory方法为内部bean工厂重新生成id,并返回bean工厂

  /**
  *告诉子类刷新内部bean工厂。
  * @return新鲜的BeanFactory实例
  * @see #refreshBeanFactory()
  * @see #getBeanFactory()
  */ 

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {     

      /**
      *为beanfactory生成唯一序列化id,beanfactory已经在GenericApplicationContext构造函数中初始化了,
      *refreshBeanFactory的逻辑在AbstractApplicationContext的实现类GenericApplicationContext中
      */

        refreshBeanFactory();
     //获取beanfactory
return getBeanFactory(); }

GenericApplicationContext类的refreshBeanFactory()方法

    //---------------------------------------------------------------------
    实现AbstractApplicationContext的模板方法
    //---------------------------------------------------------------------
    / * *
    *什么都不做:我们只有一个内部BeanFactory,并且依赖于调用者
    *通过我们的公共方法(或BeanFactory的)注册bean。
    * @see # registerBeanDefinition
    * /  
    @Override
    protected final void refreshBeanFactory() throws IllegalStateException {
        if (!this.refreshed.compareAndSet(false, true)) {
            throw new IllegalStateException(
                    "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
        }
     //生成一个序列化id
this.beanFactory.setSerializationId(getId()); }

这里使用AbstractApplicationContext.refreshBeanFactory()如果是注解的方式实现,则并没有解析项目包下的注解,而是通过在refresh()方法中执行ConfigurationClassPostProcessor后置处理器完成对bean的加载.

3.3 prepareBeanFactory(beanFactory)方法

prepareBeanFactory主要完成beanFactory的一些属性设置,BeanFactory的预准备工作

/**
*配置工厂的标准上下文特征,
*例如上下文的ClassLoader和后置处理器。
* @param beanFactory要配置的BeanFactory
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        //告诉内部bean工厂使用上下文的类加载器等等。
        //设置类加载器
     beanFactory.setBeanClassLoader(getClassLoader());
     //bean表达式解析器 beanFactory.setBeanExpressionResolver(
new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); //使用上下文回调配置bean工厂。 //添加一个BeanPostProcessor实现ApplicationContextAwareProcessor
     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.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); //将早期后置处理器注册为application监听器,用于检测内部bean。 beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); //添加编译时的AspectJ if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); //为匹配的类型设置一个临时类加载器。 beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } // 给beanfactory容器中注册组件ConfigurableEnvironment、systemProperties、systemEnvironment 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()); } }

 3.4 invokeBeanFactoryPostProcessors(beanFactory)方法

invokeBeanFactoryPostProcessors 执行bean工厂后置处理器

/**
*实例化并调用所有已注册的BeanFactoryPostProcessor beans,
*如果给定则遵守显示的顺序。
* <p>必须在单例实例化之前调用。
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    }

invokeBeanFactoryPostProcessors方法内部执行实现了BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor这两个接口的Processor,先获取所有BeanDefinitionRegistryPostProcessor的实现,按优先级执行(是否实现PriorityOrdered优先级接口,是否实现Ordered顺序接口);再以相同的策略执行所有BeanFactoryPostProcessor的实现。

PostProcessorRegistrationDelegate. invokeBeanFactoryPostProcessors实现:

public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

        //如果有的话,首先调用BeanDefinitionRegistryPostProcessors。
        Set<String> processedBeans = new HashSet<>();

        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                }
                else {
                    regularPostProcessors.add(postProcessor);
                }
            }

            
             


         //不要在这里初始化FactoryBeans:我们需要保留所有常规bean

         //未初始化的,让bean工厂的后置处理程序负责于它们!

        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

            //首先,调用实现PriorityOrated接口的BeanDefinitionRegistryPostProcessors类的方法。
            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类的方法。
            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();

            //最后,调用所有其他BeanDefinitionRegistryPostProcessors,直到没有其他的后置处理器出现。
            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();
            }

            //现在,调用到目前为止处理完所有处理器的postProcessBeanFactory回调。
            invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        }

        else {
            //调用在上下文实例中注册的工厂处理器。
            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
        }

        //不要在这里初始化FactoryBeans:我们需要保留所有常规bean
        //未初始化,以让bean工厂的后值处理器负责于它们!
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

       
        List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
            if (processedBeans.contains(ppName)) {
                //跳过-已经在上面的第一阶段处理
            }
            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);
            }
        }

        //首先,调用实现PriorityOrated接口的BeanFactoryPostProcessors类。
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

        //接下来,调用实现Ordered接口的BeanFactoryPostProcessors类方法。
        List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
        for (String postProcessorName : orderedPostProcessorNames) {
            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

        //最后,调用所有其他BeanFactoryPostProcessors,直到没有其他的后置处理器出现。
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
        for (String postProcessorName : nonOrderedPostProcessorNames) {
            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

        //清除缓存的合并bean定义,因为后置处理器可能修改了原始元数据,例如替换了值中的占位符……
        beanFactory.clearMetadataCache();
    }

这里面在处理BeanDefinitionRegistryPostProcessors时有一个非常重要的过程,AnnotationConfigApplicationContext构造函数在初始化reader时为内部beanFactory容器初始化了一个id为org.springframework.context.annotation.internalConfigurationAnnotationProcessor的组件,这是一个ConfigurationClassPostProcessor组件,用来处理添加@Configuration注解的类,并将Bean定义注册到BeanFactory中。

 3.5 invokeBeanFactoryPostProcessors(beanFactory)方法

注册后置处理器的大致逻辑是:

  1.获取所有的 BeanPostProcessor

  2.根据处理器实现的接口区分出4中类型:

    2.1.实现PriorityOrdered接口的处理器

    2.2.实现Ordered接口的处理器,

    2.3.实现MergedBeanDefinitionPostProcessor接口的处理器,

    2.4.普通后置处理器

  3.按这个4中类型依次注册到容器中

  4.注册一个特殊的后置处理器ApplicationListenerDetector,ApplicationListenerDetector本身也实现了MergedBeanDefinitionPostProcessor接口

/ * *
*实例化并注册所有BeanPostProcessor bean,如果给定则遵循显式顺序。
* <p>必须在应用程序bean的任何实例化之前调用。
* /
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
    }
public static void registerBeanPostProcessors(
            ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

        //注册BeanPostProcessorChecker,当bean在BeanPostProcessor实例化过程中被创建时,即当一个bean没有资格被所有BeanPostProcessor处理时,它记录一条信息到日志。
        int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
        beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

        //按优先级分类
        List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
                priorityOrderedPostProcessors.add(pp);
                if (pp instanceof MergedBeanDefinitionPostProcessor) {
                    internalPostProcessors.add(pp);
                }
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        //首先,调用实现PriorityOrated接口的BeanPostProcessors类。
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

        //接下来,调用实现Ordered接口的BeanPostProcessors类方法。
        List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
        for (String ppName : orderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            orderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, orderedPostProcessors);

        //现在,注册所有常规的BeanPostProcessors。
        List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
        for (String ppName : nonOrderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            nonOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

        //最后,调用所有其他BeanPostProcessors,直到没有其他的后置处理器出现。
        sortPostProcessors(internalPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, internalPostProcessors);

        //注册ApplicationListenerDetector,用于Bean创建完时检查是否是ApplicationListener
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
    }

 3.6 initMessageSource()方法

初始化MessageSource组件(做国际化功能;消息绑定,消息解析)

/ * *
初始化MessageSource。
*如果在此上下文中没有定义,则使用父类的。
* /
protected void initMessageSource() {
       //获取beanFactory 
    ConfigurableListableBeanFactory beanFactory
= getBeanFactory(); if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) { this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class); //让MessageSource知道父类的MessageSource。 if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) { HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource; if (hms.getParentMessageSource() == null) { //如果没有注册父类的MessageSource,则只将父类的上下文设置为父类的MessageSource。 hms.setParentMessageSource(getInternalParentMessageSource()); } } if (logger.isTraceEnabled()) { logger.trace("Using MessageSource [" + this.messageSource + "]"); } } else { //使用空的MessageSource来接受getMessage调用。 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 + "]"); } } }

3.7 initApplicationEventMulticaster()方法

 初始化事件派发器

/ * *
初始化ApplicationEventMulticaster。
如果上下文中没有定义,则使用SimpleApplicationEventMulticaster。
* @see org.springframework.context.event.SimpleApplicationEventMulticaster
* /
protected void initApplicationEventMulticaster() {
        //获取BeanFactory
    ConfigurableListableBeanFactory beanFactory
= getBeanFactory();
//如果有配置beanName为applicationEventMulticaster的事件派发器,则将其赋给容器中的applicationEventMulticaster对象
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 {
       //不存在,则创建一个SimpleApplicationEventMulticaster事件派发器,并注册到beanfactory中
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() + "]"); } } }

3.8 registerListeners()方法

registerListeners方法主要实现将事件监听器添加到IOC容器中的事件派发器中,并在最后做了一个事件发布的逻辑(如果之前的步骤有产生事件,则将earlyApplicationEvents中保存的事件逐一发布)

/ * *
添加实现ApplicationListener作为侦听器的bean。
*不影响其他侦听器,可以在不添加bean的情况下添加。
* /
protected void registerListeners() {
        //首先注册静态指定的监听器。
        for (ApplicationListener<?> listener : getApplicationListeners()) {
            getApplicationEventMulticaster().addApplicationListener(listener);
        }

        //不要在这里初始化factorybean:我们需要不初始化所有常规bean,以便让后置处理器处理它们
        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
        for (String listenerBeanName : listenerBeanNames) {
            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        }

        //发布早期的application事件…
        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
        this.earlyApplicationEvents = null;
        if (earlyEventsToProcess != null) {
            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }
    }

3.9 finishBeanFactoryInitialization(beanFactory)方法

初始化所有剩下的单实例bean,单例bean在初始化容器时创建,原型bean在获取时(getbean)时创建

/ * *
*完成这个上下文的bean工厂的初始化,
初始化所有剩余的单例bean。
* /
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 beans,以便尽早注册它们的转换器。
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }

        //停止使用临时类加载器进行类型匹配。
        beanFactory.setTempClassLoader(null);

        //允许缓存所有bean定义元数据,不需要进一步更改。
        beanFactory.freezeConfiguration();

        //实例化所有剩余的(非懒加载初始化)单例。
        beanFactory.preInstantiateSingletons();
    }

DefaultListableBeanFactory. preInstantiateSingletons()方法的实现:

@Override
    public void preInstantiateSingletons() throws BeansException {
        if (logger.isTraceEnabled()) {
            logger.trace("Pre-instantiating singletons in " + this);
        }

        //容器中所有bean名称
        List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

        
        for (String beanName : beanNames) {
       //获取Bean的定义信息;RootBeanDefinition RootBeanDefinition bd
= getMergedLocalBeanDefinition(beanName);
        //非抽象,单例,非延迟加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
          //是否是FactoryBean
if (isFactoryBean(beanName)) {
            // 通过"&beanName"获取工厂Bean实例 Object bean
= getBean(FACTORY_BEAN_PREFIX + beanName); if (bean instanceof FactoryBean) { final 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 {
            //不是FactoryBean,则利用getBean(beanName)实例化bean  getBean(beanName); } } }
for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { smartSingleton.afterSingletonsInstantiated(); return null; }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } } }

3.10 finishRefresh()方法

完成BeanFactory的初始化创建工作,代码走到这一步IOC容器就创建完成

/ * *
*调用LifecycleProcessor,完成此上下文的刷新
方法并发布
* {@link org.springframework.context.event.ContextRefreshedEvent}。
* /
protected void finishRefresh() {
        //清除上下文级的资源缓存(例如来自扫描的ASM元数据)。
        clearResourceCaches();

        //初始化和生命周期有关的后置处理器LifecycleProcessor,默认DefaultLifecycleProcessor
        initLifecycleProcessor();

        // 回调生命周期处理器
        getLifecycleProcessor().onRefresh();

        //发布容器刷新完成事件:ContextRefreshedEvent
        publishEvent(new ContextRefreshedEvent(this));

        
        LiveBeansView.registerApplicationContext(this);
    }

以上基本分析了AnnotationConfigApplicationContext容器的初始化过程, Spring容器在启动过程中,会先保存所有注册进来的Bean的定义信息;Spring容器根据条件创建Bean实例,区分单例,还是原型,后置处理器等(后置处理器会在容器创建过程中通过getBean创建,并执行相应的逻辑);Spring容器在创建bean实例后,会使用多种后置处理器来增加bean的功能,比如处理自动注入,AOP,异步,这种后置处理器机制也丰富了bean的功能。

我这边在AnnotationConfigApplicationContext启动原理分析的代码走读部分有参考博客: https://www.cnblogs.com/ashleyboy/p/9662119.html ,不过有些类的方法会有点不一样,因为我这边时基于Spring5.X的版本分析

 

posted @ 2019-07-04 17:20  Brian_Huang  阅读(1947)  评论(3编辑  收藏  举报