当前位置 博文首页 > yangkewei616的专栏:Spring容器初始化、bean解析、getbean流程
Context类图如下:
BeanFactory接口类图如下:
Resource接口类图如下:
BeanDefinitionReader接口类图如下:
BeanDefinition接口类图如下:
ResourceLoader接口类图如下:
ApplicationContext做为容器中心(内部wrap一个beanfactory),
1. 把持久化文件转化resource
2. 读入以流的形势读到内存,BeanDefinitionReader以流形式解析resource成BeanDefinition
3. BeanDefinitionHolder对BeanDefinition进行wrap,注册到context wrap的beanfactory中
下面开始从代码流程上分析Bean的解析过程:
使用代码如下:
String file = "bean.xml";
ClassPathXmlApplicationContext context1 = new ClassPathXmlApplicationContext(file);
ModelA modelA = (ModelA) context1.getBean("modelA");
System.out.println(modelA);
ClassPathXmlApplicationContext
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
两个主要方法:setConfigLocations,refresh,先跟setConfigLocations,功能主要两个:1.把占位符替换为真正的值 2.把值path设置到context中
AbstractRefreshableConfigApplicationContext
public void setConfigLocations(String... locations) {
if (locations != null) {
Assert.noNullElements(locations, "Config locations must not be null");
this.configLocations = new String[locations.length];
for (int i = 0; i < locations.length; i++) {
//把占位符号用环境变量或System.getProperties().get("key")替换
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}
protected String resolvePath(String path) {
//getEnvironment(),可以返回一个StandardEnvironment,继续跟到AbstractPropertyResolver类
return getEnvironment().resolveRequiredPlaceholders(path);//
}
AbstractPropertyResolver
public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
if (this.strictHelper == null) {
this.strictHelper = createPlaceholderHelper(false);
}
return doResolvePlaceholders(text, this.strictHelper);
}
private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) {
//最终处理在PropertyPlaceholderHelper
return helper.replacePlaceholders(text, new PropertyPlaceholderHelper.PlaceholderResolver() {
@Override
public String resolvePlaceholder(String placeholderName) {
return getPropertyAsRawString(placeholderName);
}
});
}
public String replacePlaceholders(String value, PlaceholderResolver placeholderResolver) {
Assert.notNull(value, "'value' must not be null");
return parseStringValue(value, placeholderResolver, new HashSet<String>());
}
//核心方法
//strVal = "${key:bean$}.xml" 带默认值
//strVal = "${key${keyiner}}.xml" 带嵌套子占位符
protected String parseStringValue(
String strVal, PlaceholderResolver placeholderResolver, Set<String> visitedPlaceholders) {
StringBuilder result = new StringBuilder(strVal);
//this.placeholderPrefix='${',这个值可以修改
int startIndex = strVal.indexOf(this.placeholderPrefix);
while (startIndex != -1) {
//找到对应${的}
//找的逻辑很简单,用index变量,从前往后找,匹配到前缀index++,匹配到后缀且index>0,index--,否则命中,如果什么都匹配继续找
int endIndex = findPlaceholderEndIndex(result, startIndex);
if (endIndex != -1) {
String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);
String originalPlaceholder = placeholder;
if (!visitedPlaceholders.add(originalPlaceholder)) {
throw new IllegalArgumentException(
"Circular placeholder reference '" + originalPlaceholder + "' in property definitions");
}
//这个递归的作用先替换子占位符,及先找出嵌套子占位符的${keyiner},用值替换
// Recursive invocation, parsing placeholders contained in the placeholder key.
//
placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
// Now obtain the value for the fully resolved key...
//到StandardEnvironment注册的Propertie和evn找替换占位符的value
String propVal = placeholderResolver.resolvePlaceholder(placeholder);
//没有找到,获取默认值,"${key:bean$}.xml"中的bean
if (propVal == null && this.valueSeparator != null) {
int separatorIndex = placeholder.indexOf(this.valueSeparator);
if (separatorIndex != -1) {
String actualPlaceholder = placeholder.substring(0, separatorIndex);
String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length());
propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);
if (propVal == null) {
propVal = defaultValue;
}
}
}
if (propVal != null) {
// Recursive invocation, parsing placeholders contained in the
// previously resolved placeholder value.
//和上面递归类似,这个是evn或prop中有占位符
propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
if (logger.isTraceEnabled()) {
logger.trace("Resolved placeholder '" + placeholder + "'");
}
startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length());
}
else if (this.ignoreUnresolvablePlaceholders) {
// Proceed with unprocessed value.
startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());
}
else {
throw new IllegalArgumentException("Could not resolve placeholder '" +
placeholder + "'" + " in string value \"" + strVal + "\"");
}
visitedPlaceholders.remove(originalPlaceholder);
}
else {
startIndex = -1;
}
}
return result.toString();
}
下面跟refresh方法,refresh主要模版在父类AbstractApplicationContext中,
AbstractApplicationContext.refresh
@Override
public void refresh() throws BeansException, IllegalStateException {
//枷锁,refresh逻辑同时只有一个线程,close方法也用的这个锁,保证只能同时执行一个方法
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
//设置启动时间、一些标志位、初始化一些全局变量等
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//真正BeanFactory创建方法,上面主要分析这个方法
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//对beanfactory
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
//子类prepare,如果子类类似webcontext,evnbean,特殊bean,在这里实现。它的作用同前一个方法
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//BeanFactoryPostProcessor的实现方法被调用
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
//把BeanPostProcessor注册到beanFactory的一个list中
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
//国际化相关,
initMessageSource();
// Initialize event multicaster for this context.
//context是实现了ApplicationEventPublisher,
//如果没有配置applicationEventMulticaster,则注册单例new SimpleApplicationEventMulticaster();
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
//默认空实现,为子类在实例singletonsBean之前,可以实例先特殊bean
onRefresh();
// Check for listener beans and register them.
//把listener注册到到applicationEventMulticaster中
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//初始化所有非懒加载的单例bean
//重要方法,跟进分析
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
//发个context event,get生命周期的相关bean,注册一些全局变量
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.
//如果挂了,清除单例bean,避免浪费资源
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方法
AbstractApplicationContext
protected void prepareRefresh() {
//纪录启动时间,设置标志位
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// Initialize any placeholder property sources in the context environment
//env等初始化一些全局的property
initPropertySources();
// Validate that all properties marked as required are resolvable
// see ConfigurablePropertyResolver#setRequiredProperties
//validate必要prop全部有,如果没有throws异常
getEnvironment().validateRequiredProperties();
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
obtainFreshBeanFactory这个时重点方法,配置文件的加载、解析、注册
AbstractApplicationContext
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//主要的初始化功能在这个方法
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
AbstractRefreshableApplicationContext
@Override
protected final void refreshBeanFactory() throws BeansException {
//如果之前存在BeanFactory
if (hasBeanFactory()) {
//destory此BeanFactory注册的单例bean
destroyBeans();
//置为当前wrap引用指向null
closeBeanFactory();
}
try {
//new BeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
//把beanFactory和当前Context用id关联
beanFactory.setSerializationId(getId());
//设置把Contxt的一些标志设置给BeanFactory,这里主要有两个
//allowBeanDefinitionOverriding(bean同名 覆盖or exception),allowCircularReferences(bean可以循环引用)
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);
}
}
真正创建的factory是DefaultListableBeanFactory
AbstractRefreshableApplicationContext
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
loadBeanDefinitions实现在子类中,因为不同的配置文件需要是不同的resource,也需要不同的reader
AbstractXmlApplicationContext.loadBeanDefinitions
@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.
//把context的env设置Reader中
beanDefinitionReader.setEnvironment(this.getEnvironment());
//把context的ResouceLoader设置Reader中,Context继承DefaultResourceLoader
beanDefinitionReader.setResourceLoader(this);
//xml中spring相关的dtd和schema的entiryResolver
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父类AbstractBeanDefinitionReader中构造方法
AbstractBeanDefinitionReader.AbstractBeanDefinitionReader
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//把DefaultListableBeanFactory实现了BeanDefinitionRegistry接
this.registry = registry;
// Determine ResourceLoader to use.
//DefaultListableBeanFactory没有实现ResourceLoader,所以走else
if (this.registry instanceof ResourceLoader) {
this.resourceLoader = (ResourceLoader) this.registry;
}
else {
this.resourceLoader = new PathMatchingResourcePatternResolver();
}
//DefaultListableBeanFactory没有实现EnvironmentCapable,所以走else