凌月风的个人博客

记录精彩人生

Open Source, Open Mind,
Open Sight, Open Future!
  menu

Java笔记系列——03-源码分析(Spring)

0 浏览

Spring简介

  • Spring是轻量级的开发框架,根本使命在于简开发,Spring 采用了4个关键策略
    • 基于POJO的轻量级和最小侵入性编程
    • 通过依赖注入和面向接口松耦合
    • 基于切面和惯性进行声明式编程
    • 通过切面和模板减少样板式代码
  • Spring 是面向 Bean 的编程(Bean Oriented Programming, BOP) , Bean 在 Spring 中才是真正的主角

  • 注解使用

    • 配置组件

      • @Configuration:把一个类作为IoC容器,它的某个方法上如果使用了@Bean注解,则会将方法返回值作为容器中的一个Bean
      • @ComponentScan:在配置类上加上该注解,会扫描该配置类所在的包下的所有配置类,并加入IoC容器
      • @Scope:用于指定作用域
      • @Lazy:延迟初始化
      • @Conditional:Spring4开始提供,作用是按照一定的条件判断,满足条件给容器注册Bean
      • @Import:导入外部资源
      • @PostConstruct:用于指定初始化方法
      • @PreDestory:用于指定销毁方法
      • @DependsOn:定义Bean初始化和销毁时的顺序
    • 自动装配组件

      • @Componet、@Service、@Controller、@Repository泛指组件
      • @Value:普通数据类型赋值
      • @Autowired、@Resource、@Qualifier:依赖注入组件
      • @PropertySource:读取配置文件
      • @Primary:自动装配多个Bean候选者时,该注解的Bean作为首选在
    • 织入组件

      • ApplicationContextAware:可以通过这个上下文环境对象得到Spring容器中的Bean
      • BeanDefinitionRegistryPostProcessor:实现了BeanFascoryPostProcessor接口,是Spring框架的BeanDefinitionRegistry的后处理器,用来注册额外的BeanDefinition
    • 切面组件

      • @EnableTransactionManagement:添加对事务管理的支持
      • @Transactional:配置声明式事务信息

模块划分

  • Spring框架源码模块划分

    • 核心模块

      image-20220722151100058

    • 切面编程

      image-20220722151129025

    • 数据访问与集成

      image-20220722151201685

    • Web组件

      image-20220722151223590

    • 通信报文

      image-20220722151318250

    • 集成测试

      image-20220722151333366

    • 集成兼容

      image-20220722151351110

    • 各模块之间依赖关系

      image-20220722151255305


核心原理

  • Spring 中最核心的功能要数IoC Container和AOP,源码分析也是从此开始

  • 关键类及类图

    • BeanFactory
      • 典型的工厂模式,是IoC容器的最顶层设计
      • 定义了IoC容器的基本功能规范,有众多的子类为不同的使用场景提供了不同实现BeanFactory
    • ApplicationContext
      • 继承了BeanFactory。属于Spring 提供的高级容器
      • 在基础容器之上还提供了许多容器之外的功能,都是通过继承不同的接口实现的
      • AbstractApplicationContext是一个ApplicationContext的关键抽象实现,有众多子类实现ApplicationContextAbstractApplicationContext
    • BeanDefinition
      • IoC容器管理的许多Bean以及Bean之间的关系,在Spring中是以BeanDefinition形式表述BeanDefinition
    • BeanWapper
    • BeanDefinitionReader
      • 主要完成对于Bean的解析,Spring 配置文件BeanDefinitionReader

源码分析

