1、聚焦原则
抓主线
2、宏观原则
关注源码结构和业务流程,淡化具体某一行代码的编写细节
1、断点,debug观察调用栈
2、调用,find usages
3、经验,spring中doXyz,一般是某些具体处理
ioc容器是spring的核心模块,是抽象了bean管理、依赖关系维护的解决方案。
spring提供了很多容器,BeanFactory是顶层容器,它定义了容器遵循的原则,
ApplicationContext是BeanFactory的一个子接口,
具体的实现容器有,
ClassPathXmlApplicationContext:包含了xml解析的一系列内容,AnnotationConfigApplicationContext:包含了注解解析的一系列内容,
等。
我们以ClassPathXmlApplicationContext为例,深入源码说明spring ioc容器的初始化流程。
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");
}
}
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>
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;
}
}
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");
}
}
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,观察调用栈
AbstractApplicationContext#refresh#finishBeanFactoryInitialization
AbstractApplicationContext#refresh#finishBeanFactoryInitialization
AbstractApplicationContext#refresh#registerBeanPostProcessors
AbstractApplicationContext#refresh#finishBeanFactoryInitialization
AbstractApplicationContext#refresh#invokeBeanFactoryPostProcessors
AbstractApplicationContext#refresh#invokeBeanFactoryPostProcessors
可以看到这些关键时间点都涉及到一个refresh方法,
前面springboot源码中提到过,refresh方法标志着springioc容器真正初始化过程的开始,
接下来我们重点要关注的就是它。
感兴趣可以看下:
springboot源码理解八、run方法执行过程(刷新应用上下文)
或Spring IoC容器初始化过程