1.BeanFactory:实现ioc容器的最基本形式。
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String var1) throws BeansException;指定名字的bean

<T> T getBean(String var1, Class<T> var2) throws BeansException;

<T> T getBean(Class<T> var1) throws BeansException;byType

Object getBean(String var1, Object... var2) throws BeansException;

<T> T getBean(Class<T> var1, Object... var2) throws BeansException;

boolean containsBean(String var1);是否包含指定名字的bean

boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
是否为单例bean
boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
是否为原型bean
boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;
查询指定名字的bean的class类型是否是特定的Class类型
boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
获取指定名字bean的Class类型
String[] getAliases(String var1);获取指定名字bean的所有别名
XmlBeanFactory:
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader;

public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, (BeanFactory)null);
}
BeanDefination来源在resource里,
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader = new XmlBeanDefinitionReader(this);
this.reader.loadBeanDefinitions(resource);
}
}
编程式使用Ioc容器
ClassPathResource res = new ClassPathResource("/applicationContext-core.xml");
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(res);
1.1Ioc容器的初始化是调用refresh()方法来启动的,
这个启动包括三个过程:1.BeanDefination的Resource定位2.载入3.注册
1).Resource定位:指的是BeanDefination的资源定位,寻找数据的过程。由ReaourceLoader通过统一的Resource接口来完成。
2).BeanDefination的载入。载入过程就是把用户定义好的Bean表示成Ioc容器内部的数据结构,而这个数据结构就是BeanDefination.
3).向Ioc容器注册这些BeanDefination的过程。这个过程是通过调用BeanDefinatinRegistry接口的实现来完成的。是把载入过程中的BeanDefination向Ioc容器进行注册,在Ioc容器内部将BeanDefination注入到一个HashMap里,Ioc容器就是通过这个HashMap持有这些BeanDefination数据。

载入和依赖注入区别:
依赖注入一般发生在应用第一次通过getBean向容器索取bean的时候,但是有一个例外就是可以对Bean设置lazyinit属性来完成bean的依赖注入,使其在初始化阶段就完成了。而不必要等到整个初始化完成以后,第一次getBean时才出发。
1.2 BeanDefiantion的Resource定位。
在ApplicationContext中Spring已经为我们提供了一系列加载不同Resource的读取器的实现,比如FileSystemXmlApplicationContext,ClassPathXmlApplicationContext,Xml
WebApplicationContext可以从文件系统,Class Path 或者web容器中载入Resource。

public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext {
public FileSystemXmlApplicationContext() {
}

public FileSystemXmlApplicationContext(ApplicationContext parent) {
super(parent);
}
//该构造函数的configLocation包含的是BeanDefination所在的文件路径
public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
this(new String[]{configLocation}, true, (ApplicationContext)null);
}
//该构造函数的configLocation包含多个BeanDefination所在的文件路径
public FileSystemXmlApplicationContext(String... configLocations) throws BeansException {
this(configLocations, true, (ApplicationContext)null);
}
//指定自己的双亲Ioc容器
public FileSystemXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException {
this(configLocations, true, parent);
}

public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
this(configLocations, refresh, (ApplicationContext)null);
}
//调用refresh方法启动了BeanDefination的载入过程
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
super(parent);
this.setConfigLocations(configLocations);
if(refresh) {
this.refresh();
}

}