启动入口

  • Spring框架的启动入口是上下文对象AbstractApplicationContext类的refresh()方法

    • refresh()是一个模板方法,定义了IoC容器的启动流程。
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            //1、调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
            prepareRefresh();
            //2、告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从
            //子类的refreshBeanFactory()方法启动
            // 创建容器的关键方法
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            //3、为BeanFactory配置容器特性,例如类加载器、事件处理器等
            prepareBeanFactory(beanFactory);
            try {
                //4、为容器的某些子类指定特殊的BeanPost事件处理器
                postProcessBeanFactory(beanFactory);
                //5、调用所有注册的BeanFactoryPostProcessor的Bean
                invokeBeanFactoryPostProcessors(beanFactory);
                //6、为BeanFactory注册BeanPost事件处理器.
                //BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件
                registerBeanPostProcessors(beanFactory);
                //7、初始化信息源,和国际化相关.
                initMessageSource();
                //8、初始化容器事件传播器.
                initApplicationEventMulticaster();
                //9、调用子类的某些特殊Bean初始化方法
                onRefresh();
                //10、为事件传播器注册事件监听器.
                registerListeners();
                //11、初始化所有剩余的单例Bean
                finishBeanFactoryInitialization(beanFactory);
                //12、初始化容器的生命周期事件处理器,并发布容器的生命周期事件
                finishRefresh();
            } catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    // s
                    logger.warn();
                }
                //13、销毁已创建的Bean
                destroyBeans();
                //14、取消refresh操作,重置容器的同步标识。
                cancelRefresh(ex);
                throw ex;
            } finally {
                //15、重设公共缓存
                resetCommonCaches();
            }
        }
    }
    

  • 通过xml配置的形式使用Spring时,Spring是以ClassPathXmlApplicationContext为起点进行启动的。可以从创建对象的源码中发现,在创建对象的时候调用了继承自父类的refresh()方法

    // 启动Spring,以及使用
    public static void main(String[] args) {
        // 1. 创建ClassPathXmlApplicationContext对象
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.properties");
        // 获取上下文中的对象
        User user = (User) context.getBean("user");
        System.out.println(user.getUsername());
    }
    //--------------------------------------分析--------------------------------------
    // 常用构造方法
    public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
        // 2. 调用重载的构造方法
        this(new String[] {configLocation}, true, null);
    }
    // 重载构造方法
    public ClassPathXmlApplicationContext(
        String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
        throws BeansException {
    
        super(parent);
        // xml配置文件的解析
        setConfigLocations(configLocations);
        // 3. 关键代码:调用了refresh()方法
        if (refresh) {
            refresh();
        }
    }
    

  • 通过注解的形式使用Spring时,Spring是以AnnotationConfigApplicationContext 为起点进行启动的。可以从创建对象的源码中发现,在创建对象的时候调用了继承自父类的refresh()方法

    // 启动Spring方式1,手动注册、手动启动
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(BeanConfig.class);
        context.refresh();
        User user =  context.getBean(User.class);
        user.say();
    }
    // 启动Spring方式2,直接通过配置文件创建
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
        User user =  context.getBean(User.class);
        user.say();
    }
    // 启动Spring方式3,通过包路径扫描
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("cn.com.rxdu.jobgrab");
        User user =  context.getBean(User.class);
        user.say();
    }
    //-------------------------------------分析----------------------------------
    // 通过配置文件创建构造方法
    public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
        this();
        // 配置文件解析注册
        register(componentClasses);
    	// 关键代码:调用了refresh()方法
        refresh();
    }
    // 通过包路径扫描创建构造方法
    public AnnotationConfigApplicationContext(String... basePackages) {
        this();
        // 包扫描
        scan(basePackages);
        // 关键代码:调用了refresh()方法
        refresh();
    }
    

  • 结合SpringMVC使用时,Spring是以ContextLoaderListener为起点进行启动的。

    1. 在web.xml中配置监听器,然后将项目部署到web容器,比如Tomcat中时。
    2. web容器启动时会启动监听,调用初始化方法contextInitialized()
    3. 在此过程中,会默认创建上下文对象XmlWebApplicationContext,并且会调用该对象的refresh()方法
    <!-- 系统组件加载顺序:context-param -> listener -> filter -> servlet -->
    <!-- spring 配置文件 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/applicationContext.xml</param-value>
    </context-param>
    
    <!-- 监听器 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    <!-- 配置dispatcherServlet -->
    <servlet>
        <servlet-name>ota</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/mvc-core-config.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    // ContextLoaderListener类的初始化方法
    public void contextInitialized(ServletContextEvent event) {
        initWebApplicationContext(event.getServletContext());
    }
    // 初始化web容器
    public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
        // 检测servlet容器中是否存在spring上下文对象,如果存在直接抛出异常
        if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
            // 日志作了删减处理
            throw new IllegalStateException();
        }
        // 此处省略部分非关键代码........
        try {
            // 关键代码: 创建spring上下文对象
            if (this.context == null) {
                // 会查询web.xml配置中是否存在contextClass属性配置
                // 如果存在,根据该属性的值创建对相应的Spring上下文对象
                // 如果不存在,则根据spi机制,查找ContextLoader.properties文件
                // 根据ContextLoader.properties文件属性值默认创建 XmlWebApplicationContext
                // 详细逻辑查看源代码
                this.context = createWebApplicationContext(servletContext);
            }  
            // XmlWebApplicationContext间接实现了ConfigurableWebApplicationContext
            if (this.context instanceof ConfigurableWebApplicationContext) {
                ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
                if (!cwac.isActive()) {
                    if (cwac.getParent() == null) {
                        ApplicationContext parent = loadParentContext(servletContext);
                        cwac.setParent(parent);
                    }
                    // 关键代码 读取相应的配置并且刷新context对象
                    configureAndRefreshWebApplicationContext(cwac, servletContext);
                }
            }
            // 将spring上下文对象加入到Servlet容器
            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
             // 此处省略部分非关键代码........
            return this.context;
        }
        catch (RuntimeException | Error ex) {
            logger.error("Context initialization failed", ex);
            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
            throw ex;
        }
    }
    // 通过refresh启动Spring
    protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
       // 此处省略部分代码........
        wac.refresh();
    }
    

  • 使用SpringBoot时,Spring是以SpringApplication为起点进行启动的。在执行run()方法时,会创建上下文对象,最终创建的是AnnotationConfigServletWebServerApplicationContext,然后执行refresh()方法

    //  启动SpringBoot
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class,args);
    }
    // 调用了SpringApplication 类的 ConfigurableApplicationContext 方法
    public ConfigurableApplicationContext run(String... args) {
        // 省略部分代码.......
        ConfigurableApplicationContext context = null;
        try {
            // 环境配置解析相关
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            configureIgnoreBeanInfo(environment);
            // 创建banner图
            Banner printedBanner = printBanner(environment);
            // 创建上下文对象,最终创建的是 AnnotationConfigServletWebServerApplicationContext
            context = createApplicationContext();
            context.setApplicationStartup(this.applicationStartup);
             // 初始化上下文对象
            prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
             // 刷新Spring容器
            refreshContext(context);
            // 省略部分代码.......
        }
       // 省略部分代码.......
        return context;
    }
    // 刷新上下文
    private void refreshContext(ConfigurableApplicationContext context) {
        if (this.registerShutdownHook) {
            shutdownHook.registerApplicationContext(context);
        }
        refresh(context);
    }
    protected void refresh(ConfigurableApplicationContext applicationContext) {
        //关键代码 refresh
        applicationContext.refresh();
    }
    

