本来博主在看Mybatis-Spring,就先把Spring 研究下。
Spring 源码阅读,应该从哪里入手?
本文(启动篇)以 AnnotationConfigApplicationContext
API 使用进行分析。本文以 AnnotationConfigApplicationContext
作为切入点,具体例子在:
https://github.com/anLA7856/springLearn/tree/master/spring-bean
本文将以以下几个问题展开:
- Spring 启动有那些过程?
第一篇文章,首先还是以简单例子入门,其中夹带一些方法。
AnnotationConfigApplicationContext 使用
实际上在开发中,直接用不到 AnnotationConfigApplicationContext
,一般启动一个 SpringBoot
程序这样即可:
@SpringBootApplication
public class MvcApplication {
public static void main(String[] args) {
SpringApplication.run(MvcApplication.class, args);
}
}
SpringApplication.run(MvcApplication.class, args)
做了些什么处理呢? 看起来有点太大了,还是先从基本的 api 方式开启 Spring IOC 容器。
当Spring 容器实例化后,可以进行bean注册:
GenericBeanDefinition definition = new GenericBeanDefinition();
definition.setBeanClass(SqlSessionFactoryBean.class);
definition.getPropertyValues().add("dataSource", getDruidDataSource());
applicationContext.registerBeanDefinition("sqlSessionFactory", definition);
AnnotationConfigApplicationContext 初始化
在 AnnotationConfigApplicationContext
的构造方法中,声明了一个reader 和一个scanner:
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
- AnnotatedBeanDefinitionReader: 主要用于 注册bean(
registterBean
),当然还包括一些工具类,例如环境变量(Environment
),bean名字生成器(BeanNameGenerator
)
- ClassPathBeanDefinitionScanner:主要用于扫描 classPath下bean定义,而后将他们放入
BeanFactory
或者ApplicationContext
中。ApplicationContext
并不管理bean,而是通过BeanFactory
管理。
默认的扫描的类注解是 @Component
、@Repository
、@Service
、@Controller
。
声明完 ApplicationContext
后,就可以启动 它了。
refresh方法
refresh
方法是 AbstractApplicationContext
的核心方法,里面包括了扫描,处理各种后至处理器、注册监听,解析 @Autowired
注解等。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备工作
prepareRefresh();
// 获取一个beanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 准备BeanFacory
prepareBeanFactory(beanFactory);
try {
// 添加某些后置处理器
postProcessBeanFactory(beanFactory);
// 触发后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 注册BeanPostProcessor 后置处理器
registerBeanPostProcessors(beanFactory);
// 初始化国际化信息
initMessageSource();
// 初始化消息广播
initApplicationEventMulticaster();
// 刷新子类等
onRefresh();
// 注册监听
registerListeners();
// 初始化其他beanfactory
finishBeanFactoryInitialization(beanFactory);
// 广播事件
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();
}
}
}
refresh 方法,后面文章博主会一一分析。
start
当初始化完 Spring 容器后,就需要告知注册过得监听器,发布特定消息,生命周期进入已启动阶段,这些是在start方法完成的:
@Override
public void start() {
getLifecycleProcessor().start();
publishEvent(new ContextStartedEvent(this));
}
结语
Spring 源码阅读,应该从哪里入手?跟着楼主就对了!
博主用了Spring 也有四五年了,以前都是停留在用的阶段,现在鼓起干劲研究源码?如文章有误,还请指出呀~
觉得博主写的有用,不妨关注博主公众号: 六点A君。
哈哈哈,一起研究Spring: