庖丁解牛之spring源码系列一
spring最重要的是ioc和aop了,深入spring学习,源码当然必不可少,本文尝试分下spring ioc源码,希望能够对大家深入spring有一定的帮助。
一、AnnotationConfigApplicationContext
spring提供了很多容器,AnnotationConfigApplicationContext是spring提供的一个支持注解式注入的容器,本文从AnnotationConfigApplicationContext容器开始,进行对spring ioc源码探索之旅。
先来分析它的继承关系图,图在下面,已从左至右,从上到下的顺序开始分析,ResourceLoader是一个支持容器从文件系统和类路径加载资源的接口,默认实现是DefaultResourceLoader,ResourcePatternResolver扩展了ResourceLoader接口,能够支持“路径模式”的方式加载资源,也就是路径带*号的,比如说支持/WEB-INF/*-context.xml形式的路径。
MessageSource是支持国际化的接口,ApplicationEventPublisher是spring提供的事件模型,支持发布事件。
BeanFactory是spring的核心接口,是用来访问spring bean的容器,这个接口的实现类会拥有一个bean definitions集合,beanDefinitions是描述spring bean的数据结构。另外spring规定了beanfactory的实现类必须要支持的生命周期接口,也就是spring给我们提供的扩展点,包括BeanNameAware、BeanClassLoaderAware,BeanFactoryAware,EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware,ApplicationEventPublisherAware,BeanPostProcessors等等,关于生命周期接口以后在详细阐述,另外它的扩展接口ListableBeanFactory表示从容器中一次性获取多个spring bean对象。EnviromentCapable是一个暴露容器环境的接口,通过getEnvironment方法,返回当前容器的Environment对象,值得一提的是在ConfigurableApplicationContext中,getEnvironment返回的是ConfigurableEnvironment,也意味着用户可以修改Environment对象。
ApplicationContext是beanfactory的一个扩展容器,继承了ListableBeanFactory,ResourceLoader,ApplicationEventPublisher接口,因此ApplicationContext除了支持beanfactory的功能,还支持加载资源,发布事件,支持国际化等,当然ApplicationContext运行的过程中仅支持可读,不能够进行更改,不过注意的是实现类可以重新加载容器。 ConfigurableApplicationContext继承了ApplicationContext,能够更加灵活的配置容器,比如重新配置环境,增加beanfactory后置处理,追加事件监听器,另外大名鼎鼎的refresh方法就是此接口定义的。
AbstractApplicationContext是ConfigurableApplicationContext的抽象实现类,使用了模板方法设计模式,由子类具体实现,AbstractApplicationContext能够自动注册一些定义在容器内部的bean,包括BeanFactoryPostProcessors、BeanPostProcessors、ApplicationListener,这个等会在源码跟踪的时候在详细阐述。GenericApplicationContext继承了ConfigurableApplicationContext,它有个DefaultListableBeanFactory成员对象,DefaultListableBeanFactory是个很牛逼的beanfactory实现类,可以拿着DefaultListableBeanFactory对象对beanfactory进行很多操作,另外它实现了BeanDefinitionRegistry接口,表示能够将BeanDefinition注册到容器中,下面给出GenericApplicationContext容器的使用代码案例。
GenericApplicationContext ctx = new GenericApplicationContext();
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
xmlReader.loadBeanDefinitions(new ClassPathResource("applicationContext.xml"));
PropertiesBeanDefinitionReader propReader = new PropertiesBeanDefinitionReader(ctx);
propReader.loadBeanDefinitions(new ClassPathResource("otherBeans.properties"));
ctx.refresh();
AnnotationConfigApplicationContext继承了GenericApplicationContext,支持注解式注入,可以使用Configuration,
Component,Bean注解啥的。
二、知识准备
首先要明确一点,在普通的java程序中,是由一个一个对象构成,生命周期是new出来之后,然后由jvm进行销毁,而在spring中,是由bean构成,spring容器管理的是bean,其中最重要的就是一个叫BeanDefinition的数据结构,它是对bean的描述,在BeanDefinition中定义各种bean的属性,比如这个bean是否是单例,是否懒加载,它的类对象是啥等等,所以spring在容器启动过程中,会先将一个一个类转化成BeanDefinition,并存放到一个beanDefinitionMap的map集合,key为beanDefinition的名字,value为beanDefinition,然后根据这个map集合的BeanDefinition所描述的信息,生成实例对象。然后梳理下我们需要知道的AnnotationConfigApplicationContext的数据结构,AnnotationConfigApplicationContext下有个beanfactory的成员变量,它会在调用AnnotationConfigApplicationContext的构造方法中被创建,类型为defaultListableBeanFactory,beanfactory下有个beanDefinitionMap的成员变量,beanDefinitionMap是一个map集合,key为beanDefinition的名字,value为beanDefinition。
三、启动过程分析
看下最基本的启动 AnnotationConfigApplicationContext 容器的例子:
@Configuration
@ComponentScan("com.ls")
public class App
{
public static void main( String[] args )
{
AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(App.class);
context.getBean("student");
}
}
@Component
public class Student {
private String name;
}
接下来点进去,发现调用了三个方法,this()、register(componentClasses)、refresh()。
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
/**
1.生成了一个DefaultListableBeanFactory的beanfactory
2.生成一个reader和scanner对象,用于beandifinition的注册
3.将一些beanfactoryProcessor注册到beanfactory中,其中有个
ConfigurationClassPostProcessor的beanfactoryProcessor这个很关键,后面它用来解析
component注解,componentscan注解,import注解等等。
*/
this();
/**
将启动的类注册到容器中
*/
register(componentClasses);
/**
调用刷新方法,这个方法很关键,spring最核心的方法,接下来着重分析这个方法
*/
refresh();
}
点击refresh方法,进入方法体,发现里面代码其实也不多,但里面很复杂,我先大概讲解下每个方法的作用,大家可以先留个印象。我这里说的把类注册到容器的意思是指这个类的beandifinition put到beandifinitionMap中。
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 容器刷新工作进行的准备
//设置定时器,容器的状态设置为**
prepareRefresh();
// 获取那个beanFactory对象,其实就是上步那个this()方法中创建的
//DefaultListableBeanFactory对象,这个代码很简单,下面就不点进去看了。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 配置beanfactory,比如说classloader,post-processors
prepareBeanFactory(beanFactory);
try {
// 这个是扩展方法,由子类进行重写,对beanfactory进行操作。
postProcessBeanFactory(beanFactory);
// 调用那些已经注册在beanfactory中的beanfactoryPostProcessors,前面提到过
//this方法中,已经注册过一些beanfactoryPostProcessors,就会在这里调用,
//ConfigurationClassPostProcessor这个调用完成后是会把component注解,
//componentscan注解的规则的类注册到beanfactory,也就是说会将student这个
//类注册到beanfactory中,也就是beandifinitionMap中了。
invokeBeanFactoryPostProcessors(beanFactory);
//BeanPostProcessors注册到beanfactory中。
registerBeanPostProcessors(beanFactory);
// 这个是用于国际化的,暂时先忽略。
initMessageSource();
//初始化事件多播器,用于发布事件
initApplicationEventMulticaster();
// 由子类重写,在springboot中就重写这个方法,用于启动嵌入式web容器
onRefresh();
// 注册事件监听器。
registerListeners();
// 初始化所有单例的实例
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();
}
}
}
prepareRefresh方法是容器刷新前的准备工作,比如定时器,**标识以及初始化一些源文件的环境属性。
protected void prepareRefresh() {
// 开始计时
this.startupDate = System.currentTimeMillis();
//设置状态
this.closed.set(false);
this.active.set(true);
//打印debug日志
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// 初始化配置的环境属性,由子类重写
initPropertySources();
// 验证属性
getEnvironment().validateRequiredProperties();
}
invokeBeanFactoryPostProcessors方法主要是调用beanfactoryPostProcessors方法,也是一个重点方法,
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
}
继续点进PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());会发现这个方法超长,先不慌,其实逻辑很简单。
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
Set<String> processedBeans = new HashSet<>();
//可以看上面继承图,这个条件是满足的
if (beanFactory instanceof BeanDefinitionRegistry) {
/**
BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口,
BeanDefinitionRegistryPostProcessor主要是向beanfactory注册beandifinition
的。这里regularPostProcessors存储BeanFactoryPostProcessor的实现类,registryProcessors存储BeanDefinitionRegistryPostProcessor的实现类。
*/
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
//调用步骤为分别顺序调用实现了 PriorityOrdered, Ordered, 其他接口的
//BeanDefinitionRegistryPostProcessors
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
//第一步先调用实现了PriorityOrdered的BeanDefinitionRegistryPostProcessors
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 然后调用实现了Ordered的BeanDefinitionRegistryPostProcessors
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 最后调用剩余的BeanDefinitionRegistryPostProcessors
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
//然后调用 postProcessBeanFactory中的方法
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// 隔离开来实现了 PriorityOrdered, 或者Ordered,或者其他的beanFactoryPostProcessor
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
//第一步调用实现PriorityOrdered的beanFactoryPostProcessor
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 然后调用实现Ordered的beanFactoryPostProcessor
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// 最后调用其他的
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
beanFactory.clearMetadataCache();
}
上面有个重要的BeanDefinitionRegistryPostProcessor值得说下,就是前面一直强调的ConfigurationClassPostProcessor,看看它的postProcessBeanDefinitionRegistry方法,里面有个parser.parse(candidates)方法,这个方法解析了@configuration,@componentscan,@import等等注解,继续点进那个parser.parse(candidates)方法,看到有个parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName())的方法,再继续进入processConfigurationClass方法,在继续进入doProcessConfigurationClass方法,终于找到解析注解的地方了。
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass);
}
//处理 @PropertySource 注解
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
//处理 @ComponentScan 注解
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// 解析 @Import 注解
processImports(configClass, sourceClass, getImports(sourceClass), true);
// 解析 @ImportResource 注解
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// 解析 @Bean 注解
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
processInterfaces(configClass, sourceClass);
// 解析父类
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
// 整个解析过程完成
return null;
}
四、结语
这篇先暂时将spring源码介绍到这,下篇将详细介绍finishBeanFactoryInitialization实例化所有单例对象方法,从源码角度分析spring bean的生命周期和spring是如何解决循环依赖等等。
推荐阅读
-
PHP网页游戏学习之Xnova(ogame)源码解读(一)
-
Springboot源码分析之Spring循环依赖揭秘
-
Spring5源码解析4-refresh方法之invokeBeanFactoryPostProcessors
-
基于Spring注解的上下文初始化过程源码解析(一)
-
Spring源码解析之ConfigurableApplicationContext
-
spring源码分析系列5:ApplicationContext的初始化与Bean生命周期
-
Java并发系列之Semaphore源码分析
-
Java并发系列之CyclicBarrier源码分析
-
Java并发系列之ConcurrentHashMap源码分析
-
Java并发系列之CountDownLatch源码分析