容器初始化

  • 步骤总结
    1. 调用refresh()方法之后,执行obtainFreshBeanFactory()方法,创建容器
    2. 生成容器对象DefaultListableBeanFactory
    3. 加载BeanDefinition放入到容器中
      • 根据DefaultListableBeanFactory创建XmlBeanDefinitionReader或者AnnotatedBeanDefinitionReader来解析bean定义信息
      • 将解析好的bean信息定义封装成BeanDefinition对象,再将BeanDefinition对象封装为BeanDefinitionHolder对象
      • BeanDefinitionHolder对象中持有BeanDefinition以及别名信息
      • 调用容器对象DefaultListableBeanFactory的registerBeanDefinition()方法将BeanDefinition信息放到容器中的属性 Map<String, BeanDefinition> beanDefinitionMap
    4. 将生成的容器对象DefaultListableBeanFactory加入到上下文对象的属性beanFactory中
    5. 至此,完成了容器的创建,并将对象的定义信息交给了对象工厂类,相当于IoC容器初始化步骤完成。

  • 根据Spring 启动的入口refresh()方法来进行分析

    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            //1、调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
            prepareRefresh();
            //2、告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从
            // 子类的refreshBeanFactory()方法启动
            // 创建容器的关键方法
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
           // 省略部分代码............
        }
    }
    
  • 容器的创建关键方法是obtainFreshBeanFactory(),最终返回的BeanFactory是DefaultListableBeanFactory,并存储到了AbstractRefreshableApplicationContext的属性中

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        refreshBeanFactory();
        return getBeanFactory();
    }
    protected final void refreshBeanFactory() throws BeansException {
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            // 创建 DefaultListableBeanFactory 对象
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);
            // 加载BeanDefinition
            loadBeanDefinitions(beanFactory);
            // 加入到上下文属性中
            this.beanFactory = beanFactory;
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }
    
  • 在创建容器的过程中,有一个步骤是加载BeanDefiniton,这个步骤是将bean定义封装为BeanDefinition,加载到容器当中。

    • 其中有两个关键对象
      • BeanDefinition的作用是用于在Spring容器初始化的时,将bean的参数转化为Spring内部的BeanDefinition的结构
      • BeanDefinitionHolder顾名思义就是对BeanDefinition的持有,同时持有的包括BeanDefinition的名称和别名
    1. 如果bean的定义使用注解,则使用AnnotatedBeanDefinitionReader加载解析
    2. 如果bean的定义在xml文件中配置,则使用XmlBeanDefinitionReader加载解析
    3. 在DefinitionReader加载解析完成之后,生成了BeanDefinitionHolder对象
    4. 然后调用DefaultListableBeanFactory的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法将BeanDefinition存储到容器中
    
    // DefaultListableBeanFactory中的属性,beanDefinition容器
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
    
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
        throws BeanDefinitionStoreException {
    
        // 省略部分代码......
    
        // 从beanDefinitionMap中获取名称对应的BeanDefinition
        BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
        if (existingDefinition != null) {
            // 如果已经存在并且不允许覆盖直接抛出异常
            if (!isAllowBeanDefinitionOverriding()) {
                throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
            }
            // 省略部分代码......
            this.beanDefinitionMap.put(beanName, beanDefinition);
        }
        else {
            // 省略部分代码......
            this.beanDefinitionMap.put(beanName, beanDefinition);
    
        }
    	// 省略部分代码......
    }
    