protected Resource getResourceByPath(String path) {
if(path != null && path.startsWith("/")) {
path = path.substring(1);
}

return new FileSystemResource(path);
}
}
1.3BeanDefination的载入和解析
载入过程:把定义的BeanDefination在Ioc容器中转换为一个Spring内部表示的数据结构的过程,这些BeanDefination数据在Ioc容器中通过一个HashMap来维护和保持。
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
super(parent);
this.setConfigLocations(configLocations);
//这里调用容器的refresh,是载入BeanDefination的入口
if(refresh) {
this.refresh();
}
}
容器的启动设计的很重要的方法refresh,在AbstractApplicationContext里,详细描述了ApplicationContext初始化的过程,比如BeanFactory的更新,MessageSource和PostProcessor的注册等等。
public void refresh() throws BeansException, IllegalStateException {
Object var1 = this.startupShutdownMonitor;
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
//设置BeanFactory的后置处理
this.postProcessBeanFactory(beanFactory);
//调用BeanFactory的后处理器
this.invokeBeanFactoryPostProcessors(beanFactory);
//注册Bean的后置处理器,在Bean创建过程中调用
this.registerBeanPostProcessors(beanFactory);
//对上下文的消息源进行初始化
this.initMessageSource();
//初始化上下文事件机制
this.initApplicationEventMulticaster();
//初始化其他的特殊Bean
this.onRefresh();
//检查监听Bean并且把这些Bean向容器注册
this.registerListeners();
//实例化所有的non-lazy-init的单件
this.finishBeanFactoryInitialization(beanFactory);
//发布容器时间,结束refresh过程
this.finishRefresh();
} catch (BeansException var9) {
if(this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
//为防止Baen资源占用,在异常处理中,销毁已经在前面生成的单件Bean
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
在refreshBeanFactory中,如果已经有容器存在则需要销毁和关闭。
不同形式的BeanDefination使用不同的BeanDefinationReader来完成数据的载入工作.
对于xml文件bean的property属性的解析,解析结果放到PropertyValue中,然后设置到BeanDefinationHolder中去。
1.4BeanDefination在Ioc容器中的注册
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
将解析得到的BeanDefination向Ioc容器的beanDefinationMap注册的过程是在载入BeanDefination完成后进行的。
首先DefaultListableBeanFactory实现了BeanDefinationRegistry接口,这个接口的实现完成了BeanDefination向容器的注册,注册过程不复杂,就是把BeanDefination设置到HashMap中去,需要注意的是,遇到同名的beanDefination需要允许覆盖。
注册BeanDefination过程
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
//获取beanName
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
String[] aliases = definitionHolder.getAliases();
if(aliases != null) {
String[] var4 = aliases;
int var5 = aliases.length;
//
for(int var6 = 0; var6 < var5; ++var6) {
String alias = var4[var6];
registry.registerAlias(beanName, alias);
}
}

}

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if(beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition)beanDefinition).validate();
} catch (BeanDefinitionValidationException var9) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var9);
}
}
BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
if(oldBeanDefinition != null) {
if(!this.isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound.");
}
if(oldBeanDefinition.getRole() < beanDefinition.getRole()) {
if(this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else if(!beanDefinition.equals(oldBeanDefinition)) {
if(this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else if(this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
this.beanDefinitionMap.put(beanName, beanDefinition);
} else {
if(this.hasBeanCreationStarted()) {
Map var4 = this.beanDefinitionMap;
synchronized(this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if(this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
} else {
//注册BeanDefination的过程,把beanName存到beanDefinitionNames的同时,把beanName作为Map的key,把BeanDefination做为value存到BeanDefinationMap中
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if(oldBeanDefinition != null || this.containsSingleton(beanName)) {
this.resetBeanDefinition(beanName);
}

Spring技术内幕阅读笔记(一)的更多相关文章

  1. spring 技术内幕读书笔记1

    1 在 java 应用开发中,往往会涉及复杂的对象耦合关系,在 代码中处理这些耦合关系,对代码的维护性和应用扩展性会带来许多不便.通过使用spring 的 IOC 容器,可以对这些耦合关系实现一个文本 ...

  2. 《Spring技术内幕》笔记-第二章 IoC容器的实现

    简单介绍 1,在Spring中,SpringIoC提供了一个主要的JavaBean容器.通过IoC模式管理依赖关系.并通过依赖注入和AOP切面增强了为JavaBean这样子的POJO提供事务管理,生命 ...

  3. 《Spring技术内幕》笔记-Spring的设计理念和总体架构

    1.Spring的主要子项目:     -1.Spring Framework(Core):Spring项目的核心.提供IoC,AOP,MVC等核心功能.     -2.Spring Web Flow ...

  4. 《Spring技术内幕》笔记-第四章 Spring MVC与web环境

    ​上下文在web容器中的启动 1,IoC容器的启动过程 IoC的启动过程就是建立上下文的过程.该上下文是与ServletContext相伴.在Spring中存在一个核心控制分发器,Dispatcher ...

  5. 《spring技术内幕》读书笔记(1)——什么是POJO模式

    今天在看<spring技术内幕>,第一章中多次提到了使用POJO来完成开发,就百度了一下,在此保留 1.     什么是POJO POJO的名称有多种,pure old java obje ...

  6. Spring源码阅读笔记

    前言 作为一个Java开发者,工作了几年后,越发觉力有点不从心了,技术的世界实在是太过于辽阔了,接触的东西越多,越感到前所未有的恐慌. 每天捣鼓这个捣鼓那个,结果回过头来,才发现这个也不通,那个也不精 ...

  7. 【转】COM技术内幕(笔记)

    COM技术内幕(笔记) COM--到底是什么?--COM标准的要点介绍,它被设计用来解决什么问题?基本元素的定义--COM术语以及这些术语的含义.使用和处理COM对象--如何创建.使用和销毁COM对象 ...

  8. Spring技术内幕:SpringIOC原理学习总结

    前一段时候我把Spring技术内幕的关于IOC原理一章看完,感觉代码太多,不好掌握,我特意又各方搜集了一些关于IOC原理的资料,特加深一下印象,以便真正掌握IOC的原理. IOC的思想是:Spring ...

  9. Spring技术内幕:设计理念和整体架构概述(转)

    程序员都很崇拜技术大神,很大一部分是因为他们发现和解决问题的能力,特别是线上出现紧急问题时,总是能够快速定位和解决. 一方面,他们有深厚的技术基础,对应用的技术知其所以然,另一方面,在采坑的过程中不断 ...

随机推荐

  1. 吴恩达《Machine Learning Yearning》总结(31-40章)

    31.解读学习曲线:其他情况 下图反映了高方差,通过增加数据集可以改善. 下图反映了高偏差和高方差,需要找到一种方法来同时减少方差和偏差. 32.绘制学习曲线 情况:当数据集非常小时,比如只有100个 ...

  2. model操作涉及的所有字段(API)

    一旦 数据模型 创建完毕, 自然会有存取数据的需要.本文档介绍了由 models 衍生而来的数据库抽象API,及如何创建,得到及更新对象. 贯穿本参考, 我们都会引用下面的民意测验(Poll)应用程序 ...

  3. 《Python编程从入门到实践》_第七章_用户输入和whlie循环

    函数input()的工作原理 函数input()让程序暂停运行,等待用户输入一些文本.获取用户输入后,python将其存储在一个变量中,以方便你使用. #输入用户名 username = input( ...

  4. 关于两个 IQueryable 合并

    原先根据需求要对数据进行两种筛选,起初写过滤条件,但是过滤后发现有的数据重叠.因此改为查询两次. 因为查询后返回的是两个相同的.匿名的 IQueryable ,最终的目的是想两个 类型结合成一个. 参 ...

  5. 人民币金额大小写Js转换

    /** * 数字转中文 * @param dValue * @returns */ function chineseNumber(dValue) { var maxDec = 2; // 验证输入金额 ...

  6. 05.if结构

    分支结构:if  if-else 选择结构:if else-if switch-case 循环结构:while do-while for foreach if语句 语法: if(判断条件) { //要 ...

  7. mysql无法连接Can't create a new thread (errno 11)

    问题描述: 今天本地navicat连接服务器mysql出错 ,提示ERROR 1135: Can't create a new thread (errno 11); if you are not ou ...

  8. scss-@media

    首先回顾下css3中的@media 定义和使用: 使用 @media 查询,你可以针对不同的媒体类型定义不同的样式. @media 可以针对不同的屏幕尺寸设置不同的样式,特别是如果你需要设置设计响应式 ...

  9. vuejs+axios发送请求

    Vue 原本有一个官方推荐的 ajax 插件 vue-resource,但是自从 Vue 更新到 2.0 之后,官方就不再更新 vue-resource 目前主流的 Vue 项目,都选择 axios  ...

  10. .NET开源工作流RoadFlow-表单设计-数据表格

    数据表格即在表单中显示一个table,该table数据可以来自任意自定义的来源: 数据类型:指定表格的数据源类型 1.datatable,即.net中的System.Data.DataTable 2. ...