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

源码剖析注意事项及容器初始化主体流程

  • 源码剖析注意事项
    • 原则
    • 方法
  • 容器初始化主体流程
    • 容器继承体系
    • 代码
      • TestServiceImpl
      • application-context.xml
      • MyBeanPostProcessor
      • MyBeanFactoryPostProcessor
      • IocTest
    • 关键时间点代码调用时机
      • 构造方法
      • InitializingBean初始化方法
      • Bean后置处理器
        • 构造器
        • before、after方法
      • BeanFactory后置处理器
        • 构造器
        • postProcessBeanFactory方法
  • refresh方法

源码剖析注意事项

原则

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

方法

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

容器初始化主体流程

容器继承体系

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

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

代码

在myspring项目中有
spring框架源码十四、源码剖析注意事项及容器初始化主体流程_第1张图片

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");
	}

}

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>

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;
	}

}

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");
	}

}

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);
	}

}

关键时间点代码调用时机

在对应的方法打上断点,运行IocTest#main,观察调用栈
spring框架源码十四、源码剖析注意事项及容器初始化主体流程_第2张图片

构造方法

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容器初始化过程

你可能感兴趣的:(spring,spring,java,mybatis)