依赖注入

  • 依赖注入即DI(Dependency Injection)主要做两件事:对象实例化和自动装配。

  • 依赖注入的入口只有一个就是BeanFactory的getBean()方法

    • Spring默认是懒加载,所以在IoC容器的初始化阶段并没有生成bean对象,当调用BeanFactory的getBean()方法才实际创建对象。
    • 如果设置了非懒加载,那么在容器启动的时候就需要生成bean对象,在容器启动的refresh()方法中有一个方法调用finishBeanFactoryInitialization(beanFactory);,此方法就是非懒加载情况下的对象实例化方法,该方法最终也是调用BeanFactory的getBean()方法去创建对象的
    • 因此,依赖注入就是从getBean()开始的

  • 步骤总结

    1. 调用getBean()方法

    2. 查找需要的bean是否在缓存中

    3. 如果存在于缓存中,直接获取并返回

    4. 如果不存在则创建对象,通过层层调用之后,通过反射创建对象实例,并将创建的对象封装为BeanWapper对象

    5. 通过AbstractAutowireCapableBeanFactory类的populateBean()方法完成创建对象的属性注入

    6. 属性注入之后,执行initializeBean(beanName, exposedObject, mbd);方法。完成bean的初始化,代理等操作

    7. 将生成的对象放入到缓存中

      • 循环依赖依靠缓存来解决,递归调用getBean()方法
      • 一级缓存:成熟的已经注入完属性的bean
      • 二级缓存:纯净的bean,还没有依赖注入
      • 三级缓存:创建代理Bean的Factory
      • 递归调用缓存使用示意

      image-20220630190346445


实例化对象

  • 从依赖注入的入口开始分析,即从调用AbstractBeanFactry的getBean()开始

    // AbstractBeanFactry类的getBean()方法
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }
    
    protected <T> T doGetBean(
        String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
        throws BeansException {
    
        String beanName = transformedBeanName(name);
        // 实例对象
        Object beanInstance;
    
        // Eagerly check singleton cache for manually registered singletons.
        // 检查实例是否在缓存中存在(会依次检查多级缓存,缓存中是共享的状态)
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            // 省略部分代码......
    
            // 如果要获取的bean对象名字是&开头的那么直接返回 sharedInstance
            // 如果名字不以&开头,并且不是工厂类那么直接返回 sharedInstance
            // 如果名字不以&开头,并且是工厂类那么经过一系列处理之后直接返回 sharedInstance
            beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
    
        else {
    
            // 省略部分代码......
            Object scopedInstance = scope.get(beanName, () -> {
                beforePrototypeCreation(beanName);
                try {
                    return createBean(beanName, mbd, args);
                }
                finally {
                    afterPrototypeCreation(beanName);
                }
            });
            beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
            // 省略部分代码......
        }
    
        return adaptBeanInstance(name, beanInstance, requiredType);
    }
    

  • 首先检查缓存中是否已经存在bean对象,如果存在直接返回,如果不存在则通过createBean()创建新对象

    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
        // 省略部分代码......
    
        //如果Bean配置了初始化前和初始化后的处理器,则试图返回一个需要创建Bean的代理对象
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean;
        }
    
        // 省略部分代码......
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isTraceEnabled()) {
            logger.trace("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
        // 省略部分代码......
    }
    

  • createBean()方法中调用了AbstractAutowireCapableBeanFactory类的doCreateBean()方法创建bean对象

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
    
        // 创建BeanWrapper对象
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            // 真实创建对象实例的方法
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
    
        //  省略部分代码.......
        // 依赖注入方法
        populateBean(beanName, mbd, instanceWrapper);
        // bean初始化:设置代理等初始化方法调用等
        exposedObject = initializeBean(beanName, exposedObject, mbd);
        //  省略部分代码.......
    
        return exposedObject;
    }
    

  • doCreateBean()方法中调用了createBeanInstance()方法,根据定义的构造方法创建对象

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
        // 省略部分代码......
    
        // 有参构造
        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
            return autowireConstructor(beanName, mbd, ctors, args);
        }
        // 省略部分代码......
    
        // 无参构造
        return instantiateBean(beanName, mbd);
    }
    protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
        try {
            Object beanInstance;
            // 省略部分代码......
            // 通过反射创建对象
            if (System.getSecurityManager() != null) {
                beanInstance = AccessController.doPrivileged(
                    (PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
                    getAccessControlContext());
            }
            else {
                beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
            }
            // 将实例化的对象封装成BeanWrapper
            BeanWrapper bw = new BeanWrapperImpl(beanInstance);
            initBeanWrapper(bw);
            return bw;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
        }
    }
    

属性注入

  • 属性的注入是在创建实例对象的时候调用 的,在创建对象的方法doCreateBean()中,有一部分是 populateBean()

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
        //  省略部分代码.......
        // 依赖注入方法
        populateBean(beanName, mbd, instanceWrapper);
        exposedObject = initializeBean(beanName, exposedObject, mbd);
        //  省略部分代码.......
    
        return exposedObject;
    }
    //将Bean属性设置到生成的实例对象上
    protected void populateBean(String beanName
                                , RootBeanDefinition mbd
                                , @Nullable BeanWrapper bw) {
        // 省略部分代码......
        //获取容器在解析Bean定义资源时为BeanDefiniton中设置的属性值
        PropertyValues pvs
            = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
        // 省略部分代码......
    
        //对属性进行注入
        applyPropertyValues(beanName, mbd, bw, pvs);
    
    }
    

