提升自我,超实用的 Spring 注解驱动开发技术

小七学习网,助您升职加薪,遇问题可联系:客服微信【1099252741】 备注:来自网站

作为一名 Java 开发者,必须得学会 Spring 注解驱动开发。不然你将看不懂 Spring Boot、Spring Cloud 的底层实现原理?以及无法自主封装 Spring 组件?如何给已知的…

作为一名 Java 开发者,必须得学会 Spring 注解驱动开发。不然你将看不懂 Spring Boot、Spring Cloud 的底层实现原理?以及无法自主封装 Spring 组件?如何给已知的应用程序做功能拓展?学会 Spring 注解驱动开发,你的工作将会更加地轻松自如,升级加薪才会有希望。接下来,一起手把手完成 Spring 注解驱动开发的每一个场景案例(基本都是从实际工作中出发)!

本文主要内容:

  • Spring 容器以及各个注解使用原理
  • Spring 组件注册原理以及工作中的真实案例
  • Spring 拓展原理,并实现应用功能拓展


前言

如果你之前一直在使用 Spring、Spring MVC 框架,那么一定需要编写大量的 xml 配置文件。如今,Spring Boot、Spring Cloud 兴起之后,其底层都是基于 Spring 注解驱动,使用大量的注解替代原先的 xml 配置文件,通过学习 Spring 注解驱动开发,了解每个注解的基本使用以及背后的原理,便于以后我们深入学习与使用 Spring Boot、Spring Cloud 框架。

前期准备工作

创建项目

第一步:创建 maven 工程

第二步:填写 maven 坐标

next→next→finish→项目创建成功。

创建成功

引入依赖

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context --><dependency>    <groupId>org.springframework</groupId>    <artifactId>spring-context</artifactId>    <version>4.3.25.RELEASE</version></dependency>

成功引入依赖:

在这里插入图片描述

容器

概述

Spring 之所以被广泛使用,是因为对于开发大型项目及其方便简单,这一切离不开 Spring 容器帮助我们管理 bean 的生命周期,那么 Spring 容器到底是什么呢?

bean 是 Spring 的的核心组成,而 Spring 容器就是用于管理这些对象的生命周期,例如:创建、销毁等。

项目中我们通过 ApplicationContext 的实现类来获取上下文,获取容器中的 bean 的元数据。

从代码上讲:一个 Spring 容器就是某个实现了 ApplicationContext 接口的类的实例。也就是说,从代码层面,Spring 容器其实就是一个 ApplicationContext(一个实例化对象)。

从源码角度来说,Spring 容器就是实现了 ApplicationContext 类的实例,获取当前环境的实例即可获取容器的内容,不同的项目环境上下文的实现类不同。

如:

    # 实现 AbstractApplicationContext,xml 和注解都可以初始化    public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry    # Spring Boot 中提供的实现,需要 Web Server 环境下使用    public class AnnotationConfigReactiveWebServerApplicationContext extends ReactiveWebServerApplicationContext implements AnnotationConfigRegistry

在这里插入图片描述

常见实现类

容器的功能

spring 容器

容器的分类及特点

容器分类

容器的运行原理

创建方式
//创建基于注解的 springIOC 容器ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);//创建基于配置文件的 springIOC 容器ApplicationContext applicationContext = new ClassPathXmlApplicationContext(\"/spring-app.xml\");// 创建基于注解的 WebServer 环境的 springIOC 容器,等等。。。。。。。。。。。。。。。。ApplicationContext applicationContext = new AnnotationConfigServletWebServerApplicationContext();
运行原理

本文以 AnnotationConfigApplicationContext 为例,AnnotationConfigApplicationContext 构造器源码,用于初始化容器。

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {        //1.会首先调用父类 GenericApplicationContext 中的构造方法,初始化工厂 bean 为 new DefaultListableBeanFactory()        //2.调用自己的构造方法,初始化了一个读取器:AnnotatedBeanDefinitionReader reader;一个扫描器:ClassPathBeanDefinitionScanner scanner        //3.在 reader 的初始化构造方法中,还注册了 6 个 post processors        this();        //注册 bean,注册就是把 bean 都放在某个地方,一个并发 map 中,Map<String, BeanDefinition> beanDefinitionMap        //这调用了 AnnotatedBeanDefinitionReader reader 的注册方法        //只注册了 6 个 post process 类        register(annotatedClasses);        //实现的 bean 的初始化;        //自定义的 bean 也在这里注册并初始化        refresh();    }

1. 注册容器 register()

源码解析:

public void register(Class<?>... annotatedClasses) {        Assert.notEmpty(annotatedClasses, \"At least one annotated class must be specified\");        this.reader.register(annotatedClasses);    }
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,                            @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {    //得到 bean 的描述信息,比如 bean 的注解,作用范围,是否懒加载,注入方式等    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);    //被条件注解@Conditional 注释的 bean 跳过注册    if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {        return;    }    abd.setInstanceSupplier(instanceSupplier);    //解析 bean 的 Scope,比如是否单例 singleton 还是其他    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);    abd.setScope(scopeMetadata.getScopeName());    //生成 bean name,默认就是类名小写    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));            }        }    }    for (BeanDefinitionCustomizer customizer : definitionCustomizers) {        customizer.customize(abd);    }    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);}

register 主要分为三步(只要是注册 BeanDefinition,都是这 3 步):

  1. 根据 class 文件获取 BeanDefinition,这里是其实现类 AnnotatedGenericBeanDefinition abd;
  2. 将 BeanDefinition 放到 BeanDefinitionHolder 中进一步封装;
  3. 最后一行,执行注册动作。

测试

随便一个普通的 Java 类进行注册到容器中:

   public static void main(String[] args) {        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();        context.register(FistBeanFactoryPostProcessor.class);        context.refresh();        FistBeanFactoryPostProcessor postProcessor = (FistBeanFactoryPostProcessor) context.getBean(\"fistBeanFactoryPostProcessor\");        System.out.println(null != postProcessor);    }

通过断点调试,省略中间其它过程说明,直接上核心代码:

BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    @Override    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 existingDefinition = this.beanDefinitionMap.get(beanName);        if (existingDefinition != null) {            if (!isAllowBeanDefinitionOverriding()) {                throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);            }            else if (existingDefinition.getRole() < beanDefinition.getRole()) {                // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE                if (logger.isInfoEnabled()) {                    logger.info(\"Overriding user-defined bean definition for bean \'\" + beanName +                            \"\' with a framework-generated bean definition: replacing [\" +                            existingDefinition + \"] with [\" + beanDefinition + \"]\");                }            }            else if (!beanDefinition.equals(existingDefinition)) {                if (logger.isDebugEnabled()) {                    logger.debug(\"Overriding bean definition for bean \'\" + beanName +                            \"\' with a different definition: replacing [\" + existingDefinition +                            \"] with [\" + beanDefinition + \"]\");                }            }            else {                if (logger.isTraceEnabled()) {                    logger.trace(\"Overriding bean definition for bean \'\" + beanName +                            \"\' with an equivalent definition: replacing [\" + existingDefinition +                            \"] 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<>(this.beanDefinitionNames.size() + 1);                    updatedDefinitions.addAll(this.beanDefinitionNames);                    updatedDefinitions.add(beanName);                    this.beanDefinitionNames = updatedDefinitions;                    removeManualSingletonName(beanName);                }            }            else {                // Still in startup registration phase                this.beanDefinitionMap.put(beanName, beanDefinition);                this.beanDefinitionNames.add(beanName);                removeManualSingletonName(beanName);            }            this.frozenBeanDefinitionNames = null;        }        if (existingDefinition != null || containsSingleton(beanName)) {            resetBeanDefinition(beanName);        }    }

普通 java 类注册到容器中

// 所有的 bean 注册最终都是 put  beanDefinitionMap 中private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);// 注册的 bean nameprivate volatile List<String> beanDefinitionNames = new ArrayList<>(256);

2. 刷新容器 refresh()

AbstractApplicationContext 是 ApplicationContextspring IOC 容器的基类,refresh 方法是 Spring 最核心的方法,搞清楚这个方法的运行过程,拓展原理基本一看就会。

Spring 容器创建之后,会调用它的 refresh 方法刷新 Spring 应用的上下文。

Spring Boot 项目启动 run 中也是调用 refresh() 刷新上下文:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

refresh 执行过程

源码解析:

public void refresh() throws BeansException, IllegalStateException {    synchronized (this.startupShutdownMonitor) {        // Prepare this context for refreshing.        //前期准备;记录了容器启动时间;容器状态;刷新一些在此方法之前就可能已经存在的监听器        prepareRefresh();        // Tell the subclass to refresh the internal bean factory.        //最终得到 DefaultListableBeanFactory,也就是在 this()方法中通过父类构造函数初始化的那个 bean factory        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();        // Prepare the bean factory for use in this context.        //准备 bean factory,初始化工厂的一些标准固定的容器特性        //因为后边一系列容器初始化操作,都是基于 beanFactory,所以前期准备得充足        prepareBeanFactory(beanFactory);        try {            // Allows post-processing of the bean factory in context subclasses.            //空方法,用于子类扩展功能            postProcessBeanFactory(beanFactory);            // Invoke factory processors registered as beans in the context.            //实例化并执行之前已经注册了的各种 BeanFactoryPostProcessor            invokeBeanFactoryPostProcessors(beanFactory);            // Register bean processors that intercept bean creation.            //实例化 拦截 bean 创建的处理器 BeanPostProcessor;            //这里的注册,是指把实例化的 BeanPostProcessor 存到 beanFactory 的某个 list 中            registerBeanPostProcessors(beanFactory);            // Initialize message source for this context.            //初始化容器的 MessageSource 类型的 bean,MessageSource 用于解析消息            initMessageSource();            // Initialize event multicaster for this context.            //初始化容器的事件广播            //用于管理若干 ApplicationListener 对象,并向他们推送消息            initApplicationEventMulticaster();            // Initialize other special beans in specific context subclasses.            //空方法,在特定的子类中 初始化其他特殊 bean            onRefresh();            // Check for listener beans and register them.            //注册实现了 ApplicationListener 接口的监听者            registerListeners();            // Instantiate all remaining (non-lazy-init) singletons.            //实例化剩下的单例 bean,完成全部 bean 的实例化,除了懒加载的            finishBeanFactoryInitialization(beanFactory);            // Last step: publish corresponding event.            //最后一步,完成此刷新方法,发布完成事件            finishRefresh();        }        catch (BeansException ex) {            if (logger.isWarnEnabled()) {                logger.warn(\"Exception encountered during context initialization - \" +                        \"cancelling refresh attempt: \" + ex);            }            // Destroy already created singletons to avoid dangling resources.            destroyBeans();            // Reset \'active\' flag.            cancelRefresh(ex);            // Propagate exception to caller.            throw ex;        }        finally {            // Reset common introspection caches in Spring\'s core, since we            // might not ever need metadata for singleton beans anymore...            resetCommonCaches();        }    }}

内部方法解析

总共分为 12 个重要过程,这里挑选重点解析。

1. prepareRefresh

protected void prepareRefresh() {    // Switch to active.    //容器启动时刻    this.startupDate = System.currentTimeMillis();    //容器激活状态,默认没有关闭    this.closed.set(false);    //容器激活状态,默认激活的    this.active.set(true);    if (logger.isInfoEnabled()) {        logger.info(\"Refreshing \" + this);    }    // Initialize any placeholder property sources in the context environment.    //空方法    initPropertySources();    // Validate that all properties marked as required are resolvable:    // see ConfigurablePropertyResolver#setRequiredProperties    getEnvironment().validateRequiredProperties();    // Store pre-refresh ApplicationListeners...    //执行 refresh 之前就已经注册的 listeners 集合,如果没有,就初始化集合;    //调试发现是 null 的    if (this.earlyApplicationListeners == null) {        this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);    }    else {        // Reset local application listeners to pre-refresh state.        //如果不为空,重新设置到 applicationListeners 监听器集合        this.applicationListeners.clear();        this.applicationListeners.addAll(this.earlyApplicationListeners);    }    // Allow for the collection of early ApplicationEvents,    // to be published once the multicaster is available...    //事件集合初始化    this.earlyApplicationEvents = new LinkedHashSet<>();}

2. invokeBeanFactoryPostProcessors(beanFactory)

实例化并执行之前已经注册了的各种 BeanFactoryPostProcessor,可用于拓展。

BeanFactoryPostProcessor 是 beanFactory 的后置处理器,也就是说当所有的 bean 定义已经保存并加载到 beanFactory,但是却没有被实例化。那么执行顺序:beanFactory > BeanFactoryPostProcessor > bean , 也就是说初始化完 beanFactory 之后 BeanFactoryPostProcessor 才会被调用,因此 BeanFactoryPostProcessor 是在 bean 初始化之后才会被调用,使用场景:用于定制或者修改 BeanFactory 的内容。

BeanFactoryPostProcessor 原理如下。

1. IOC 容器创建对象:

invokeBeanFactoryPostProcessors(beanFactory);

2. 先根据类型获取各种 postProcessorNames:

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

分类保存为各种 priorityOrderedPostProcessors、orderedPostProcessors、nonOrderedPostProcessors 的集合其实就是各种 BeanFactoryPostProcessor。

然后分别排序上一步的各种集合,按顺序分别执行各种 BeanFactory 的后置处理器。

案例:实现 BeanFactoryPostProcessor 接口。

public interface BeanFactoryPostProcessor {    /**     * 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 overriding or adding     * properties even to eager-initializing beans.     * @param beanFactory the bean factory used by the application context     * @throws org.springframework.beans.BeansException in case of errors     */    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;}
public class FistBeanFactoryPostProcessor implements BeanFactoryPostProcessor {    @Override    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {        int beanDefinitionCount = beanFactory.getBeanDefinitionCount();        System.out.println(\"容器中的 bean 数量:\" + beanDefinitionCount);        int beanPostProcessorCount = beanFactory.getBeanDefinitionCount();        System.out.println(\"beanPostProcessorCount:\" + beanPostProcessorCount);        String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();        for (String beanName : beanDefinitionNames) {            System.out.println(\"beanDefinitionName:\" + beanName);        }        System.out.println(\"--------------------------BeanFactoryPostProcessor is after----------------------------------\");    }    public static void main(String[] args) {        ApplicationContext context = new AnnotationConfigApplicationContext(FistBeanFactoryPostProcessor.class);        String[] beanDefinitionNames = context.getBeanDefinitionNames();        for (String beanName : beanDefinitionNames) {            System.out.println(\"beanName:\" + beanName);        }    }}

输出结果:

输出结果

3. postProcessBeanFactory(beanFactory)

空方法,用于子类扩展功能。

4. BeanDefinitionRegistryPostProcessor

  • 在所有 bean 定义信息将要被加载,bean 实例还未创建的;
  • 优先于 BeanFactoryPostProcessor 执行;
  • 利用 BeanDefinitionRegistryPostProcessor 给容器中再额外添加一些组件。

5. BeanFactoryPostProcessor 原理

IOC 创建对象

refresh() -> invokeBeanFactoryPostProcessors(beanFactory);

从容器中获取到所有的 BeanDefinitionRegistryPostProcessor 组件。

String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class ..);

invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry) -> 依次触发所有的 postProcessBeanDefinitionRegistry() 方法 。

再来触发 invokeBeanFactoryPostProcessors(registryProcessors, beanFactory) -> postProcessBeanFactory() 方法 BeanFactoryPostProcessor。

之后从容器中找到 BeanFactoryPostProcessor 组件,然后依次触发 postProcessBeanFactory() 方法。

案例:

public class FistBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {    @Override    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {        System.out.println(\"FistBeanDefinitionRegistryPostProcessor...bean 的数量:\"+beanDefinitionRegistry.getBeanDefinitionCount());        RootBeanDefinition definition = new RootBeanDefinition(FistBeanFactoryPostProcessor.class);        beanDefinitionRegistry.registerBeanDefinition(\"test\",definition);    }    @Override    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {        System.out.println(\"FistBeanDefinitionRegistryPostProcessor...bean 的数量:\"+configurableListableBeanFactory.getBeanDefinitionCount());    }    public static void main(String[] args) {        ApplicationContext context = new AnnotationConfigApplicationContext(FistBeanDefinitionRegistryPostProcessor.class);        String[] beanDefinitionNames = context.getBeanDefinitionNames();        for (String beanName : beanDefinitionNames) {            System.out.println(\"beanName:\" + beanName);        }    }}

在这里插入图片描述

6. registerListeners()

用于管理 ApplicationListener:

protected void registerListeners() {    // Register statically specified listeners first.    for (ApplicationListener<?> listener : getApplicationListeners()) {        getApplicationEventMulticaster().addApplicationListener(listener);    }    // Do not initialize FactoryBeans here: We need to leave all regular beans    // uninitialized to let post-processors apply to them!    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);    for (String listenerBeanName : listenerBeanNames) {        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);    }    // Publish early application events now that we finally have a multicaster...    //广播事件到对应的监听器;    //earlyApplicationEvents 是在第一个方法 prepareRefresh()中初始化的    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;    this.earlyApplicationEvents = null;    if (earlyEventsToProcess != null) {        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {            getApplicationEventMulticaster().multicastEvent(earlyEvent);        }    }}

7. finishBeanFactoryInitialization(beanFactory)

实例化所有的 bean,除了懒加载的 bean。

8. finishRefresh()

发布所有的事件:

protected void finishRefresh() {    // Clear context-level resource caches (such as ASM metadata from scanning).    clearResourceCaches();    // Initialize lifecycle processor for this context.    initLifecycleProcessor();    // Propagate refresh to lifecycle processor first.    //执行 LifecycleProcessor 的方法    getLifecycleProcessor().onRefresh();    // Publish the final event.    //发布完成事件给所有的监听者    publishEvent(new ContextRefreshedEvent(this));    // Participate in LiveBeansView MBean, if active.    LiveBeansView.registerApplicationContext(this);}

总结

源码执行过程详解

prepareRefresh 准备刷新容器

  1. initPropertySources() 自定义属性设置,空方法,留给子类继承。
  2. getEnvironment.validateRequiredProperties 首先获取环境配置,然后校验必需属性。
  3. this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners); 初始化事件监听器。
  4. this.earlyApplicationEvents = new LinkedHashSet<>(); 初始化早期事件。

obtainFreshBeanFactory 获取组件工厂

  1. refreshBeanFactory 新建一个组件工厂,类型为 DefaultListableBeanFactory,然后对这个组件工厂设置了一个序列化 ID。
  2. getBeanFactory 返回刚刚创建的组件工厂。

prepareBeanFactory 对组件工厂做各种预处理设置

  1. 在组件工厂中设置类加载器、属性解析器等。
  2. 在组件工厂中添加部分组件后置处理器,例如 ApplicationContextAwareProcessor、ApplicationListenerDetector。
  3. 在组件工厂中设置忽略自动注入的接口。
  4. 设置自动装配规则。
  5. 在组件工厂中注册一些组件,例如环境配置 ConfigurableEnvironment。

postProcessBeanFactory 组件工厂的后置处理工作

invokeBeanFactoryPostProcessors 执行组件工厂后置处理器

这一步是在组件工厂的标准初始化(1~4)之后进行的,主要是执行 BeanFactoryPostProcessor 及其子接口的。

BeanFactoryPostProcessor 的子接口主要是指 BeanDefinitionRegistryPostProcessor,可以向容器中注册新的组件,这个接口的特点是有两个方法,一个是自身的 postProcessBeanDefinitionRegistry,另一个继承自 BeanFactoryPostProcessor 的 postProcessBeanFactory,从源码可以看出,Spring 会先执行 BeanDefinitionRegistryPostProcessor 类型的组件的自身方法,然后执行其继承方法,最后才调用非 BeanDefinitionRegistryPostProcessor 的 BeanFactoryPostProcessor 的后置处理方法。

  1. 从容器器中获取 BeanDefinitionRegistryPostProcessor 类型的组件。
  2. 将 BeanDefinitionRegistryPostProcessor 类型的组件按照顺序分类并排序,即是否实现了 PriorityOrdered、Ordered 接口。
  3. 依次执行实现了 PriorityOrdered 接口的、实现了 Ordered 接口的、没有实现任何顺序接口的组件的 postProcessBeanDefinitionRegistry 方法。
  4. 执行所有 BeanDefinitionRegistryPostProcessor 组件的 postProcessBeanFactory 方法。
  5. 从容器中获取其他的 BeanFactoryPostProcessor 类型的组件,即不是 BeanDefinitionRegistryPostProcessor 类型的。
  6. 剩下的步骤跟上面类似,就是先按照实现的顺序接口分类,在每个类别下排序,然后依次执行它们的 postProcessBeanFactory 方法。

registerBeanPostProcessors 注册组件后置处理器

这种处理器用于拦截 bean 的创建过程。beanPostProcessor 有很多子接口,每种子接口的执行时机各有不同。

  • DestructionAwareBeanPostProcessor
  • InstantiationAwareBeanPostProcessor
  • MergedBeanDefinitionPostProcessor
  • SmartInstantiationAwareBeanPostProcessor

1. 获取所有的 beanPostProcessor 的组件名。

2. 将所有的组件按优先顺序分为三类:

  • 实现了 PriorityOrdered 接口的列表 priorityOrderedPostProcessors
  • 实现了 Ordered 接口的列表 orderedPostProcessors
  • 没有实现任何顺序接口的列表 nonOrderedPostProcessors

还有一种特殊情况,凡是 MergedBeanDefinitionPostProcessor 类型的,都放在 internalPostProcessors 中。

3. 注册 priorityOrderedPostProcessors。

4. 注册 orderedPostProcessors。

5. 注册 nonOrderedPostProcessors。

6. 注册 internalPostProcessors。

7. 注册 ApplicationListenerDetector,它的作用是在组件初始化之后判断其是否为 ApplicationListner 类型,如果是,则将其添加进容器的监听器集合。

initMessageSource 初始化消息源组件

用于消息绑定、消息解析等功能,并且提供国际化解决方案。

  1. 获取 beanFactory。
  2. 判断 beanFactory 中是否包含 id 为 messageSource 的组件。
  3. 如果已存在,则赋值给容器的 messageSource 属性,这种情况是我们自己在容器中注册了这个组件。
  4. 如果不存在,则新建一个 DelegatingMessageSource,并赋值给容器的 messageSource 属性,然后在 beanFactory 中注册这个新组件,并设置其 id 为 messageSource。

initApplicationEventMulticaster 初始化事件广播器

  1. 获取 beanFactory。
  2. 判断 beanFactory 中是否存在 id 为 applicationEventMulticaster 的组件
  3. 如果已存在,则赋值给容器的 applicationEventMulticaster 属性,这种情况是我们自己在容器中注册了这个组件。
  4. 如果不存在,则新建一个 SimpleApplicationEventMulticaster,并赋值给容器的 applicationEventMulticaster 属性,然后在 beanFactory 中注册这个新组件, 并设置其 id 为 applicationEventMulticaster。

onRefresh

留给子类继承的,我们可以自定义子容器,在重写方法中做一些我们想要的操作。

registerListeners 注册事件监听器

  1. 获取容器的属性 applicationListeners,这是一个事件监听器的集合,将集合中的每个元素都添加进事件广播器 getApplicationEventMulticaster().addApplicationListener(listener);
  2. 从容器中获取所有 ApplicationListener 类型的组件,将这些组件添加进事件广播器。
  3. 派发之前步骤产生的事件。

finishBeanFactoryInitialization 完成剩下的单实例 bean 的初始化

  1. 进入 DefaultListableBeanFactory.preInstantiateSingletons 方法,获取容器中所有的组件 id 列表。
  2. 获取容器中的所有 Bean,依次进行初始化和创建对象。
  3. Bean 不是抽象的,是单实例的,是非懒加载。

判断是否是 FactoryBean;是否是实现 FactoryBean 接口的 Bean;如果是就用工厂 bean 来创建及 FacBean 中的 getObject 同 SpringIOC 中的二(3)。如果不是工厂 Bean。利用 getBean(beanName) 创建对象。

getBean(beanName); ioc.getBean();
AbstractBeanFactory.doGetBean(name, null, null, false);

先获取缓存中保存的单实例 Bean。如果能获取到说明这个 Bean 之前被创建过(所有创建过的单实例 Bean 都会被缓存起来),Object sharedInstance = getSingleton(beanName); 缓存到 DefaultSingletonBeanRegistry 类的 singletonObjects 单例对象存储的 Map 一级缓存。

缓存中获取不到,开始 Bean 的创建对象流程。标记当前 bean 已经被创建:

markBeanAsCreated(beanName);

获取 Bean 的定义信息:

RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName)

获取当前 Bean 依赖的其他 Bean,如果有按照 getBean(dep) 把依赖的 Bean 先创建出来:

String[] dependsOn = mbd.getDependsOn()

启动单实例 Bean 的创建流程如下:

AbstractAutowireCapableBeanFactory.createBean(beanName, mbd, args);

让 BeanPostProcessor 先拦截返回代理对象:

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

InstantiationAwareBeanPostProcessor 提前执行,先触发 postProcessBeforeInstantiation(),如果有返回值,触发 postProcessAfterInitialization()。

如果前面的 InstantiationAwareBeanPostProcessor 没有返回代理对象,调用 AbstractAutowireCapableBeanFactory.doCreateBean 创建 Bean。

创建 Bean 实例:

createBeanInstance(beanName, mbd, args);

利用工厂方法或者对象的构造器创建出 Bean 实例。

applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

调用 MergedBeanDefinitionPostProcessor 的 postProcessMergedBeanDefinition(mbd, beanType, beanName);

Bean 属性赋值:

populateBean(beanName, mbd, instanceWrapper);

拿到 InstantiationAwareBeanPostProcessor 后置处理器 postProcessAfterInstantiation(),拿到 InstantiationAwareBeanPostProcessor 后置处理器 postProcessPropertyValues()。

为 Bean 属性赋值,为属性利用 setter 方法等进行赋值:

applyPropertyValues(beanName, mbd, bw, pvs);

Bean 初始化:

initializeBean(beanName, exposedObject, mbd);

执行 Aware 接口方法:

invokeAwareMethods(beanName, bean);

执行 xxxAware 接口的方法 BeanNameAware\\BeanClassLoaderAware\\BeanFactoryAware。

执行后置处理器初始化之前:

applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);BeanPostProcessor.postProcessBeforeInitialization();

执行初始化方法:

invokeInitMethods(beanName, wrappedBean, mbd);

是否是 InitializingBean 接口的实现,执行接口规定的初始化,是否自定义初始化方法。

执行后置处理器初始化之后,applyBeanPostProcessorsAfterInitialization 也就是 BeanPostProcessor.postProcessAfterInitialization()。

注册 Bean 的销毁方法:

registerDisposableBeanIfNecessary(beanName, bean, mbd);

将创建的 Bean 添加到缓存中 singletonObjects。

finishRefresh 完成容器刷新

  1. 初始化生命周期处理器(LifecycleProcessor),先从 BeanFactory 中按类型获取,如果没有就新建一个 DefaultLifecycleProcessor,并注册进 BeanFactory。
  2. 获取上一步注册的生命周期处理器,回调其 onRefresh 方法。
  3. 发布容器刷新事件,即 ContextRefreshedEvent。

流程图详解

图解

简述

Spring 容器在启动的时候,先会保存所有注册进来的 Bean 的定义信息:

  • xml 注册 bean:<bean>
  • 注解注册 Bean:@Service、@Component、@Bean、xxx

Spring 容器会合适的时机创建这些 Bean:

  • 用到这个 bean 的时候,利用 getBean 创建 bean,创建好以后保存在容器中。
  • 统一创建剩下所有的 bean 的时候 finishBeanFactoryInitialization()。

后置处理器 BeanPostProcessor

每一个 bean 创建完成,都会使用各种后置处理器进行处理,来增强 bean 的功能。

  • AutowiredAnnotationBeanPostProcessor:处理自动注入
  • AnnotationAwareAspectJAutoProxyCreator:来做 AOP 功能
  • ….
  • 增强的功能注解:AsyncAnnotationBeanPostProcessor
  • ….

事件驱动模型

  • ApplicationListener:事件监听
  • ApplicationEventMulticaster:事件派发
免责声明: 1、本站信息来自网络,版权争议与本站无关 2、本站所有主题由该帖子作者发表,该帖子作者与本站享有帖子相关版权 3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和本站的同意 4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责 5、用户所发布的一切软件的解密分析文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。 6、您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。 7、请支持正版软件、得到更好的正版服务。 8、如有侵权请立即告知本站(邮箱:1099252741@qq.com,备用微信:1099252741),本站将及时予与删除 9、本站所发布的一切破解补丁、注册机和注册信息及软件的解密分析文章和视频仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。
(0)
上一篇 2022年8月29日 下午1:48
下一篇 2022年8月29日 下午1:48

小七学习网,助您升职加薪,遇问题可联系:客服微信【1099252741】 备注:来自网站

相关推荐

  • 金职位_前端工程师32周[完结]

    ├──金职位_前端工程师32周[完结] | ├──阶段1:前端基础入门 | | ├──第1周 HTML5基础语法与标签 | | ├──第2周 CSS3基础语法与盒模型 | | ├──第3周 CSS3浮动定位与背景样式 | | ├──第4周 CSS3动画与穷游首页开发实战 | | ...

    2022年8月25日
    202
  • 经典再升级-FFmpeg音视频核心技术全面精讲+实战

    〖课程介绍〗:      本课程将理论与实战相结合,由浅入深地讲解FFmpeg核心技术,去掉音视频处理的一层层神秘面纱,让你掌握FFmpeg音视频编解码,音视频渲染,不依赖第三方SDK的播放器开发等核…

    2022年8月31日
    351
  • 带后台的IM即时通讯App 全程MVP手把手打造

    〖课程介绍〗:        本课程将全程手把手,带你运用MVP架构,封装思想以及当下主流的技术框架开发一款功能全面的聊天APP(客户端+服务端),让你系统学习IM技术,并拥有一款高质量的APP,最终…

    2022年8月31日
    232
  • 来offer_全栈开发项目实践课程(58.4G)

    来offer_全栈开发项目实践课程(58.4G)/ ├──1-10 | ├──01_.mp4 465.22M | ├──02_.mp4 409.55M | ├──03_.mp4 394.19M | ├──04_.mp4 479.20M | ├──05-1.mp4 151.13M ...

    2022年8月25日
    425
  • 晋级TypeScript高手,成为抢手的前端开发人才

    〖课程介绍〗:        TypeScript已经异常火爆,几乎每一家IT企业在招聘前端时,都要求熟练掌握TS。但许多前端开发者虽然已经使用很多年TS,但是技术仅停留在皮毛,对于TS理解并不透彻。…

    2022年8月31日
    225
  • 微专业 – Java高级开发工程师(完整版)

    微专业 - Java高级开发工程师(完整版)/ ├──阶段1:高性能编程专题 | ├──1.1 互联网系统架构演进之路it课程分享群.mp4 74.27M | ├──1.1.1 JAVA程序运行原理分析it课程分享群.mp4 43.73M | ├──1.1.2 安装it课程分享群...

    2022年8月25日
    170
  • 深入JavaScript高级语法-coderwhy大神新课

    深入JavaScript高级语法-coderwhy大神新课 该课程的核心目的是深入学习JavaScript的核心语法,特别是JavaScript比较复杂的、难以理解的一些概念和特性...

    2022年6月15日
    397
  • 遇问题可联系 / 客服微信【1099252741】
  • 金职位_人人都能学会数据分析(完结)百度网盘慕课下载

    2021年金职位人人都能学会数据剖析分享下载 数据剖析是指用恰当的统计剖析办法对搜集来的大量数据进行剖析,将它们加以汇总和了解并消化,以求最大化地开发数据的功用,发挥数据的效果。数据剖析是为了提取有用信息和构成定论而对数据加以具体研讨和归纳总结的进程 数据剖析是指用恰当的统...

    2022年8月25日
    304
  • Selenium3.0 平台级自动化测试框架综合实战

    〖课程介绍〗:      本课程将从理论到实战,全面完整的带你搭建集持续集成、单元测试、脚本编程、测试报告、邮件通知以及测试结果大数据统计为一体的自动化测试框架,让你深入理解自动化测试框架的设计原理,…

    2022年8月31日
    173