以ClassPathXmlApplicationContext的构造函数为入口点。(ClassPathXmlApplicationContext继承图见上一日记)
public ClassPathXmlApplicationContext(
String[] configLocations,
boolean refresh,
@Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
重点就在于refresh()方法,该接口是ConfigurableApplicationContext中定义的,AbstractApplicationContext实现了该方法,如下:
public void refresh()
throws BeansException, IllegalStateException {
synchronized (
this.
startupShutdownMonitor) {
// Prepare this context for refreshing.
//初始化一些参数,校验一些必须的属性是否配置
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//创建一个新的beanFactory,重新加载bean的定义
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
//初始化事件广播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
这只是一个模版方法,定义基本的操作骨架,涉及的一些抽象方法必须在延迟到子类中实现。
Refresh()方法的功能主要是重新生成一个beanFactory(DefaultListableBeanFactory类型),然后执行加载bean定义,生成对应的BeanDefinition对象保存在beanFactory中的map属性中。这一功能的主要实现主要通过
obtainFreshBeanFactory()
方法,继续跟进:
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (
logger.isDebugEnabled()) {
logger.debug(
"Bean factory for " + getDisplayName() +
": " + beanFactory);
}
return beanFactory;
}
refreshBeanFactory方法是一个抽象方法,具体的代码逻辑我们可以根据之前的关于applicationContext的继承线中查找离ClassPathXmlApplicationContext最近的实现了该方法的类(这里是AbstractRefreshableApplicationContext),具体实现代码如下:
@Override
protected final void refreshBeanFactory()
throws BeansException {
if (hasBeanFactory()) {
//一个模版方法,默认是销毁所有在beanFactory中的缓存的单例对象(CurrentHashMap保存kv)
destroyBeans();
//将beanFactory变量指向null
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
//默认实现为设置beanFactory的setAllowBeanDefinitionOverriding和setAllowCircularReferences
customizeBeanFactory(beanFactory);
//根据beanFactory得到资源,读取资源并解析,封装为BeanDefinition对象,通过beanFactory注册该bean定义对象到map容器中
loadBeanDefinitions(beanFactory);
synchronized (
this.
beanFactoryMonitor) {
this.
beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException(
"I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
这个方法中的一些操作的具体作用都在注释中标明了,最关键的代码就是loadBeanDefinitions()方法,该方法会加载配置文件中的bean定义,详细代码如下:
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader =
new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
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);
}
其中的XmlBeanDefinitionReader是xml文件格式配置的bean定义读取类,真正的bean定义的加载逻辑就是委托它来实现的。在这里我们将beanFactory作为构造参数传递给XmlBeanDefinitionReader,XmlBeanDefinitionReader内部会将该beanFactory作为一个bean定义的注册器BeanDefinitionRegistry。继续跟loadBeanDefinitions(),代码如下:
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);
}
}
主要判断下当前上下文中是否有资源,如果有就直接加载,没有的话,会根据location通过
ResourceLoader获取资源,然后再执行这个方法。
@Override
public int loadBeanDefinitions(Resource resource)
throws BeanDefinitionStoreException {
//EncodedResource(resource):包装resource,获取字符输入流的时候根据编码和字符集将原始字节流转换。
return loadBeanDefinitions(
new EncodedResource(resource));
}
我们直接跳过一些代码,一直跟进和bean定义加载有关的方法,最后会到这么一个方法中:
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//使用jdk1.8 rt.jar中的使用sax解析xml文件的方式,得到Document对象
Document doc = doLoadDocument(inputSource, resource);
return registerBeanDefinitions(doc, resource);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
//后续都是一些catch操作,直接省略
……………..
}
根据输入源inputSource获取对应的输入流,再解析为代表整个xml配置文件的document对象,最后执行beanDefinitions的注册操作。
public int registerBeanDefinitions(Document doc, Resource resource)
throws BeanDefinitionStoreException {
//创建一个DefaultBeanDefinitionDocumentReader类型的实例
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
BeanDefinitionDocumentReader为用于读取解析包含spring bean定义的document的spi。这里的实际类型为DefaultBeanDefinitionDocumentReader。
createReaderContext(resource)方法会生成一个xml读取上下文对象,并且会将this指向XmlBeanDefinitionReader对象赋给上下文内部的reader属性。
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
//readerContext中的XmlBeanDefinitionReader类型的reader属性中的registry为传递进去的beanFactory
// (该beanFactory实现了beanDefineRegister接口)
this.
readerContext = readerContext;
logger.debug(
"Loading bean definitions");
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
}
注意,这里该方法将readerContext对象赋给了同名的内部属性,后面注册beanDefinitions时,使用的就是readerContext中的XmlBeanDefinitionReader对象的registry(其实就是DefaultListableBeanFactory类型的对象)属性,调用相关注册接口完成注册操作。
继续跳过一些非功能性代码,继续跟进:
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//1.该标签为空,2.该标签的 xmlns = http://www.springframework.org/schema/beans,说明为
根标签
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)) {
//解析spring中的默认标签
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
这里会获取root节点()下的所有子节点,下面我跟进parseDefaultElement方法
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele,
IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele,
ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele,
BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele,
NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
这里它会判断当前节点名为import,alias,bean,还是beans,来进行进一步的操作,这里我们以bean为例子。
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder !=
null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
BeanDefinitionReaderUtils.
registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error(
"Failed to register bean definition with name '" +
bdHolder.getBeanName() +
"'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(
new BeanComponentDefinition(bdHolder));
}
}
这里第一步生成了BeanDefinitionHolder对象,该对象其实就是BeanDefinition持有对象,内部还有beanName,aliases属性,跟进
delegate.parseBeanDefinitionElement(ele)方法,这次跳过中间的一些方法,直接到最终解析element节点封装为BeanDefinition对象的方法
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
@Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {
if (ele.hasAttribute(
SINGLETON_ATTRIBUTE)) {
error(
"Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
}
else if (ele.hasAttribute(
SCOPE_ATTRIBUTE)) {
bd.setScope(ele.getAttribute(
SCOPE_ATTRIBUTE));
}
else if (containingBean !=
null) {
// Take default from containing bean in case of an inner bean definition.
bd.setScope(containingBean.getScope());
}
if (ele.hasAttribute(
ABSTRACT_ATTRIBUTE)) {
bd.setAbstract(
TRUE_VALUE.equals(ele.getAttribute(
ABSTRACT_ATTRIBUTE)));
}
String lazyInit = ele.getAttribute(
LAZY_INIT_ATTRIBUTE);
if (
DEFAULT_VALUE.equals(lazyInit)) {
lazyInit =
this.
defaults.getLazyInit();
}
bd.setLazyInit(
TRUE_VALUE.equals(lazyInit));
String autowire = ele.getAttribute(
AUTOWIRE_ATTRIBUTE);
bd.setAutowireMode(getAutowireMode(autowire));
if (ele.hasAttribute(
DEPENDS_ON_ATTRIBUTE)) {
String dependsOn = ele.getAttribute(
DEPENDS_ON_ATTRIBUTE);
bd.setDependsOn(StringUtils.
tokenizeToStringArray(dependsOn,
MULTI_VALUE_ATTRIBUTE_DELIMITERS));
}
String autowireCandidate = ele.getAttribute(
AUTOWIRE_CANDIDATE_ATTRIBUTE);
if (
"".equals(autowireCandidate) ||
DEFAULT_VALUE.equals(autowireCandidate)) {
String candidatePattern =
this.
defaults.getAutowireCandidates();
if (candidatePattern !=
null) {
String[] patterns = StringUtils.
commaDelimitedListToStringArray(candidatePattern);
bd.setAutowireCandidate(PatternMatchUtils.
simpleMatch(patterns, beanName));
}
}
else {
bd.setAutowireCandidate(
TRUE_VALUE.equals(autowireCandidate));
}
if (ele.hasAttribute(
PRIMARY_ATTRIBUTE)) {
bd.setPrimary(
TRUE_VALUE.equals(ele.getAttribute(
PRIMARY_ATTRIBUTE)));
}
if (ele.hasAttribute(
INIT_METHOD_ATTRIBUTE)) {
String initMethodName = ele.getAttribute(
INIT_METHOD_ATTRIBUTE);
bd.setInitMethodName(initMethodName);
}
else if (
this.
defaults.getInitMethod() !=
null) {
bd.setInitMethodName(
this.
defaults.getInitMethod());
bd.setEnforceInitMethod(
false);
}
if (ele.hasAttribute(
DESTROY_METHOD_ATTRIBUTE)) {
String destroyMethodName = ele.getAttribute(
DESTROY_METHOD_ATTRIBUTE);
bd.setDestroyMethodName(destroyMethodName);
}
else if (
this.
defaults.getDestroyMethod() !=
null) {
bd.setDestroyMethodName(
this.
defaults.getDestroyMethod());
bd.setEnforceDestroyMethod(
false);
}
if (ele.hasAttribute(
FACTORY_METHOD_ATTRIBUTE)) {
bd.setFactoryMethodName(ele.getAttribute(
FACTORY_METHOD_ATTRIBUTE));
}
if (ele.hasAttribute(
FACTORY_BEAN_ATTRIBUTE)) {
bd.setFactoryBeanName(ele.getAttribute(
FACTORY_BEAN_ATTRIBUTE));
}
return bd;
经过上面的解析,成功构造出一个BeanDefinitionHolder对象,该对象中的属性详细记录了bean创建时的一些细节,比如是否支持懒加载,是否为单例,初始化方法和销毁方法等等...
bean定义解析完成后,就是注册方法
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder !=
null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
BeanDefinitionReaderUtils.
registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error(
"Failed to register bean definition with name '" +
bdHolder.getBeanName() +
"'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(
new BeanComponentDefinition(bdHolder));
}
}
继续跟进注册方法:
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
//注册bean定义,这里的registry对象的实际类型为实现了BeanDefinitionRegistry接口的DefaultListableBeanFactory对象
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases !=
null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
这里首先取出beanName, 然后获得registry对象(也就是DefaultListableBeanFactory对象),有了beanName, beanDefinition,beanFactory就可以将该xml配置文件中标签定义的beanName和创建细节维护到一个DefaultListableBeanFactory内部的一个beanDefinitionMap对象中。
到现在为止,bean定义的加载逻辑就全部理完了。
加载bean定义完成后,spring就会执行非懒加载的单例对象的初始化。这点主要在finishBeanFactoryInitialization(beanFactory)方法中实现。
首先spring会获取beanFactory中的beanDefinitionMap, 然后遍历判断是否为非抽象非懒加载单例模式,然后执行创建逻辑。如果该单例对象不是一个factoryBean,那么会直接调用getBean(beanName)方法,判断beanFactory中的单例缓存池(DefaultSingletonBeanRegistry中的
singletonObjects)中是否含有该对象,有,返回该对象,没有,根据beanDefinition执行创建逻辑,并将创建后的对象添加进singletonObjects中
,
然后返回。