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. bzoj 5329: [Sdoi2018]战略游戏

    Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着 ...

  2. java生产者,消费者

    有很多实现的方法 使用blockingqueue实现 demo import java.util.concurrent.LinkedBlockingQueue; /** * Created by 58 ...

  3. ECharts动态数据加载

    最近有用到ECharts做可视化报表,小结一下 一.准备数据 1.官网下载echarts.min.js 2.引入jquery.js 3.请求用的json数据 { "list":[ ...

  4. html和css命名-望文生义

    HTML+CSS命名规则 在一个内容较多的HTML页面中,需要设计许多不同的框架,再为这些不同的框架及内容进行分类,给予相应的名称,从而使得网页结构更加清晰,也为工作提供了方便.许多新手朋友在设计一个 ...

  5. 使用 iframe + postMessage 实现跨域通信

    在实际项目开发中可能会碰到在 a.com 页面中嵌套 b.com 页面,这时第一反应是使用 iframe,但是产品又提出在 a.com 中操作,b.com 中进行显示,或者相反. 1.postMess ...

  6. Stage3--Python控制流程及函数

    说在前面: Stage1-Stage4简单介绍一下Python语法,Stage5开始用python实现一些实际应用,语法的东西到处可以查看到,学习一门程序语言的最终目的是应用,而不是学习语法,语法本事 ...

  7. Zygote和System进程的启动过程

    ##init脚本的启动 +------------+ +-------+ +-----------+ |Linux Kernel+--> |init.rc+-> |app_process| ...

  8. 【起航计划ObjC 003】印第安老斑鸠ObjC的幻想 ---- ObjC经典问题

    1.Objective-C的类可以多重继承么?可以采用多个协议么? 答:不可以多重继承,可以采用多个协议. 2.#import和#include的区别是什么?#import<> 跟 #im ...

  9. SQL Server中的高可用性----复制

    在本系列文章的前两篇对高可用性的意义和单实例下的高可用性做了阐述.但是当随着数据量的增长,以及对RTO和RPO要求的严格,单实例已经无法满足HA/DR方面的要求,因此需要做多实例的高可用性.本文着重对 ...

  10. Selenium 2.0 以后不在必须Selenium server了

    does not require the Selenium Server to automate the browser.这个句话,解决了我很的疑惑,新版Selenium 可以直接操作浏览器了,还可以 ...