本文更应该是bean定义和bean注册了,但是为了都是在Spring启动的时候执行的ContextLoaderListener,所以标题名字就是继续ContextLoaderListener了。
还是DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root);
核心方法this.parseBeanDefinitions(root, this.delegate);
如何使Spring的默认标签执行this.parseDefaultElement(ele, delegate);
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if(delegate.nodeNameEquals(ele, "import")) {
this.importBeanDefinitionResource(ele);
} else if(delegate.nodeNameEquals(ele, "alias")) {
this.processAliasRegistration(ele);
} else if(delegate.nodeNameEquals(ele, "bean")) {
//处理bean的方法,传入的是BeanDefinitionParserDelegate
this.processBeanDefinition(ele, delegate);
} else if(delegate.nodeNameEquals(ele, "beans")) {
this.doRegisterBeanDefinitions(ele);
}
}
看如何读取的bean标签:
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if(bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
} catch (BeanDefinitionStoreException var5) {
this.getReaderContext().error("Failed to register bean definition with name \'" + bdHolder.getBeanName() + "\'", ele, var5);
}
this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
其实还是委托给了BeanDefinitionParserDelegate
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {//containingBean传入的是null
String id = ele.getAttribute("id");
String nameAttr = ele.getAttribute("name");
ArrayList aliases = new ArrayList();
if(StringUtils.hasLength(nameAttr)) {
//name属性值用,;隔开就是别名啊
String[] beanName = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
aliases.addAll(Arrays.asList(beanName));
}
//有Id直接用作beanName
String beanName1 = id;
if(!StringUtils.hasText(id) && !aliases.isEmpty()) {
//id属性值没有值,就用上面别名的第一个值作为beanName
beanName1 = (String)aliases.remove(0);
if(this.logger.isDebugEnabled()) {
this.logger.debug("No XML \'id\' specified - using \'" + beanName1 + "\' as bean name and " + aliases + " as aliases");
}
}
if(containingBean == null) {
//保证beanName和别名都不会存在,即都是唯一的
//然后将beanName和alias都放入到成员变量HashSet
//这个成员变量包含所有bean的beanName和aliases哈
this.checkNameUniqueness(beanName1, aliases, ele);
}
AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName1, containingBean);
if(beanDefinition != null) {
if(!StringUtils.hasText(beanName1)) {
try {
if(containingBean != null) {
beanName1 = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
} else {
beanName1 = this.readerContext.generateBeanName(beanDefinition);
String aliasesArray = beanDefinition.getBeanClassName();
if(aliasesArray != null && beanName1.startsWith(aliasesArray) && beanName1.length() > aliasesArray.length() && !this.readerContext.getRegistry().isBeanNameInUse(aliasesArray)) {
aliases.add(aliasesArray);
}
}
if(this.logger.isDebugEnabled()) {
this.logger.debug("Neither XML \'id\' nor \'name\' specified - using generated bean name [" + beanName1 + "]");
}
} catch (Exception var9) {
this.error(var9.getMessage(), ele);
return null;
}
}
String[] aliasesArray1 = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName1, aliasesArray1);
} else {
return null;
}
}
有必要提一下这个方法是返回的BeanDefinitionHolder,hold的对象是BeanDefinition哈,从该方法可以知道每个bean标签对应一个BeanDefinitionHolder,每个holder中都有一个BeanDefinition
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
try{
String className = ele.getAttribute("class").trim();
ex = ele.getAttribute("parent");
//通过className和parent属性来构建一个GenericBeanDefinition对象
AbstractBeanDefinition bd = this.createBeanDefinition(className, ex);
//bean标签上的属性 init-method destroy-method factory-method
//factory-bean abstract scope autowire lazy-init //depends-on autowire-candidate primary dependency-check
//总之就是调用bd.setXxx(xxx)来填充BeanDefinition而已
this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));
//处理meta标签
this.parseMetaElements(ele, bd);
//处理lookup-method标签
this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//处理子节点的construct标签
this.parseConstructorArgElements(ele, bd);
//处理子节点的property标签
this.parsePropertyElements(ele, bd);
//处理qualifier标签
this.parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(this.extractSource(ele));
AbstractBeanDefinition var7 = bd;
return var7;
catch(Exception ex){
xxxxx
}finally{
this.parseState.pop();
}
return null;
}
我们回顾一下
第一步:DefaultBeanDefinitionDocumentReader. doRegisterBeanDefinitions(Element root);还是从Root(即beans标签)开始
第二步:解析Element(import bean等标签)
this.processBeanDefinition(ele, delegate);,this完全委托给了delegate完成装在beanDefinition和注册
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
a)在通过解析bean(以bean为例子)标签设置BeanDefinition的各个属性,然后连同beanName和别名通过构造函数一起放到BeanDefinitionHolder中。
b)注册beanDefinition和alias,注册器就是DefaultListableBeanFactory工厂其实就是跟成员map或者list添加一个值或者多个值
c)注册beanDefinitioin即给其成员变量beanDefinitionMap = new ConcurrentHashMap(256);
添加一个keybeanName,value为BeanDefinition的值
同时给另一个成员beanDefinitionNames = new ArrayList(256);
添加一个beanName值
d)注册别名
DefaultListableBeanFactory的父类SimpleAliasRegistry
aliasMap = new ConcurrentHashMap(16);
key是alias value是beanName
e)有哪些bean的引用,继承了那些bean
到这里一个bean标签转换成BeanDefinition再到注册算是完成了。
还记得这篇博文是那个方法进来的吗?哈哈
wax.refresh()方法的ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
public void refresh() throws BeansException, IllegalStateException {
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
}
obtainFreshBeanFactory()方法内部,给AbstractRefreshableApplicationContext的beanFactory赋值之前就是前面所有看到的、讲解过的代码
protected final void refreshBeanFactory() throws BeansException {
DefaultListableBeanFactory ex = this.createBeanFactory();
ex.setSerializationId(this.getId());
this.customizeBeanFactory(ex);
this.loadBeanDefinitions(ex);//这一步是之前所讲
Object var2 = this.beanFactoryMonitor;
synchronized(this.beanFactoryMonitor) {
this.beanFactory = ex;//获取工厂
}
}
在代码中跳来跳去,原来只是为了获取DefaultListableBeanFactory
oh,my god!!这一行代码中,读取了配置文件,获取了Document的root节点、找到bean标签
转化成了BeanDefinition 在和beanname以及别名组装到了BeanDefintionHolder中,在将BeanDefinition注册到工厂中,别名也注册进去(工厂的父类)SimpleAliasRegistry。
在看wac.refresh()全景
this.prepareRefresh();
//已读
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
//准备在设置部分信息到BeanFactory
this.prepareBeanFactory(beanFactory);
this.postProcessBeanFactory(beanFactory);
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
}
看下prepareBeanFactory,它set了一堆对象,并往BeanFactory注册了几个跟环境有关的对象,这里说的注册还是给成员singletonObjects = new ConcurrentHashMap(256);添加key和value对
DefaultListableBeanFactory的三个成员有值了,下面是所有成员变量,先看下,后边都会用到。
private static Class<?> javaUtilOptionalClass = null;
private static Class<?> javaxInjectProviderClass = null;
private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories;
private String serializationId;
private boolean allowBeanDefinitionOverriding = true;
private boolean allowEagerClassLoading = true;
private Comparator<Object> dependencyComparator;
private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();
private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap(16);
// applicationContext.xml中bean key:test value
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap(64);
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap(64);
//
private volatile List<String> beanDefinitionNames = new ArrayList(256);
private volatile Set<String> manualSingletonNames = new LinkedHashSet(16);
private volatile String[] frozenBeanDefinitionNames;
private volatile boolean configurationFrozen = false;
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.setBeanClassLoader(this.getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
if(beanFactory.containsBean("loadTimeWeaver")) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
if(!beanFactory.containsLocalBean("environment")) {
beanFactory.registerSingleton("environment", this.getEnvironment());
}
if(!beanFactory.containsLocalBean("systemProperties")) {
beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties());
}
if(!beanFactory.containsLocalBean("systemEnvironment")) {
beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment());
}
}
到这里,只是一个bean标签的解析,还有import ,甚至是自定义标签 tx 等没有讲,但是现在已经有些晕乎了。。。