可能已经启动了另外一个Bean工厂,所以需要刷新,先关闭,再启动一个新的Bean工厂;
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 初始化BeanFactory,并进行XML文件读取,并将得到的BeanFactory记录再当前实体的属性中
refreshBeanFactory();
// 返回当前实体的BeanFactory属性
return getBeanFactory();
}
如果有就删除和关闭
没有就创建,设置Id,自定义BeanFactory
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
//
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
下面这个方法也是可以扩展的,可以修改相关的属性,通过extents重写这个类,然后super()调用父类的方法就可以了;
allowBeanDefinitionOverriding允许Bean的定义信息覆盖:lookup注解的原理,就是依靠了这个注解,原型Bean,每次获取都获取新的Bean。
allowCircularReferences允许循环引用:是否允许循环引用
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
if (this.allowBeanDefinitionOverriding != null) {
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.allowCircularReferences != null) {
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
loadBeanDefinitions,第二个重要的代码块
加载Bean的定义信息,将信息存储到工程类中,这里就体现到了设计模式。适配器的设计模式。
package org.springframework.core.Constatnts类,对类文件中的场景进行管理封装成一个实例。
private static final Constants constants = new Constants(XmlBeanDefinitionReader.class);
Spring中的注册接口,声明了接口可以用来注册类型,比如BeanDefinitionRegistry可以用来注册BeanDefinition。
这个Generator实现了接口,实际干活委派给了Utils类。
public class DefaultBeanNameGenerator implements BeanNameGenerator {
/**
* A convenient constant for a default {@code DefaultBeanNameGenerator} instance,
* as used for {@link AbstractBeanDefinitionReader} setup.
* @since 5.2
*/
public static final DefaultBeanNameGenerator INSTANCE = new DefaultBeanNameGenerator();
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
return BeanDefinitionReaderUtils.generateBeanName(definition, registry);
}
}
public class NamedThreadLocal<T> extends ThreadLocal<T> { private final String name; /** * Create a new NamedThreadLocal with the given name. * @param name a descriptive name for this ThreadLocal */ public NamedThreadLocal(String name) { Assert.hasText(name, "Name must not be empty"); this.name = name; } @Override public String toString() { return this.name; } }
这个StringUtils的方法可以用来使用任意一个分隔符解析分割,很好用。
public static String[] tokenizeToStringArray(@Nullable String str, String delimiters) { return tokenizeToStringArray(str, delimiters, true, true); }
root和generic不是继承的关系
流式变成,一个断言一个Consumer
private void removeManualSingletonName(String beanName) { updateManualSingletonNames(set -> set.remove(beanName), set -> set.contains(beanName)); } /** * Update the factory's internal set of manual singleton names. * @param action the modification action * @param condition a precondition for the modification action * (if this condition does not apply, the action can be skipped) */ private void updateManualSingletonNames(Consumer<Set<String>> action, Predicate<Set<String>> condition) { if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) synchronized (this.beanDefinitionMap) { if (condition.test(this.manualSingletonNames)) { Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames); action.accept(updatedSingletons); this.manualSingletonNames = updatedSingletons; } } } else { // Still in startup registration phase if (condition.test(this.manualSingletonNames)) { action.accept(this.manualSingletonNames); } } }
总结:
流程十分,非常的繁杂,包括了对文件的解析,总之最后将文件或者注解解析完成后,会放在beanFactory中的两个日期中,一个是Map,key是bean的名字,value是BeanDefinition,另外一个是Set,存储的是beanName,这个其中涉及到了许多的类,组合起来和抽象起来,非常多的分支,很难看明白或者看透彻,这里面每一个类都是可以拿来研究的,比如研究抽象了什么,怎么时候,命名等等。