切面编程

  • 步骤总结
    1. 在spring启动阶段,会向容器中注册许多BeanPostProcesser
    2. 在bean实例化阶段,会调用已经注册好的BeanPostProcesser实例的postProcessAfterInitialization()方法
    3. 最终通过AbstractAutoProxyCreator类的postProcessAfterInitialization() 方法,完成代理对象的创建

  • 在容器启动阶段会在上下文对象的beanFactory中注册多个bean后置处理器,其中会有一个AnnotationAwareAspectJAutoProxyCreator

    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
    
            prepareRefresh();
    
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            //为BeanFactory配置容器特性,例如类加载器、事件处理器等
            prepareBeanFactory(beanFactory);
            try {
                //4、为容器的某些子类指定特殊的BeanPost事件处理器
                postProcessBeanFactory(beanFactory);
                //5、调用所有注册的BeanFactoryPostProcessor的Bean
                invokeBeanFactoryPostProcessors(beanFactory);
                //6、为BeanFactory注册BeanPost事件处理器.
                //BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件
                registerBeanPostProcessors(beanFactory);
               // 省略部分代码......
    }
    
  • 在依赖注入的bean实例化阶段,会调用bean的初始化方法,在此阶段会执行容器初始化时注册的bean处理器方法

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
        //  省略部分代码.......
        // 依赖注入方法
        populateBean(beanName, mbd, instanceWrapper);
        // 初始化方法
        exposedObject = initializeBean(beanName, exposedObject, mbd);
        //  省略部分代码.......
    
        return exposedObject;
    }
    // bean初始化方法
    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        // 省略部分代码....
        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            // 在初始化之前调用bean后置处理器方法, @PostConstruct的方法在这一步执行
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }
        // 省略部分代码....
        // 初始化方法
        invokeInitMethods(beanName, wrappedBean, mbd);
    
        // 省略部分代码....
        if (mbd == null || !mbd.isSynthetic()) {
            // 在初始化之后调用bean后置处理器方法
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
    
        return wrappedBean;
    }
    
  • 在执行bean后置处理器方法 applyBeanPostProcessorsAfterInitialization(),会执行容器初始化阶段设置的所有BeanPostProsser子类的postProcessAfterInitialization()方法。AOP相关的AnnotationAwareAspectJAutoProxyCreator,会调用父类AbstractAutoProxyCreator的相关方法

    // AbstractAutoProxyCreator
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                // 对初始化的bean进行一层包装
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }
    
        // Create proxy if we have advice.
        // 创建AOP代理对象
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            Object proxy = createProxy(
                bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }
    
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
    

