Spring是每个java程序员都必须要掌握的技能,很多人都想通过阅读源码来提升自己的技术深度,这里分享一下我读源码的方法。
我觉得看源码应该先大概的读,知道主脉络,然后再去读细节,这样才不会乱,先放上我画的图(不怎么会画,大概看看就好,最大的正方形就是ioc容器)
然后我们来看一下照着图来走一下代码
在springboot启动类打断点
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
经过SpringApplication构造函数完成一些初始化操作后来到
SringApplication这个类的ConfigurableApplicationContext 方法,
这个方法我们主要看 this.refreshContext(context); 这一行,这是创建ioc容器的方法,其他的可以等熟悉了主要脉络再去细看
public ConfigurableApplicationContext run(String... args) {
//计时器实例,并设置计时器id,name和开始时间
StopWatch stopWatch = new StopWatch();
stopWatch.start();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
//系统属性设置 一般是在程序开始激活headless模式,告诉程序,现在你要工作在Headless mode下,就不要指望硬件帮忙了,你得自力更生,依靠系统的计算能力模拟出这些特性来
configureHeadlessProperty();
//初始化监听器 META-INF/spring.factories文件中获取SpringApplicationRunListener接口的实现类。
SpringApplicationRunListeners listeners = getRunListeners(args);
//启动已经准备好的监听器 getSpringFactoriesInstances
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
//装配环境参数 保存args参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 准备环境变量, 读取 bootstrapContext application.properties文件中的环境变量
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
// 系统配置忽略标志spring.beaninfo.ignore
configureIgnoreBeanInfo(environment);
//打印banner图案
Banner printedBanner = printBanner(environment);
//创建ConfigurableApplicationContext(应用配置上下文)
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
//将listeners、environment、applicationArguments、banner等重要组件与上下文对象关联
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
//这个方法很重要 ioc容器的创建
refreshContext(context);
//ioc容器创建后
afterRefresh(context, applicationArguments);
//计时结束
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
一路进去AbstractApplicationContext这个实现类的refresh()方法
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
//初始化工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
this.prepareRefresh();
//这个是创建bean工厂的方法主要是createBeanFactory():创建BeanFactory和loadBeanDefinitions() :加载BeanDefinination两个方法
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
//填充beanFactory属性
this.prepareBeanFactory(beanFactory);
try {
//这是一个扩展点
this.postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
//实例化并调用所有注册的BeanFactoryPostProcessors
this.invokeBeanFactoryPostProcessors(beanFactory);
// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
this.registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
//国际化相关
this.initMessageSource();
// 初始化当前 ApplicationContext 的事件广播器
this.initApplicationEventMulticaster();
// 从方法名就可以知道,典型的模板方法(钩子方法),
// 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
this.onRefresh();
// 注册事件监听器,监听器需要实现 ApplicationListener 接口
this.registerListeners();
// 重点,重点,重点
// 初始化所有的 singleton beans
//(lazy-init 的除外)
this.finishBeanFactoryInitialization(beanFactory);
// 最后,广播事件,ApplicationContext 初始化完成
this.finishRefresh();
} catch (BeansException var10) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
}
// 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
this.destroyBeans();
// Reset 'active' flag.
this.cancelRefresh(var10);
throw var10;
} finally {
this.resetCommonCaches();
contextRefresh.end();
}
}
}
对于上面大家不知道BeanFactoryPostProcessor和BeanPostProcessor是干嘛的。大家可以看看这篇文章
https://blog.youkuaiyun.com/caihaijiang/article/details/35552859
然后这里给大家说一下具体每个方法做了什么
- prepareRefresh
protected void prepareRefresh() {
// Switch to active.
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
// ①在上下文环境中初始化任何占位符属性源。
initPropertySources();
// ②验证所有标记为required的属性都是可解析的:
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
ApplicationContext刷新前的准备工作,比如设置启动时间(startupDate),激活标志(active & closed),以及执行属性源的初始化(见阐释)
阐释:
①initPropertySources()是模板抽象方法,用户可以根据需要进行重写。 Warn见WebApplicationContext解析
protected void initPropertySources() {
// For subclasses: do nothing by default.
}
我们可以覆盖该方法,进行自定义的属性处理以及设置。比如如果项目的启动必须依赖于当前机器的环境变量ENV,那么我们可以这样写:
protected void initPropertySources() {
// For subclasses: do nothing by default.
getEnvironment().setRequiredProperties("ENV")
}
②getEnvironment().validateRequiredProperties(),对所有被标记为required的属性进行验证
在前面我们知道,这里的envirmonent是一个StandardEnvironment,它是ConfigurablePropertyResolver的子类,故而它可以执行validateRequiredProperties()方法(因为该方法是由ConfigurablePropertyResolver接口声明的)。
我们还知道AbstractEnvironment中声明了一个类型为ConfigurablePropertyResolver的propertyResolver属性,并硬编码其值为PropertySourcesPropertyResolver对象。在这里的验证required属性的工作也是交给了这个PropertyResolver来处理!!
具体的验证逻辑读者可以自行阅读源码,其实:
- setRequiredProperties()是将字符串加入到一个由AbstractPropertyResolver维护的一个名为requiredProperties的Set集合中
- validateRequiredProperties()仅仅是循环requiredProperties并验证存在罢了。
private final ConfigurablePropertyResolver propertyResolver =
new PropertySourcesPropertyResolver(this.propertySources);
@Override
public void validateRequiredProperties() throws MissingRequiredPropertiesException {
this.propertyResolver.validateRequiredProperties();
}
- obtainFreshBeanFactory
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
protected final void refreshBeanFactory() throws BeansException {
//如果当前存在beanFactory,则先销毁掉
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
}
概述:refreshBeanFactory()方法对ApplicationContext上下文的底层beanFactory执行真正的刷新,先关闭之前的beanFactory(如果有的话),并为当前的ApplicationContext上下文生命周期的下一阶段初始化一个新的beanFactory。
refreshBeanFactory()方法中的核心方法调用分别是:
- createBeanFactory():创建BeanFactory
- loadBeanDefinitions() :加载BeanDefinination
createBeanFactory
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
下面是DefaultListableBeanFactory的创建历程
该过程仅仅是BeanFactory的实例化,并设置一些比较公共的配置,不予讲解,感兴趣的可以自己Debug看看
loadBeanDefinitions
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 为给定的BeanFactory创建一个XmlBeanDefinitionReader
// XmlBeanDefinitionReader用于读取XML并解析为BeanDefinition,并进行注册
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 为BeanDefinition的读取器,配置资源加载器,环境变量,以及EntityResolver(用于判断)
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
Ⅰ.首先,使用给定的BeanFactory类型的入参,创建一个XmlBeanDefinitionReader
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
//提供了对Document的解析能力,并将解析后的BeanDefinition注册到BeanDefintionRegistry对象上
private Class<? extends BeanDefinitionDocumentReader> documentReaderClass =
DefaultBeanDefinitionDocumentReader.class;
@Nullable
//处理自定义标签时候需要使用,它可以访问我们注册的自定义标签解析器,完成对自定义标签的解析
//默认的实现是DefaultNamespaceHandlerResolver
private NamespaceHandlerResolver namespaceHandlerResolver;
//将Resource转为Document的加载器,纯技术SAX技术,无需关心
private DocumentLoader documentLoader = new DefaultDocumentLoader();
@Nullable
private EntityResolver entityResolver;
private final ThreadLocal<Set<EncodedResource>> resourcesCurrentlyBeingLoaded =
new NamedThreadLocal<>("XML bean definition resources currently being loaded");
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
//直接调用方父类构造器
super(registry);
}
}
public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader, EnvironmentCapable {
//用于注册解析的BeanDefinition(说白了,就是将解析出的BeanDefinition,放到registry里保存,以用于bean实例化)
private final BeanDefinitionRegistry registry;
@Nullable
//用于加载配置文件的处理器,它可以将配置及文件解析为Resourced对象,以用于后面将Resource通过SAX转为Document对象
private ResourceLoader resourceLoader;
@Nullable
//ApplicationContext的类加载器
private ClassLoader beanClassLoader;
//环境变量
private Environment environment;
//XmlBeanDefinitionReader的父类AbstractBeanDefinitionReader
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
// 根据传入的registry,决定ResourceLoader(它是用于加载配置文件的加载器)
if (this.registry instanceof ResourceLoader) {
this.resourceLoader = (ResourceLoader) this.registry;
}
else {
this.resourceLoader = new PathMatchingResourcePatternResolver();
}
// 如果可能的话,继承Environment
if (this.registry instanceof EnvironmentCapable) {
this.environment = ((EnvironmentCapable) this.registry).getEnvironment();
}
else {
this.environment = new StandardEnvironment();
}
}
}
注:从XmlBeanDefinitionReader的构造器参数签名中,我们发现其实XmlBeanDefinitionReader需要的是一个BeanDefinitionRegistry对象,但是因为我们刚才生成的BeanFactory实现了该接口,故而可以作为入参。
阐释:真实的构造逻辑在AbstractBeanDefinitionReader中实现的,它将我们传入的registry,赋值给自己的registry属性上
验证传入的这个registry(本例中指的是beanFactory)是否是一个ResourceLoader接口的实现:
- 如果是:直接将该其赋值给resourceLoader属性
- 如果否:创建一个PathMatchingResourcePatternResolver对象,然后赋值给resourceLoader属性。本例中的beanFactory是DefaultListableBeanFactory,它并没有实现ResourceLoader。PathMatchingResourcePatternResolver是对DefaultResourceLoader(它是ResourceLoader的默认实现)的二次封装,它额外添加了对classpath*:
或者 war: 或者 */ 等路径语法的支持!!!
然后验证传入的这个registry(即该beanFactory)是否是一个EnvironmentCapable接口的实现:
- 如果是:则将其赋值给environment属性
- 如果否:则创建一个StandardEnvironment并赋值给environment属性
PS:ResourceLoader是用于加载资源文件为Resource对象的,故而对XmlBeanDefinitionReader很重要
Ⅱ. 实例化完XmlBeanDefinitionReader,对其进行配置
// 使用该上下文的资源加载环境,来配置XmlBeanDefinitionReader
beanDefinitionReader.setEnvironment(this.getEnvironment());
//请注意,这里对ResourceLoader进行了重新赋值,即将this,即ClassPathXmlApplicationContext赋值给它
//ClassPathXmlApplicationContext的父类继承自DefaultResourceLoader(它是ResourceLoader的默认实现),因此它是一个有效的ResourceLoader
//多嘴一句,ClassPathXmlApplicationContext并不是直接复用DefaultResourceLoader,而是在其内部初始化了一个PathMatchingResourcePatternResolver类型的resourcePatternResolver变量,在真正加载文件时,全权交给他,如果是模式匹配的,那么它就处理了,如果并模式匹配,那么再复用这个DefaultResourceLoader。
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// 允许子类提供Reader的自定义初始化(保留给子类使用的)
initBeanDefinitionReader(beanDefinitionReader);
Ⅲ .loadBeanDefinitions(beanDefinitionReader)
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
概述:对ApplicationConext的configLoacations进行for循环,分别交给XmlBeanDefinitionReader单解析
阐述:需要注意的是,我们在最前面讲了,ApplicationContext将配置文件的路径,存储在configLocations属性中。因此在解析BeanDefinition之前,需要先将该配置文件提取出来,然后交给XmlBeanDefinitionReader去操作(因为XmlBeanDefinitionReader与ApplicationmContext并没有直接关系,因此无法在运行时获取到这些配置文件的信息)。
public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader, EnvironmentCapable {
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
int count = 0;
for (String location : locations) {
count += loadBeanDefinitions(location);
}
return count;
}
@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
//还记得为XmlBeanDefinitionReader单独配置的ResourceLoader吗??
//这里需要使用它,将configLocation里的配置文件路径,加载解析为Resource资源
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
}
if (resourceLoader instanceof ResourcePatternResolver) {
// 资源的模式匹配功能可用.本例子中的resourceLoader是ClassPathXmlApplicationContext,它所实现的ResolveLoader是具有资源模式匹配的能力的
try {
//将资源加载的工作委托给resourceLoader
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
int count = loadBeanDefinitions(resources);
if (actualResources != null) {
Collections.addAll(actualResources, resources);
}
if (logger.isTraceEnabled()) {
logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
}
return count;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// 资源的模式匹配功能不可用,只可以通过绝对URL加载单一资源
Resource resource = resourceLoader.getResource(location);
int count = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isTraceEnabled()) {
logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
}
return count;
}
}
}
注:XmlBeanDefinitionReader是AbstractBeanDefinitionReader的子类
配置文件资源的加载比较简单,看上面的注释即可,接下来着重讲解loadBeanDefinitions方法调用
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
@Override
//对Resource进行编码
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Loading XML bean definitions from " + encodedResource);
}
//resourcesCurrentlyBeingLoaded中存储了当前正在被解析的Resource的Set集合,防止同一Resource被多次解析
//文件被解析完后,会从Set集合中删除掉
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
//获取编码后的Resource的文件流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
//使用InputSourece对InputStream进行封装(因为SAX值只识别IputSouce)
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
//BeanDefinition加载
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//使用XmlBeanDefinitionReader的类型为DefaultDocumentLoader的documentLoader变量,来将Resource解析为Document
//纯SAX技术,无需care
Document doc = doLoadDocument(inputSource, resource);
//
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
}
//提供了对Document的解析能力,并将解析后的BeanDefinition注册到BeanDefintionRegistry对象上
private Class<? extends BeanDefinitionDocumentReader> documentReaderClass =
DefaultBeanDefinitionDocumentReader.class;
@Nullable
//处理自定义标签时候需要使用,它可以访问我们注册的自定义标签解析器,完成对自定义标签的解析
//默认的实现是DefaultNamespaceHandlerResolver
private NamespaceHandlerResolver namespaceHandlerResolver;
//将Resource转为Document的加载器,纯技术SAX技术,无需关心
private DocumentLoader documentLoader = new DefaultDocumentLoader();
@Nullable
private EntityResolver entityResolver;
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
return BeanUtils.instantiateClass(this.documentReaderClass);
}
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//创建一个可以解析Doument的解析器
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
//使用documentReader完成BeanDefinition的提取,构造和注册(注册到BeanDefinitionRegistry上)
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
}
这一块代码体量较大,但是工作内容很简单,读者可以参考我的注释,脑海里勾勒粗Spring的处理过程,为了简答起见,我以直白的表述,阐释这个过程.:
在前面,我们通过XmlBeanDefinitionReader中的ResourceLoader,将配置文件解析为Resource,我们先对该Resource做编码(比如UTF-8等格式的编码),然后提取该资源的InputStream,最终将其转换为可以为SAX解析器所识别的InputSource对象。
XmlBeanDefinitionReader中定义了一个类型为DefaultDocumentLoader的documentLoader变量,通过该加载器,可以将InputSource解析为Document对象。
XmlBeanDefinitionReader还定义了一个专门负责解析Document的读取器,即DefaultBeanDefinitionDocumentReader,我们将前面DocumentLoader解析生成的Document对象交付给它,并附带一个XmlReaderContext对象。
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
//创建一个XmlReaderContext,即Xml配置文件读取的上下文,用于承载一些读取、解析Xml配置文件时
//所需要使用的一些工具处理器,比如配置文件的Resource、NamespaceHandlerResolver等
public XmlReaderContext createReaderContext(Resource resource) {
return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
this.sourceExtractor, this, getNamespaceHandlerResolver());
}
public NamespaceHandlerResolver getNamespaceHandlerResolver() {
if (this.namespaceHandlerResolver == null) {
//初始化XmlBeanDefinitionReader时并未设置namespaceHandlerResolver属性,因此
//会创建一个NamespaceHandlerResolver的默认实现类:DefaultNamespaceHandlerResolver的实例
this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
}
return this.namespaceHandlerResolver;
}
}
注:XmlReaderContext,是Per-Resource的,即一个Resource对应一个Document,而每个Docunent则对用唯一的专用ReaderContext对象。该对象提供了对NamespaceHandlerResolver的访问,使用的是DefaultNamespaceHandlerResolver这个默认实现,当然,这是XmlBeanDefinitionReader在构造它时,为其装载的)。
具体的BeanDefinition解析逻辑,完全的委托给了DefaultBeanDefinitionDocumentReader,注目观看:
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
doRegisterBeanDefinitions(doc.getDocumentElement());
}
protected void doRegisterBeanDefinitions(Element root) {
//入参是Document的根元素
//DefaultBeanDefinitionDocumentReader将Element元素的解析工作,委托给了BeanDefinitionParserDelegate来负责
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
//profile验证
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
//模板方法,实现是空的,由用户自定义,在真正处理XML解析之前做什么...
preProcessXml(root);
//BeanDefinition核心解析方法
parseBeanDefinitions(root, this.delegate);
//模板方法,实现是空的,由用户自定义,在真正处理XML解析之前做什么...
postProcessXml(root);
this.delegate = parent;
}
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//注意:这里的元素是根节点Element
//如果delegate判断该Element是属于默认命名空间的,那么取出子节点,循环解析
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
//如果子节点是默认命名空间的元素
if (delegate.isDefaultNamespace(ele)) {
//解析默认元素的方法
parseDefaultElement(ele, delegate);
}
else {
//如果是自定义命名空间的元素,则调用解析自定义元素的方法
delegate.parseCustomElement(ele);
}
}
}
}
else {
//如果根元素就是自定义明明空间的元素,则调用解析自定义元素的方法
delegate.parseCustomElement(root);
}
}
protected BeanDefinitionParserDelegate createDelegate(
XmlReaderContext readerContext, Element root, @Nullable BeanDefinitionParserDelegate parentDelegate) {
BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
delegate.initDefaults(root, parentDelegate);
return delegate;
}
}
概述:DefaultBeanDefinitionDocumentReader将Element解析的重任,委托给了BeanDefinitionParserDelegate对象,而它则负责Document中Element的拆解,元素识别以及调用delegate的适当方法做元素的解析,最终生成BeanDefinition对象。
阐释:DefaultBeanDefinitionDocumentReader在这里的作用,更像是一个装备工人,它购买一个BeanDefinitionParserDelegate机器(该机器可以将Element解析为一个BeanDefinition),然后使用它判断原料(即Document的根元素)是否是Spring原厂(即Spring默认命名空间)的:
- 如果该Element是原厂的,那说明是使用Spring的标准配置的配置文件,那么先拆解该根元素,取出所有的子元素,for迭代,然后在交给BeanDefinitionParserDelegate来判断该子元素是否是Spring原厂的(比如Spring所支持的<
bean />
元素),如果是原厂支持的,那么调用parseDefaultElement(element,delegate)做二次解析,毕竟各种元素的处理方法是不一样的,比如<
bean />,以及< import
/>等。如果子元素并非Spring原厂支持的,亦即自定义的,那么完全委托给BeanDefinitionParserDelegate的parseCustomElement()方法去处理 - 如果子元素并非原厂的,那么完全委托给BeanDefinitionParserDelegate的parseCustomElement()方法去处理
先看如何加工Spring原厂的Element:
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
//如果该子元素是<import>,那么先对import内文件地址解析,即替换掉${...},然后进行beanDefinition的解析工作,这个过程与我们传给ClassPathXmlApplicationContext的配置文件的解析过程一毛一样,也建议读者自行阅读源码
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
//如果该子元素是<alias>,那么直接在readerContext中的registry上注册该别名即可
//实现比较简单,建议读者自行阅读源码
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
//如果盖子元素是一个<bean>,那么完全委托给deleaget去解析
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// 如果该子元素是一个<beans>,那么递归调用doRegisterBeanDefinitions
doRegisterBeanDefinitions(ele);
}
}
}
概述:方法很简单,根据Element的节点名称,调用不同的方法去解析及注册
最重要的就是< bean />元素的处理,下面着重描述:
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//委托给delegate全权处理element的解析,返回一个BeanDefinitionHolder
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
//若可以,对BeanDefinitionHolder进行包装,也是很重要的
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 将最终包装过的BeanDefinitionHolder,注册到BeanDefinitionRegistry上
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// 发送注册消息
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
最重要的三个步骤:
- delegate.parseBeanDefinitionElement(ele);
- elegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
- BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder,
getReaderContext().getRegistry());
public class BeanDefinitionParserDelegate {
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
//提取element的id、name 属性,需要提到的一点是,name属性也被成为别名,name是支持多值得,格式类似于name="piemon,anokata"
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<>();
//将name属性按照分隔符分割开来,并添加到alias列表中
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
//将id赋值给beanName,校验:beanNaame不能为空与alias为空不可同时存在
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isTraceEnabled()) {
logger.trace("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
//beanName唯一性校验,前面说过,BeanDefinitionParserDelegate是一个有状态的对象,
//它使用一个Set<String>类型的usedNames,其中保存beanName和别名(别名也参与一致性校验)
//实现个很简单,Set中查找beanName,查到就不满足唯一性,异常!否则通过
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
//解析Element元素,生成一个ASbstractBeanDefinition对象(其实真实类型是GenericBeanDefinition,它是AbstractBeanDefinition的子类)
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
// Register an alias for the plain bean class name, if still possible,
// if the generator returned the class name plus a suffix.
// This is expected for Spring 1.2/2.0 backwards compatibility.
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (logger.isTraceEnabled()) {
logger.trace("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
//BeanDefinitionHolder包装BeanDefinition
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
//该方法存在无法解析Element的情况,因此返回null
return null;
}
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, @Nullable BeanDefinition containingBean) {
//parseState中保存当前正在被解析的beanName,它是一个栈结构,push/pop
this.parseState.push(new BeanEntry(beanName));
String className = null;
//判断<bean>中是否有class属性,如 <bean class="">
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
String parent = null;
//判断<bean>中是否有parent属性 <bean parent="">
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
try {
//根据className和parent属性的值,构建AbstractBeanDefinition
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
//解析<bean>中的attribute
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
//给BeanDefinition设置一个用于展示的好看的名字,没啥鸟用
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
//解析<bean>中的<meta>子标签,也被成为元属性
parseMetaElements(ele, bd);
//这两两个解析比较重要,分别下列两种子元素:
// <lookup-method name="createCommand" bean="myCommand"/>
// <replaced-method name="computeValue" replacer="replacementComputeValue" />
//这两个特别有用,用于方法注入,并非setter注入哟~~
//典型场景:Singleton Bean种使用短周期的Bean(比如Proto/Request/Session等Scope的Bean)
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//解析构造器参数,即<bean>中的<construct-arg>子元素
parseConstructorArgElements(ele, bd);
//解析<bean>中的<property name="" value="">
parsePropertyElements(ele, bd);
//<bean class="example.SimpleMovieCatalog">
< // <qualifier value="main"/>
//</bean> 多用于同类型多Bean的情况
parseQualifierElements(ele, bd);
//为BeanDefinition设置Resource,就是此Element所存在于的配置文件的Resource表现形式
bd.setResource(this.readerContext.getResource());
//功能主要是由SourceExtractor负责的,但是我也不知道干嘛的~~希望读者有懂得,下面留言指点下
bd.setSource(extractSource(ele));
return bd;
}
catch (ClassNotFoundException ex) {
error("Bean class [" + className + "] not found", ele, ex);
}
catch (NoClassDefFoundError err) {
error("Class that bean class [" + className + "] depends on not found", ele, err);
}
catch (Throwable ex) {
error("Unexpected failure during bean definition parsing", ele, ex);
}
finally {
//弹出压入得beanName,表示已经解析完成
this.parseState.pop();
}
return null;
}
//new一个BeanDefinition
protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName)
throws ClassNotFoundException {
//将创建BeanDefinition的任务,交给了BeanDefinitionReaderUtils,并设置其parent属性以及beanClassName属性,这些属性都是参数传来的!
return BeanDefinitionReaderUtils.createBeanDefinition(
parentName, className, this.readerContext.getBeanClassLoader());
}
}
概述:BeanDefinitionParserDelegate是一个有状态的委托类,用于解析XML格式的配置文件。parseBeanDefinitionElement(…)方法的作用,是将一个Element,解析成一个BeanDefinition,然后用BeanDefinitionHolder包装一下。
阐述:看注释,更清楚
继续回到Spring原厂元素的解析上,将Element解析为BeanDefinition后,可能还需要包装它,下面讲decorateBeanDefinitionIfRequired:
PS:先看完下面的自定义元素解析(parseCustomerElement),再回头看这里的包装,否则本末倒置了!!!
public class BeanDefinitionParserDelegate {
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder originalDef) {
//交给重载的方法处理
return decorateBeanDefinitionIfRequired(ele, originalDef, null);
}
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
Element ele, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
BeanDefinitionHolder finalDefinition = originalDef;
// 首先根据自定义的attribute,进行包装
NamedNodeMap attributes = ele.getAttributes();
for (int i = 0; i < attributes.getLength(); i++) {
Node node = attributes.item(i);
finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
}
// 然后根据内嵌的自定义子元素,进行包装
// 需要交代一下,我们前面讲过,自定义的元素会交给ddelegate的parseCustomerElemenmt方法解析
NodeList children = ele.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node node = children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
}
}
return finalDefinition;
}
public BeanDefinitionHolder decorateIfRequired(
Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
//首先获取元素的命名空间
String namespaceUri = getNamespaceURI(node);
//判断是否是默认的命名空间,Spring的默认命名空进是beans,其他的都不是
if (namespaceUri != null && !isDefaultNamespace(namespaceUri)) {
//如果是自定义的元素,那么很可能会需要包装,我们首先解析出该命名空间的NamespaceHandler
//该NamespaceHandler的具体类型的父类型是一个NamespaceHandlerSupport,它是NamespaceHandler子类
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler != null) {
//每个命名空间都有一个自己的专属NamespaceHandler,当然这是规范,可以不遵守的
//每个NamespaceHandler里都维护着BeanDefinitionParser的Map:parsers和BeanDefinitionDecorator的map:decorators、map:attributeDecorators(不知道怎么解释,直白一点,前者包装<aop:scope-proxy>,即元素级的包装标签,后者包装的是Attribute级的属性),
//顾名思义,BeanDefinitionParser是用来解析自定义的元素为BeanDefinition的,
//而BeanDefinitionDecorator则用来包装
BeanDefinitionHolder decorated =
handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
if (decorated != null) {
return decorated;
}
}
else if (namespaceUri.startsWith("http://www.springframework.org/")) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
}
else {
// A custom namespace, not to be handled by Spring - maybe "xml:...".
if (logger.isDebugEnabled()) {
logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
}
}
}
return originalDef;
}
}
概述:根据Element的命名空间,找到注册的NamespaceHandlerSupport(他是NamespaceHandler接口的子类),然后找出其上注册的BeanDefinitionDecorator,用于对BeanDefinition进行包装。
BeanDefinition的注册:
public abstract class BeanDefinitionReaderUtils {
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
//首先在beanName下注册BeanDefinition
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 然后注册别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
}
概述:该工具方法先在beanName之下注册BeanDefinition,然后在想registry注册其别名吗,使得对别名的引用亦可以指向所属的Bean
阐释:BeanDefinitionRegistry是一个接口,具体的实现是在DefaultListableBeanFactory中实现。
DefaultListableBeanFactory中声明了一堆的Map,因为他实现了BenaDefinitionRegistry接口,所以他需要具有BeanDefinition的注册能力,而下面这些Map就是做这个注册的:
- beanDefinitionMap:Map<String, BeanDefinition>类型,存储BeanDefinition
- beanDefinitionNames:List<String,>类型,存储beanName
- frozenBeanDefinitionNames:String[]类型,冻结的beanName数组
- aliasMap:Map<String, String>类型,存储别名与beanName的映射
其实可以将BeanDefinitionRegistry,看做是一个内存数据库,所有的BeanDefinition信息都会记录在其中,用于Bean实例化。
至此,解析并注册了BeanDefinition~~
parseCustomerElement
Spring默认的命名空间仅包括beans.xsd所支持的配置项,而像aop、tx、context等命名空间,是属于自定义的!!!
在我们的配置项中,添加了对于< context annotation-config >,在< bean />中添加了< aop:scoped-proxy/>,这都是自定义的,为此我们着重解释一下
public class BeanDefinitionParserDelegate {
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
//有了Element所归属的命名空间(更直白一点,就是我们知道<context annotation-config>是由哪个命名空间定义的)
//我们就是提取出readerContext(就是XMLReaderContext,我们在上面讲过),然后用readerContext中的mamespaceHandlerResolver
//来对这个命名空间URI进行解析,找出该命名空间的处理器,即NamespaceHandler。
//此处得到NamespaceHandlerResolver是DefaultNamespaceHandlerResolver类型的,它内部维护这一个handlerMapping,
//Map<String, Object> handlerMappings;,键是命名空间URI,而值则是NamespaceHander或者是class全类名字符串(可以反射生成处理器对象)
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
//将Element交给该NamespaceHandler解析处理
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
public String getNamespaceURI(Node node) {
//Element是Node的子类,Node中声明了getNamespaceURI()方法,获取当前节点的命名空间URI
//对于<context:annotation-config>,他的命名空间URI就是http://www.springframework.org/schema/context,细心的读者会发现,这是我们在XML上引入的
return node.getNamespaceURI();
}
}
获取命名空间URI,然后使用NamespaceHandlerResolver对象,根据命名空间URI,检出对应的命名空间处理器(NamespaceHandelr),最后将Element委托给该handler解析。
注:NamespaceHandler还要负责注册解析的BeanDefinition到BeanDefinitionRegistry上
自定义命名空间比较重要,我先解释一下命名空间、命名空间处理器(NamespaceHandelr)、命名空间URI,不要略过,很简单的:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
1.命名空间:xmlns,就是xml命名空间,全称xml-namespace,对于xmlns:context,他对应的命名空间就是“http://www.springframework.org/schema/context”,但是这个名字太长了,我们就给他一个短小精悍的别名,即context,官方的解释是,给命名空间提供一个独一无二的名字。
2.命名空间URI:其实亦可以称其为命名空间,我么可以看一下spring-context.xsd定义(Ctrl就能点进去):
<xsd:schema xmlns="http://www.springframework.org/schema/context"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
##这就是我们context的命名空间
targetNamespace="http://www.springframework.org/schema/context"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
</xsd:schema>
3.NamespaceHandler:xsd中定义了规范,但是规范没法将这一个个的Element解析成BeanDefinition,这就需要NamespaceHandler登场了,NamespaceHandlerResolver根据命名空间URI,找出其对应的NamespaceHandler,然后让它去帮我们将Element解析成BeanDefinition
下面我就以spring-context来举个栗子!!!
众所周知,< context annotation-config>使得注解变得可能,那么它是如何实现的呢??我们一步步的看:
- 首先是spring-context.xsd,他定义了context命名空间的配置规范,使得我们可以在配置文件中使用< context annotation-config> < context conponent-scan> < context load-time-weaver>等等。spring-context.xsd只是一个配置规范,用于限制用户,大家完全可以把它类比成API接口,公共出服务协议。
- 我们最终的目标,是需要解析这些XML配置中的Element,而解析的任务,则是由BeanDefinitionParser接口定义的,Spring的Coder自定义一个AnnotationConfigBeanDefinitionParser类,实现BeanDefinitionParser接口,并在其中添加了对Element的解析逻辑
public class AnnotationConfigBeanDefinitionParser implements BeanDefinitionParser {
@Override
@Nullable
/**
* parse方法解析Element,并将解析后的BeanDefinition,通过parserContext.getRegistry()返回的
* BeanDefinitionRegistry进行注册。
* 如果解析后的BanDefinition需要以内嵌的形式被使用,比如被ref属性引用,那么返回必须不能为null
* 如果解析后的BeanDefinition并不需要以内嵌的形式被使用,那么可以返回null
*
* 不得不提的一点是,parserContext是解析上下文,可以与XML配置文件读取的XmlReaderContext类比,parserContext引用了readerContext,而readerContext引用了beanfactory(beanFacory可以注册BeanDefinition,因为他实现了BeanDefinitionRegistry)
* 和environment(他提供了环境变量和${..}解析)。
*/
public BeanDefinition parse(Element element, ParserContext parserContext) {
Object source = parserContext.extractSource(element);
// 获取与该注解相关的BeanPostProcessor的beanDefinition
Set<BeanDefinitionHolder> processorDefinitions =
AnnotationConfigUtils.registerAnnotationConfigProcessors(parserContext.getRegistry(), source);
// 为<context:annotation-config> 创建一个CompositeComponentDefinition对象来表示
CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
parserContext.pushContainingComponent(compDefinition);
// 将上面得到的BeanPostProcessor集合,定义为BeanComponentDefinition,并作为该标签的CompositeComponentDefinition的内嵌属性组件,等于声明了一个组件层级关系
for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
parserContext.registerComponent(new BeanComponentDefinition(processorDefinition));
}
parserContext.popAndRegisterContainingComponent();
//因为该注解是属于配置型的,并没有Bean会依赖它,所以返回null
return null;
}
}
public abstract class AnnotationConfigUtils {
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
/**
* 向BeanDefinitionRegistry注册了一堆BeanPostProcessor和BeanFactoryPostProcessor,
* 当然并不是通过调用registerBeanPostProcessor来注册,而是注册为BeanDefinition,这样就成为了配置型的BeanPostProcessor
* 需要提醒的一点是,Spring将beanPostProcessor/beanFactoryPostFactory分成了两类,
* 一类是硬编码注册的,即通过ApplicationContext的addBeanPostProcessor/addBeanFactoryPostFactory,
* 第二类则是通过配置配置的,即将BeanPostProcess/BeanFactoryPostProcess注册为BeanDefinition
* 硬编码的优先级,大于任何配置方式的!!!
*/
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
//注册一个beanName = internalConfigurationAnnotationProcessor的BeanDefinition
//他的原始类型是ConfigurationClassPostProcessor类
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}
}
- NamespaceHandelr:AnnotationConfigBeanDefinitionParser更像是建筑工人,而NamespaceHandler则是包工头。
//一步了然
//当遇见context命名空间中的annotation-config时候,使用AnnotationConfigBeanDefinitionParser来解析
//当遇到context命名空间中的component-scan时候,使用ComponentScanBeanDefinitionParser来解析
public class ContextNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
}
}
- 注册NamespaceHandler,META-INF文件夹下,编写spring.handlers和spring.schemas文件
spring.handelrs
http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler
spring.schemas
http\://www.springframework.org/schema/context/spring-context.xsd=org/springframework/context/config/spring-context.xsd
http\://www.springframework.org/schema/jee/spring-jee.xsd=org/springframework/ejb/config/spring-jee.xsd
http\://www.springframework.org/schema/lang/spring-lang.xsd=org/springframework/scripting/config/spring-lang.xsd
http\://www.springframework.org/schema/task/spring-task.xsd=org/springframework/scheduling/config/spring-task.xsd
http\://www.springframework.org/schema/cache/spring-cache.xsd=org/springframework/cache/config/spring-cache.xsd
//
https\://www.springframework.org/schema/context/spring-context.xsd=org/springframework/context/config/spring-context.xsd
https\://www.springframework.org/schema/jee/spring-jee.xsd=org/springframework/ejb/config/spring-jee.xsd
https\://www.springframework.org/schema/lang/spring-lang.xsd=org/springframework/scripting/config/spring-lang.xsd
https\://www.springframework.org/schema/task/spring-task.xsd=org/springframework/scheduling/config/spring-task.xsd
https\://www.springframework.org/schema/cache/spring-cache.xsd=org/springframework/cache/config/spring-cache.xsd
Spring遇到自定义的命名空间,比如context,他会首先解析出他的NamespaceURI,也就是http://www.springframework.org/schema/context,然后让NamespaceHandlerResolver去查找该命名空间的NamespaceHandler,他去查找spring.handlers文件,就可以找到ContextNamespaceHandler,继而可以找到annotation-config的BeanDefinitionParser:AnnotationConfigBeanDefinitionParser
- 使用,有了这些基础工作,我们就可以在XML中使用context上下文:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:contexts="http://www.springframework.org/schema/context" ##为该命名空间起一个别名contexts(注意,我们没有用context,这个名字可以随意改变)
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context ##contexts命名空间的schema地址
http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
自定义的Element也解析完毕,听懂了吗??
prepareBeanFactory
填充BeanFactory属性
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 告知BeanFactory使用与ApplicationContext一样的类加载器
beanFactory.setBeanClassLoader(getClassLoader());
//配置SPEL表达式的支持,即#{beanName.field}用法
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//配置属性编辑器,我们为什么可以在配置Bean的时候,用字符串表达数值等的意思??因为PropertyEditor帮我们转换了
//<property name="age" value="99"> 这里的99是个int,但是我们依然可以用字符串配置它
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
/**
* 配置BeanPostProcessor,BeanPostProcessor会在实例化Bean的init-method方法之前前后分别
* 调用其postProcessBeforeInitialization和postProcessAfterInitialization方法
* 我们可以深入看下ApplicationContextAwareProcessor源码,截取最重要的片段:
* if (bean instanceof Aware) {
* if (bean instanceof EnvironmentAware) {
* ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
* }
* ..类比..
* }
* 其实ApplicationContextAwareProcessor会帮我把几个特定类型做后置处理,填补上他们需要Aware的东西,
* 比如上面的EnvironmentAware所想感知到的Environent
* 我需要提醒一下,这是硬编码的BeanPostProcess,applicationContext维护了一个 beanPostProcessors:List<BeanPostProcessor>,他保存这些硬编码的BeanPostProcessor
*/
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//设置Bean实例化时所需要忽略的自动装配的类型,即在依赖注入时,忽略他们
//结合上面的这个ApplicationContextAwareProcessor,应该知道为什么了吧??
beanFactory.ignoreDependencyInterface(EnvironmentAware.class); ##Look Here
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
//当注册了依赖解析后,当你在Bean中,注入了BeanFactory类型的值,或者ApplicationEventPublisher类型的值
//那么,便会直接将beanFactory或者this给他注入进去
//class servier{
// @Autowired
// private ApplicationEventPublisher publisher;
//}
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
//如果需要的话,添加AOP
//<contexts:load-time-weaver />
//containsBean获取查找是否有beanName为LOAD_TIME_WEAVER_BEAN_NAME的singleton或者beanDefinition
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// 为类型匹配设置一个临时的类加载器
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// 注册三个单例的Environment Bean,并设置beanName为environment/systemProperties/systemEnvironment
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
postProcessBeanFactory
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}
抽象模板方法,交给子类去覆写,到此时,ApplicationContext中的beanFactory已经完全的初始化完,这时候所有的BeanDefinition已经注册完,但是还没有实例化任何的Bean。此时允许自定义的子类中(就是你自己实现的ApplicationContext类中)去注册一些特定的BeanPostProcessors。
invokeBeanFactoryPostProcessors
/**
* 实例化并调用所有注册的BeanFactoryPostProcessors,
* 如果BeanFactoryPostProcessor又显式的优先级,那么必须care
* 一定要在singleton的bean实例化前执行它
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//将实例化和调用的逻辑,委托给PostProcessorRegistrationDelegate
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// 检测LoadTimeWeaver并为编织做准备,算是有点冗余,前面prepareBeanFactory步骤中其实都做了,但是不影响
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
//获取硬编码的BeanFactoryPostProcessor,y一定要与配置的BeanFactoryPostProcessor区分开来
private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>();
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
return this.beanFactoryPostProcessors;
}
下面先看PostProcessorRegistrationDelegate到底是如何做的:
final class PostProcessorRegistrationDelegate {
//代码题很长,但是逻辑很简单,查找,filter,排序,invoke
//该方法入参有两个:
//beanFactory:不多讲了
//beanFactoryPostProcessors:注意哟,它的值是在AbstractApplicationContext中通过getBeanFactoryPostProcessors()方法
//获取的,而beanFactoryPostProcessors是硬编码的BeanFactoryPostProcssor的列表(即通过AbstractApplicationContext.addBeanFactoryPostProcessor方法添加进去的)
//硬编码的BeanFactoryPostFacry的优先级是最高的,比任何配置的BeanFactoryPostProcessor要高
//您可能会问,那配置的硬编码的BeanFactoryPostProcessor在哪呢,他在我们的BeanDefinitionRegistry上注册着呢
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// BanFactoryPostProcessor接口是顶级接口,他的子接口BeanDefinitionRegistryPostProcessors在其上声明了一个额外的方法
//即void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
//我们要先执行BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry这个方法
//然后在调用这些BanFactoryPostProcessor的postProcessBeanFactory方法
//但是呢,Spring允许BeanDefinitionRegistryPostProcessors和postProcessBeanFactory的实现具有优先级(即实现Ordered或者PriorityOrdered),其中PriorityOrdered的又要比Ordered优先级高一点,优先级最低的是无序的BeanFactoryPostProcessor
Set<String> processedBeans = new HashSet<>();
//如果传入的BeanFactory实例是实现了BeanDefinitionRegistry的话
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
//声明两个临时列表:
//regularPostProcessors用于存储常规的BeanFactoryPostProcessor
//registryProcessors则用于存储实现自BeanDefinitionRegistryPostProcessor的BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
//beanFactoryPostProcessors指的是硬编码的BeanFactoryPostProcessor,它的优先级是最高的,故而先执行
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
//如果此硬编码的BeanFactoryPostProcessor是实现自BeanDefinitionRegistryPostProcessor,则将其加入到registryProcessors,并执行其特殊的
//postProcessBeanDefinitionRegistry方法,否则,加入到regularPostProcessors中,并不执行任何方法,等最后再统一执行
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, 调用实现了PriorityOrdered的BeanDefinitionRegistryPostProcessors
//beanFactory.getBeanNamesForType,根据类型,获取该类型的beanMame
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//如果实现了PriorityOrdered,则将其add到currentRegistryProcessors,等待一会的排序和执行
//并将beanName加入到processedBeans,以防止同一个bean,被调用多次
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
//对currentRegistryProcessors排序,然后将其add到registryProcessors
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
//调用currentRegistryProcessors中的BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
//清空currentRegistryProcessors,本人觉得是一种不好的设计
currentRegistryProcessors.clear();
// Next, 调用实现了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();
// Finally, 调用所有其他BeanDefinitionRegistryPostProcessors,知道没有任何一个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();
}
// Now, 调用到目前为止出现的所有BeanFactoryPostProcessor 的postProcessBeanFactory方法.
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// 调用用上下文实例注册的工厂处理器。即硬编码的BeanFactoryPostProcessor
//因为程序走到这里,也说明BeanFactory实例并非BeanDefinitionRegistry类型,因此优先级什么的也不care了
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// 分割BeanFactoryPostProcessors,按照PriorityOrdered > Ordered > 其他的顺序
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
//跳过,因为这表示该BeanFactoryPostProcessor也是一个BeanDefinitionRegistryPostProcessor,而他已经在前面被处理过了
}
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);
}
}
// First, 调用实现了PriorityOrdered接口的 BeanFactoryPostProcessors .
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, 调用实现了Ordered接口的 BeanFactoryPostProcessors .
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, 调用剩下下的 BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
//清理缓存的merged Bean定义,因为post-processors可能修改了原始元数据,例如替换值中的占位符……
beanFactory.clearMetadataCache();
}
}
概述:在实例化singleton的Bean之前,先调用BeanFactoryPostProcessor,以修改BenDifinition。ApplicationContext存在两种BeanFactoryPostProcessor,一种是硬编码的(即通过ApplicationContext的addBeanFactoryPostProcessor方法注册的),一种是配置的(即通过xml配置的)。先执行硬编码的BeanFactoryPostProcessor,Spring允许优先级,同时BeanDefinitionRegistryPostProcessor作为BeanFactoryPostProcessor的子接口,也拥有比纯BeanFactoryPostProcessor类型的实例更高的优先级。排序与执行,看注释即可。
registerBeanPostProcessors
//实例化并注册所有BeanPostProcessor的Bean实例
//优先级敏感
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
final class PostProcessorRegistrationDelegate {
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// 在BeanPostPorocessor的链最开始,注册一个BeanPostProcessorChecker,他的作用是
//在bean实例窗前的时候,打印日志,比如当:a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// 将实现了PriorityOrdered、Ordered还有其他的 BeanPostProcessors分隔开来
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First,注册实现了 PriorityOrdered 的 BeanPostProcessors.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, 注册实现了Ordered接口的BeanPostProcessors.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now,注册所有的常规BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, 重新注册所有的内置BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// 重新注册后置处理器ApplicationListenerDetector,该处理器会检测实现了ApplicationListener接口的bean,
// 将其移动到处理器链的最后(用于获取代理等)
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
}
概述:代码较长,但是干的工作也很简单,获取所有配置的BeanPostProcssor,然后按照PriorityOrdered > Ordered > 其他的顺序,调用beanFactory.addBeanPostProcessor(postProcessor)方法进行注册。因为BeanPostProcessor并不在此时执行,所以这里做的工作只是实例化、注册。
BeanPostProcessor是在实例化Bean时候init-method执行前后才会被调用哟,详细见Bean加载的讲解。
initMessageSource()
国际化相关
initApplicationEventMulticaster()
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
//注册监听者
protected void registerListeners() {
// 首先注册静态指定的监听者。
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 这里不初始化FactoryBean:我们需要不初始化所有常规bean,而是让后置处理程序应用于它们!
//这里只是将beanName注册到了广播器上,即注册配置方式注册的监听者的beanName
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// 发布事件
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
}
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
//广播事件
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
}
概述:如果用户自定义了事件广播器,那么使用用户定义的,否则使用SimpleApplicationEventMulticaster这个ApplicationEventMulticaster默认实现,来作为applicationEventMulticaster变量的值,并将其注册到beanFactory的单例缓存中。
onRefresh()
对Web的ApplicationContext至关重要,在特定上下文子类中初始化其他特殊bean。
registerListeners()
protected void registerListeners() {
// 注册静态(硬编码)的特定监听器.
for (ApplicationListener<?> listener : getApplicationListeners()) {
//注册
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 注册配置的监听者的BeanName,先不实例化他们
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
//注册
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// 发射一个earlyEvent
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
finishBeanFactoryInitialization(beanFactory)
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 我当前上下文环境初始化转换服务,ConversionService
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
//如果此时没有注册任何一个解析属性值的后置处理器, 那么就注册一个默认的内嵌属性值解析器。
//此时,只要用于解析注解中的值
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// 尽早初始化LoadTimeWeaverAware bean,以便尽早注册它们的转换器。
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
//停止使用临时类加载器进行类型匹配。
beanFactory.setTempClassLoader(null);
// 缓存bean的定义(BanDefinition),不会再修改他们了
beanFactory.freezeConfiguration();
// 实例化所有剩余的(非lazy-init的)单例。
beanFactory.preInstantiateSingletons();
}
概述:在该方法中完成BeanFactory的初始化工作,
-
首先检查ConversionService,那段是否有名字
为"conversionService"或者ConversionService类型的BeanDefinition存在,如果存在,则设置为beanFactory的conversionService变量的值。
-
判断当前的beanFactory是否有内嵌属性值解析器,如果不存在,则赋一个默认的解析器
-
尽早初始化LoadTimeWeaverAware bean,以便尽早注册它们的转换器。
-
停止对临时类加载器的使用
-
冻结所有的beanDefinition,暗示以后不会再修改它们了
-
实例化所有的单例Bean(排除lazy-init)
finishRefresh()
protected void finishRefresh() {
// 清理上下文级别的Rsource资源 (such as ASM metadata from scanning).
clearResourceCaches();
// 为当前上下文初始化生命周期处理器
initLifecycleProcessor();
// 首先将refresh传播到生命周期处理器上.
getLifecycleProcessor().onRefresh();
//发送终极事件.
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
protected void initLifecycleProcessor() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//判断上下文是否存在“lifecycleProcessor”的BanDefinition
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
if (logger.isTraceEnabled()) {
logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
}
}
else {
//实例化一个默认的生命周期处理器
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
defaultProcessor.setBeanFactory(beanFactory);
this.lifecycleProcessor = defaultProcessor;
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
if (logger.isTraceEnabled()) {
logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
"[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
}
}
}
public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactoryAware {
public void onRefresh() {
startBeans(true);
this.running = true;
}
private void startBeans(boolean autoStartupOnly) {
//获取所有实现了Lifecycle的Ban
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
Map<Integer, LifecycleGroup> phases = new HashMap<>();
//循环启动刷新
lifecycleBeans.forEach((beanName, bean) -> {
if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
int phase = getPhase(bean);
LifecycleGroup group = phases.get(phase);
if (group == null) {
group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
phases.put(phase, group);
}
group.add(beanName, bean);
}
});
if (!phases.isEmpty()) {
List<Integer> keys = new ArrayList<>(phases.keySet());
Collections.sort(keys);
for (Integer key : keys) {
phases.get(key).start();
}
}
}
//从当前上下文的底层BeanFactory中获取所有实现了Lifecycle的Bean
protected Map<String, Lifecycle> getLifecycleBeans() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
Map<String, Lifecycle> beans = new LinkedHashMap<>();
String[] beanNames = beanFactory.getBeanNamesForType(Lifecycle.class, false, false);
for (String beanName : beanNames) {
String beanNameToRegister = BeanFactoryUtils.transformedBeanName(beanName);
boolean isFactoryBean = beanFactory.isFactoryBean(beanNameToRegister);
String beanNameToCheck = (isFactoryBean ? BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
if ((beanFactory.containsSingleton(beanNameToRegister) &&
(!isFactoryBean || matchesBeanType(Lifecycle.class, beanNameToCheck, beanFactory))) ||
matchesBeanType(SmartLifecycle.class, beanNameToCheck, beanFactory)) {
Object bean = beanFactory.getBean(beanNameToCheck);
if (bean != this && bean instanceof Lifecycle) {
beans.put(beanNameToRegister, (Lifecycle) bean);
}
}
}
return beans;
}
}
概述:Spring中提供了lifecycle接口,而该接口声明了start/stop方法,实现此接口的Bean,Spring会在启动时调用其start方法,在Sring关闭时调用stop方法,以开启和关闭生命周期。
好了,ioc容器的创建过程就是这个样子,后面再详细的写一下aop的原理与bean的生命周期完善一下就差不多了。其他的细节就需要自己慢慢细看了
参考:
https://blog.youkuaiyun.com/qq_31179577/article/details/100693282
https://blog.youkuaiyun.com/nuomizhende45/article/details/81158383/