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. Linux Kernel文件系统写I/O流程代码分析(一)

    Linux Kernel文件系统写I/O流程代码分析(一) 在Linux VFS机制简析(二)这篇博客上介绍了struct address_space_operations里底层文件系统需要实现的操作 ...

  2. ul+js模拟select+改进

    html: <div class="select_box"> <input type="text" value="还款方式" ...

  3. POST 还是 GET?

    POST 还是 GET? 浏览器使用 method 属性设置的方法将表单中的数据传送给服务器进行处理.共有两种方法:POST 方法和 GET 方法. 如果采用 POST 方法,浏览器将会按照下面两步来 ...

  4. 深入理解JavaScript系列(34):设计模式之命令模式

    介绍 命令模式(Command)的定义是:用于将一个请求封装成一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或者记录请求日志,以及执行可撤销的操作.也就是说改模式旨在将函数的调用.请求和 ...

  5. Dictionary集合 字典

    1 Dictionary<int, string> dic = new Dictionary<int, string>(); dic.Add(,"张三"); ...

  6. vba SpecialCells(Type,Value) 参数说明

    Range.SpecialCells 方法可以返回一个 Range 对象,该对象代表与指定类型和值匹配的所有单元格. 其语法如下: 表达式.SpecialCells(Type,Value) 其Type ...

  7. Java开发高性能网站需要关注的事

    转自:http://www.javabloger.com/java-development-concern-those-things/ 近期各家IT媒体举办的业内技术大会让很多网站都在披露自己的技术内 ...

  8. Android 时间范围选择器PickTimeDialog

    个人提供了自己封装的第三方时间选择器,能够自定义时间格式,以及设置时间范围. 基础使用 PickTimeDialog pickDilog= new PickTimeDialog(this).setMa ...

  9. java 理解有符号数和无符号数

    转至:http://jinguo.iteye.com/blog/212049 理解有符号数和无符号数负数在计算机中如何表示呢? 这一点,你可能听过两种不同的回答. 一种是教科书,它会告诉你:计算机用“ ...

  10. 浅谈SQL Server中的事务日志(三)----在简单恢复模式下日志的角色

    简介 在简单恢复模式下,日志文件的作用仅仅是保证了SQL Server事务的ACID属性.并不承担具体的恢复数据的角色.正如”简单”这个词的字面意思一样,数据的备份和恢复仅仅是依赖于手动备份和恢复.在 ...