MVC

  • 九大组件image-20220702120357747

  • 关系类图DispatcherServlet

  • 步骤总结

    1. 在Spring启动时,会初始化一些非懒加载的Bean。其中有与MVC相关的重要的两个类RequestMappingHandlerMapping与RequestMappingHandlerAdapter

      • RequestMappingHandlerMapping对象在实例化时,会将所有的Controller中对应的支持请求的方法以及支持访问的地址封装成HandlerMethod,存储到属性当中
    2. 在接收到请求时,会创建DispatcherServlet实例对象。

      • 实例创建时会根据继承关系,调用HttpServletBean中的init()方法,最终执行到initStrategies()来完成SpringMVC的组件初始化
      • 组件初始化过程中会将RequestMappingHandlerMapping与RequestMappingHandlerAdapter加入到属性DispatcherServlet属性中,分别是handlerMappingshandlerAdapters
    3. 接受到请求时,会先根据DispatcherServlet属性中的handlerMappings查找具体的执行HandlerMethod,然后将该HandlerMethod与拦截器封装为HandlerExecutionChain对象

    4. 找到HandlerAdapter反射执行HandlerMethod对象中的具体Controller方法


  • web容器启动时,会启动Spring容器,Spring启动时会在refresh()方法中执行finishBeanFactoryInitialization()初始化所有非懒加载单例对象

    public void refresh() throws BeansException, IllegalStateException {
        // 省略部分代码......
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);
    
    
        postProcessBeanFactory(beanFactory);
    
    
        invokeBeanFactoryPostProcessors(beanFactory);
    
        // Register bean processors that intercept bean creation.
        registerBeanPostProcessors(beanFactory);
        // 省略部分代码......
    
        // 初始化所有非懒加载单例
        finishBeanFactoryInitialization(beanFactory);
        // 省略部分代码......
    }
    
  • 其中有一个类RequestMappingHandlerMapping,这个类是HandlerMapping的关键类,该类间接实现了InitializingBean接口,因此在实例化之后会执行其afterPropertiesSet()方法。通过继承关系最终执行父类AbstractHandlerMethodMapping的afterPropertiesSet()方法

    public void afterPropertiesSet() {
        initHandlerMethods();
    }
    protected void initHandlerMethods() {
        for (String beanName : getCandidateBeanNames()) {
            if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
                // 关键方法
                processCandidateBean(beanName);
            }
        }
        handlerMethodsInitialized(getHandlerMethods());
    }
    protected void processCandidateBean(String beanName) {
        // 省略部分代码......
        if (beanType != null && isHandler(beanType)) {
            // 关键方法
            detectHandlerMethods(beanName);
        }
    }
    
  • 通过detectHandlerMethods()方法,将所有的映射到的方法以及所属的handler封装为MappingRegistry,加入到RequestMappingHandlerMapping的属性中

    protected void detectHandlerMethods(Object handler) {
        // 省略部分代码......
        // 所有请求映射到的controller的方法
        methods.forEach((method, mapping) -> {
            Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
            // 根据方法名称、请求映射、所属controller进行注册
            registerHandlerMethod(handler, invocableMethod, mapping);
        });
    
    }
    protected void registerHandlerMethod(Object handler, Method method, T mapping) {
        this.mappingRegistry.register(mapping, handler, method);
    }
    
    // RequestMappingHandlerMapping类的属性
    private final MappingRegistry mappingRegistry = new MappingRegistry();
    
  • MappingRegistry时一个内部类,结构如图

    class MappingRegistry {
        // 存储的是url与controller方法的对应关系
        private final Map<T, MappingRegistration<T>> registry = new HashMap<>();
    	// 映射的url地址
        private final MultiValueMap<String, T> pathLookup = new LinkedMultiValueMap<>();
    	// 方法名称
        private final Map<String, List<HandlerMethod>> nameLookup = new ConcurrentHashMap<>();
    
        // 省略部分代码......
    }
    
  • web容器启动时,会启动Spring容器。在接收到请求时会根据web.xml配置,调用DispatchServlet的init()方法进行初始化

    // 根据DispatchServlet的继承体系找到HttpServletBean 继承了HttpServlet
    public final void init() throws ServletException {
    
        // 省略部分代码....
        initServletBean();
    }
    
  • 初始化容器方法init()执行之后,调用到了FrameworkServlet的initServletBean()方法

    protected final void initServletBean() throws ServletException {
        // 省略部分代码......
        // 关键代码,初始化web上下文
        this.webApplicationContext = initWebApplicationContext();
        initFrameworkServlet();
        // 省略部分代码......
    }
    
  • 在初始化上下文的方法中,执行到了关键代码onRefresh()

    protected WebApplicationContext initWebApplicationContext() {
        // 省略部分代码......
        onRefresh(wac);
        // 省略部分代码......
    }
    
  • 通过onRefresh()方法,调用初始化策略,初始化SpringMVC的九大组件

    protected void onRefresh(ApplicationContext context) {
        initStrategies(context);
    }
    
    protected void initStrategies(ApplicationContext context) {
        initMultipartResolver(context);
        initLocaleResolver(context);
        initThemeResolver(context);
        // 初始化处理器映射器
        initHandlerMappings(context);
        // 初始化处理器适配器
        initHandlerAdapters(context);
        initHandlerExceptionResolvers(context);
        initRequestToViewNameTranslator(context);
        initViewResolvers(context);
        initFlashMapManager(context);
    }
    
  • 在初始化处理器映射器时,将RequestMappingHandlerMapping加入到DispatchServlet属性handlerMappings

    private List<HandlerMapping> handlerMappings;
    
    private void initHandlerMappings(ApplicationContext context) {
        this.handlerMappings = null;
    
        if (this.detectAllHandlerMappings) {
    
            // 关键代码,将IoC容器中的HandlerMapping 找出来,加入到 handlerMappings中
            Map<String, HandlerMapping> matchingBeans =
                BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
            if (!matchingBeans.isEmpty()) {
                this.handlerMappings = new ArrayList<>(matchingBeans.values());
               // 排序
                AnnotationAwareOrderComparator.sort(this.handlerMappings);
            }
        }
        // 省略部分代码......
    }
    
  • 在接受到web请求时,会调用servlet的doService()方法,最终执行 到了DispatcherServlet的doDispatch()方法。

    protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 省略部分代码......
        doDispatch(request, response);
        // 省略部分代码......
    }
    
  • doDispatch()方法中首先会根据请求地址,去handlerMappings中 查找对应的具体执行方法,根据查询结果返回一个HandlerMethod对象。然后将对象以及所有的Interceptor封装为执行链对象HandlerExecutionChain

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HandlerExecutionChain mappedHandler = null;
        // 省略部分代码......
        // 查找具体对应的handler
        mappedHandler = getHandler(processedRequest);
        // 省略部分代码......
    }
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        // 省略部分代码......
        HandlerExecutionChain handler = mapping.getHandler(request);
        // 省略部分代码......
    }
    public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        // 根据请求url找到RequestMappingHandlerMapping属性MappingRegistry中的执行方法
        Object handler = getHandlerInternal(request);
        // 省略部分代码......
        // 封装执行链
        HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
        // 省略部分代码......
        return executionChain;
    }
    // 将具体的执行器,和拦截器封装为HandlerExecutionChain对象
    protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
        // 省略部分代码......
        for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
            if (interceptor instanceof MappedInterceptor) {
                MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
                if (mappedInterceptor.matches(request)) {
                    chain.addInterceptor(mappedInterceptor.getInterceptor());
                }
            }
            else {
                chain.addInterceptor(interceptor);
            }
        }
        return chain;
    }
    // HandlerExecutionChain结构
    public class HandlerExecutionChain {
        // 省略部分代码......
        // 具体的处理器对象controller
        private final Object handler;
    
        private final List<HandlerInterceptor> interceptorList = new ArrayList<>();
        // 省略部分代码......
    }
    
  • 找到与HandlerMapping对应的HandlerAdapter。此处应该是RequestMappingHandlerMapping与之对应的RequestMappingHandlerAdapter。这两个类都是在Spring启动时加入到Spring容器中的。然后反射调用实际的Handler方法,返回ModelAndView对象

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 省略部分代码......
        HandlerExecutionChain mappedHandler = null;
        // 省略部分代码......
        mappedHandler = getHandler(processedRequest);
        // 省略部分代码......
        // 找到对应的HandlerAdapter
        HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
        // 省略部分代码......
        // 执行具体处理逻辑
        mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
        // 省略部分代码......
    }
    
    // 父类为AbstractHandlerMethodAdapter类的handler方法
    public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
        return handleInternal(request, response, (HandlerMethod) handler);
    }
    
    protected ModelAndView handleInternal(HttpServletRequest request,
                                          HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    
        ModelAndView mav;
        // 省略部分代码......
        mav = invokeHandlerMethod(request, response, handlerMethod);
        // 省略部分代码......
    
        return mav;
    }
    protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
                                               HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    
        // 省略部分代码......
        ServletWebRequest webRequest = new ServletWebRequest(request, response);
        ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
        ModelAndViewContainer mavContainer = new ModelAndViewContainer();
        // 省略部分代码......
    
        // 关键调用
        invocableMethod.invokeAndHandle(webRequest, mavContainer);
        // 省略部分代码......
        return getModelAndView(mavContainer, modelFactory, webRequest);
        // 省略部分代码......
    }
    public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
                                Object... providedArgs) throws Exception {
        // 关键调用
        Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
        // 省略部分代码......
    }
    public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
                                   Object... providedArgs) throws Exception {
    	// 参数处理,方法执行所需参数已经封装到了 HandlerMethod对象中,有了需要的参数和请求参数就可以做处理了
        Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
        // 省略部分代码......
        return doInvoke(args);
    }
    protected Object doInvoke(Object... args) throws Exception {
        Method method = getBridgedMethod();
        // 省略部分代码......
        return method.invoke(getBean(), args);
        // 省略部分代码......
    }
    
  • doDispatch()中的后续流程不再分析

image/svg+xml