加载机制:
ClassPathXmlApplicationContext:应用程序的上下文,将普通路径解析为类(classpath)路径资源名称
// 多个配置文件的情况下,后加载的bean会覆盖先前定义好的bean,这样做的目的是为了通过额外的XML文件来特意重写某个Bean
public ClassPathXmlApplicationContext(String[] configLocations, booleanrefresh, ApplicationContext parent)
throwsBeansException {
//
super(parent);
// 解析 bean.xml 文件
setConfigLocations(configLocations);
if (refresh){
refresh();
}
}
DefaultBeanDefinitionDocumentReader: BeanDefinitionDocumentReader 接口的默认实现根据“spring-beans” DTD和XSD格式读取bean定义(Spring的默认XML bean定义格式)。
// 在 {@code <beans />} 元素中注册每个定义好的bean
// 同时会解析 beans 的 profile
-> protectedvoid doRegisterBeanDefinitions(Element root);
// 根据“spring-beans”XSD解析bean定义
-> public voidregisterBeanDefinitions(Document doc, XmlReaderContextreaderContext);
// 解析 root 节点下的其它节点 import","alias", "bean".
-> protectedvoid parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate);
-> 判断当前 ele 是什么节点 ,然后在跳转到对应的方法中处理
private voidparseDefaultElement(Element ele,BeanDefinitionParserDelegate delegate);
|
|--->processBeanDefinition(ele, delegate);
1.InputStreamSource 封装了任何能返回 InputStream 的类,比如 File ClassPath Byte Array 等
-> booleanexists(); 判断文件是否存在
-> booleanisReadable(); 文件是否可读/权限
-> booleanisOpen(); 文件是否打开状态
-> 此外还提供了 URL URI File 类型转换,以及获取lastModified属性,文件名,出错信息等
1.加载 bean.xml 文件
-> ConfigReader:用于读取及验证配置文件是否正确(XML的XSD验证)
-> ReflectionUtil:根据 bean.xml 中的配置进行反射实例化对象
2.解析 bean.xml 标签,找到对应 bean 的配置,实例化对象
Spring 核心类
-> DefaultListableBeanFactory(核心类/注册及Bean的默认实现) 扩展了 XmlBeanDefinitionReader(自定义的XML读取器,实现个性化的BeanDefinitionReader读取)
->XmlBeanDefinitionReader XML文件读取
->AbstractBeanDefinitionReader
//读取 bean 定义时的环境 比如 @Profile("dev") 这种
//同时默认加载systemPropertiessystemEnvironment 系统配置及修通变量 - 详请(StandardEnvironment.class)
->protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry);
//从指定的XML文件加载bean定义。
publicint loadBeanDefinitions(EncodedResource encodedResource) throwsBeanDefinitionStoreException;
->BeanDefinitionReader
->ResourceLoader:资源加载器,应用于根据给定资源地址返回对应资源(Resource)
->DefaultResourceLoader:ResourceLoader接口的默认实现。
->AbstractApplicationContext
//
->public void refresh();
->AbstractRefreshableApplicationContext
*刷新上下文
*如果之前存在 bean工厂,关闭以前的bean工厂 (destroyBeans() | closeBeanFactory())
*为上下文生命周期的下一阶段初始化一个新鲜的bean工厂。
->protected final void refreshBeanFactory()
->DefaultListableBeanFactory beanFactory = createBeanFactory(); 然后创建一个全新的 BeanFactory
->protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
->AbstractXmlApplicationContext
*通过 XmlBeanDefinitionReader 加载定义好的 Bean
->protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
->AbstractRefreshableConfigApplicationContext
*以init-param风格设置此应用程序上下文的配置位置,
*即用不同的位置用逗号,分号或空格分开。
*<p>如果没有设置,则实现可以使用默认值。
->public void setConfigLocations(String... locations)
->AbstractBeanDefinitionRead:实现下面俩个接口
->BeanDefinitionReader:资源转换 BeanDefinition 的各个功能
->EnvironmentCapable:获取 Environment 方法
->DocumentLoader:从资源文件加载到转换为 Document 功能
—>BeanDefinitionDocumentRead:读取Document并注册 BeanDefinition
->BeanDefinitionParserDelegate:解析 Element 各种方法
//根据 bean元素的属性初始化的bean定义
//解析 Element(比如 <bean />) 会设置 scope lazy-init 等 ,
//默认属性参考“DocumentDefaultsDefinition”
->public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, StringbeanName,BeanDefinition containingBean, AbstractBeanDefinition bd);
-> 继承AbstractAutowireCapableBeanFactory :综合 AbstractBeanFactory 并对接口 Autowire CapableBeanFactory 进行实现
// 确定指定 bean 的目标类型
->protected Class<?> determineTargetType(String beanName,RootBeanDefinition mbd, Class<?>... typesToMatch)
/**
* 使用“深拷贝”来拷贝 bean工厂中正常运行的bean 目的是防止因直接修改“引用”而导致 bean工厂中维护的 bean对象被修改
* @param beanName 为了获得更准确的异常信息而传递的bean名称
* @param mbd 合并后的bean
* @param bw 使用 BeanWrapper 包装目标对象 bw.setPropertyValues(newMutablePropertyValues(deepCopy));
* @param pvs 新的属性值
*/
->protected void applyPropertyValues(String beanName, BeanDefinition mbd,BeanWrapper bw, PropertyValues pvs)
/**
* 使用合适的实例化策略来构建指定的 bean(工厂方法 | 构造函数 | 自动装配)
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
* @see #instantiateBean
*/
->protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinitionmbd, Object[] args);
// 使用 BeanWrapper 实例化 bean 定义的属性值
->protected void populateBean(String beanName, RootBeanDefinition mbd,BeanWrapper bw)
|
|--->PropertyValues pvs = mbd.getPropertyValues(); 拿到 bean 中所有 <property name="id" value="1"/> 的 Key 与 Value
-> 实现ConfigurableListableBeanFactory 接口
-> 实现 BeanDefinitionRegistry 接口
1、在spring同一个配置文件中,不能存在id相同的两个bean,否则会报错。
2、在两个不同的spring配置文件中,可以存在id相同的两个bean,启动时,不会报错。这是因为spring ioc容器在加载bean的过程中,
类 DefaultListableBeanFactory 会对id相同的bean进行处理:后加载的配置文件的bean,覆盖先加载的配置文件的bean。
DefaultListableBeanFactory类中,有个属性allowBeanDefinitionOverriding,默认值为true,该值就是用来指定出现两个bean的id相同的情况下,如何进行处理。如果该值为false,则不会进行覆盖,而是抛出异常。
=>DefaultListableBeanFactory
// 获取 Bean 类型的名称、比如是否为 FactoryBean
->private String[] doGetBeanNamesForType(ResolvableType type, booleanincludeNonSingletons, boolean allowEagerInit);
AliasRegistry :定义对 alias 的简单增删改操作
->SimpleAliasRegistry:`AliasRegistry`接口的实现,使用Map缓存alias
//@param name 用户指定的名称
//@return 被转换的名字
->public String canonicalName(String name) 别名解析 : 根据原始名称,将别名解析为规范名称。
SingletonBeanRegistry:单例Bean容器(注册/获取)
-> DefaultSingletonBeanRegistry:`SingletonBeanRegistry`的默认实现
/**根据 beanName 返回指定 bean 的单例对象,如果不存在返回 null
*/
->protected Object getSingleton(String beanName, boolean allowEarlyReference)
BeanFactory:Bean的相关属性
->HierarchicalBeanFactory:继承 BeanFactory ,在其基础之上增加了对 parentFactory 的支持
BeanDefinition:
->BeanDefinitionRegistry:定义对 BeanDefinition 的相关操作
FactoryBeanRegistrySupport:在DefaultSinglentBeanRegistry基础上增加了 FactoryBean 的特殊处理
ConfigurableBeanFactory:提供配置 BeanFactory 的各种方法
ListableBeanFactory:根据条件获取 Bean的配置清单
AbstractBeanFactory:综合 FactoryBeanRegistrySupport 和 ConfigurableListableBeanFactory 的功能
解析Bean以及将它存储在 mergedBeanDefinitions 中缓存起来
->protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throwsBeansException
初始化自定义的PropertyEditorRegistry
->protected void registerCustomEditors(PropertyEditorRegistry registry)
*将指定的 bean 添加到该工厂中的一次性bean的列表中,
*注册其DisposableBean接口和/或给定的销毁方法
*在工厂关机时被调用(如适用)。只适用于单例对象。
->protected void registerDisposableBeanIfNecessary(String beanName, Object bean,RootBeanDefinition mbd)
->protected RootBeanDefinition getMergedBeanDefinition(String beanName,BeanDefinition bd, BeanDefinition containingBd) throwsBeanDefinitionStoreException
-> 默认 RootBeanDefinition mbd = null;
-> 判断了Bean是否存在, 缓存(mergedBeanDefinitions)存在则从缓存中直接提取
if(containingBd == null) {
mbd= this.mergedBeanDefinitions.get(beanName);
}
->单例分配| | 由于 <bean id="person" class="com.battcn.bean.Person"/> 并未指定scope那么提取系统默认的RootBeanDefinition.SCOPE_SINGLETON值
if(!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
}
->SimpleInstantiationStrategy:在BeanFactory中使用的简单对象实例化策略。尽管它提供了子类的钩子以覆盖添加方法注入支持,例如通过覆盖方法。但是不支持方法注入
// 在此处通过 BeanUtils.instantiateClass(constructorToUse); 反射实例化出对象
// public Person() {
// System.out.println("init");
// }
// 在调用完 BeanUtils.instantiateClass(constructorToUse); 后就可以看到日志输出的 init
-> publicObject instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner);
Spring
-> lazy-init="default | true | false"
当我们使用lazy-init = "default"作为元素中的一个属性时,容器拾取由元素的default-lazy-init ="true | false"属性指定的值,并将其用作lazy-init ="true | false"。
如果元素中不存在default-lazy-init 属性,则元素中的lazy-init =“default” 的行为就像lazy-init-“false” 一样。
结合 scope = "singleton" 可以理解为懒汉单例模式与饿汉单例模式区别
Spring 的Bean默认单例
-> scope="singleton |prototype"默认 singleton = 单例 prototype = 多实例