• spring框架源码十四、源码剖析注意事项及容器初始化主体流程


    源码剖析注意事项

    原则

    1、聚焦原则
    抓主线
    2、宏观原则
    关注源码结构和业务流程,淡化具体某一行代码的编写细节

    方法

    1、断点,debug观察调用栈
    2、调用,find usages
    3、经验,spring中doXyz,一般是某些具体处理

    容器初始化主体流程

    容器继承体系

    ioc容器是spring的核心模块,是抽象了bean管理、依赖关系维护的解决方案。
    spring提供了很多容器,BeanFactory是顶层容器,它定义了容器遵循的原则,
    ApplicationContext是BeanFactory的一个子接口,
    具体的实现容器有,
    ClassPathXmlApplicationContext:包含了xml解析的一系列内容,AnnotationConfigApplicationContext:包含了注解解析的一系列内容,
    等。

    我们以ClassPathXmlApplicationContext为例,深入源码说明spring ioc容器的初始化流程。

    代码

    在myspring项目中有
    在这里插入图片描述

    TestServiceImpl

    com.duohoob.spring.ioc.TestServiceImpl

    package com.duohoob.spring.ioc;
    
    import org.springframework.beans.factory.InitializingBean;
    
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
    
    /**
     *
     */
    public class TestServiceImpl implements InitializingBean {
    
    	public TestServiceImpl() {
    		System.out.println("TestServiceImpl构造方法");
    	}
    
    	/**
    	 * 相当于xml中的init-method方法
    	 */
    	@PostConstruct
    	public void init() {
    		System.out.println("创建bean");
    	}
    
    	/**
    	 * 相当于xml中的destroy-method方法
    	 */
    	@PreDestroy
    	public void destroy() {
    		System.out.println("销毁bean");
    	}
    
    	/**
    	 * 实现了InitializingBean的类,bean初始化时会调用afterPropertiesSet,在init-method之前
    	 * @throws Exception
    	 */
    	@Override
    	public void afterPropertiesSet() throws Exception {
    		System.out.println("TestServiceImpl afterPropertiesSet");
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    application-context.xml

    src\main\resources\application-context.xml

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"
           default-lazy-init="false">
    
    	
    	<context:component-scan base-package="com.duohoob.spring"/>
    
        <bean id="testService" class="com.duohoob.spring.ioc.TestServiceImpl"/>
    
    beans>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    MyBeanPostProcessor

    com.duohoob.spring.ioc.MyBeanPostProcessor

    package com.duohoob.spring.ioc;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import org.springframework.stereotype.Component;
    
    /**
     * Bean后置处理器
     * 2022年11月3日
     */
    @Component
    public class MyBeanPostProcessor implements BeanPostProcessor {
    
    	public MyBeanPostProcessor() {
    		System.out.println("MyBeanPostProcessor构造方法");
    	}
    
    	@Override
    	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    		// TODO Auto-generated method stub
    		if ("testService".equals(beanName)) {
    			System.out.println("init-method之前");
    		}
    		return bean;
    	}
    
    	@Override
    	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    		// TODO Auto-generated method stub
    		if ("testService".equals(beanName)) {
    			System.out.println("init-method之后");
    		}
    		return bean;
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    MyBeanFactoryPostProcessor

    com.duohoob.spring.ioc.MyBeanFactoryPostProcessor

    package com.duohoob.spring.ioc;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    import org.springframework.stereotype.Component;
    
    /**
     * BeanFactory后置处理器
     * 2022年11月3日
     */
    @Component
    public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    
    	public MyBeanFactoryPostProcessor() {
    		System.out.println("MyBeanFactoryPostProcessor构造方法");
    	}
    
    	@Override
    	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    		System.out.println("MyBeanFactoryPostProcessor postProcessBeanFactory");
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    IocTest

    com.duohoob.spring.ioc.IocTest

    package com.duohoob.spring.ioc;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * 2022年11月3日
     */
    public class IocTest {
    
    	public static void main(String[] args) {
    		ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application-context.xml");
    		TestServiceImpl testService = (TestServiceImpl) context.getBean("testService");
    		System.out.println(testService);
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    关键时间点代码调用时机

    在对应的方法打上断点,运行IocTest#main,观察调用栈
    在这里插入图片描述

    构造方法

    AbstractApplicationContext#refresh#finishBeanFactoryInitialization

    InitializingBean初始化方法

    AbstractApplicationContext#refresh#finishBeanFactoryInitialization

    Bean后置处理器

    构造器

    AbstractApplicationContext#refresh#registerBeanPostProcessors

    before、after方

    AbstractApplicationContext#refresh#finishBeanFactoryInitialization

    BeanFactory后置处理器

    构造器

    AbstractApplicationContext#refresh#invokeBeanFactoryPostProcessors

    postProcessBeanFactory方法

    AbstractApplicationContext#refresh#invokeBeanFactoryPostProcessors

    refresh方法

    可以看到这些关键时间点都涉及到一个refresh方法,
    前面springboot源码中提到过,refresh方法标志着springioc容器真正初始化过程的开始,

    接下来我们重点要关注的就是它。

    感兴趣可以看下:
    springboot源码理解八、run方法执行过程(刷新应用上下文)
    Spring IoC容器初始化过程

  • 相关阅读:
    ISP技术概述
    Java_笔记_StringJoiner
    【JavaWeb】-- idea下使用TomCat新建javaweb项目
    技术周报收集
    真全!阿里最新Redis全栈小册涵盖了所有操作
    【面试题】详解Cookie、localStorage、sessionStorage区别
    从勾股定理看机器学习
    基于瞬时频率的语言信号清/浊音判决和高音检测(MATLAB R2021)
    Redis 竟然能用 List 实现消息队列
    流量3-------3
  • 原文地址:https://blog.csdn.net/qq_35549286/article/details/127679135