最近看了一下Spring源码加载的简装版本,为了更好的理解,所以在绘图的基础上,进行了一些总结。(图画是为了理解和便于记忆Spring架构)

Spring的核心是IOC(控制反转)和AOP(面向切面编程),首先我们先一步一步的来了解IOC的实现:

一:首先是第一个模型:Model1:

     种子 =  BeanDefinition        工厂=BeanFactory

1、此处我们可以看见两个对象 BeanDefinition和BeanFactory,此处把创建对象的权限交给了BeanFactory,现在我们可以看到IOC的雏形,即把创建对象的权利交给了工厂。

public class BeanDefinition {

    private Object bean;

    public BeanDefinition(Object bean) {
this.bean = bean;
} public Object getBean() {
return bean;
} }
public class BeanFactory {

    private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();

    public Object getBean(String name) {
return beanDefinitionMap.get(name).getBean();
} public void registerBeanDefinition(String name, BeanDefinition beanDefinition) {
beanDefinitionMap.put(name, beanDefinition);
} }

二:接下來我們看第二个模型,对BeanFactory进行扩展

     1、此处的BeanDefinition 进行了扩展字段,可以看做是种子有了 3 片叶子,便于记忆,分别是 :

Object -> bean     Class ->beanClass   String ->beanClassName

2、此处的BeanFactory有了解耦的思想,使用了接口和抽象类

public class BeanDefinition {

    private Object bean;

    private Class beanClass;

    private String beanClassName;

    public BeanDefinition() {
} public void setBean(Object bean) {
this.bean = bean;
} public Class getBeanClass() {
return beanClass;
} public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
} public String getBeanClassName() {
return beanClassName;
} public void setBeanClassName(String beanClassName) {
this.beanClassName = beanClassName;
try {
this.beanClass = Class.forName(beanClassName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} public Object getBean() {
return bean;
} }
public interface BeanFactory {

    Object getBean(String name);

    void registerBeanDefinition(String name, BeanDefinition beanDefinition);
}

此处 BeanFactory定义了获取Bean 和注册Bean的方法

public abstract class AbstractBeanFactory implements BeanFactory {

    private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();

    @Override
public Object getBean(String name) {
return beanDefinitionMap.get(name).getBean();
} @Override
public void registerBeanDefinition(String name, BeanDefinition beanDefinition) {
Object bean = doCreateBean(beanDefinition);
beanDefinition.setBean(bean);
beanDefinitionMap.put(name, beanDefinition);
} /**
* 初始化bean
* @param beanDefinition
* @return
*/
protected abstract Object doCreateBean(BeanDefinition beanDefinition); }

此处实现了getBean 和registerBean的方法;另外声明了 doCreateBean的抽象方法;

public class AutowireCapableBeanFactory extends AbstractBeanFactory {

    @Override
protected Object doCreateBean(BeanDefinition beanDefinition) {
try {
Object bean = beanDefinition.getBeanClass().newInstance();
return bean;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}

最后实现类通过反射的方式,创建bean;并注册到工厂里,以便调用。

三:接下来继续完善,查看第三个模型:

  1、此处 BeanDefiniton多了一个自定义的属性 propertyValues,便于属性的注入,BeanFactory方法也有所改变

1、BeanDefinition类的定义

public class BeanDefinition {

    private Object bean;

    private Class beanClass;

    private String beanClassName;

    private PropertyValues propertyValues;

    public BeanDefinition() {
} public void setBean(Object bean) {
this.bean = bean;
} public Class getBeanClass() {
return beanClass;
} public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
} public String getBeanClassName() {
return beanClassName;
} public void setBeanClassName(String beanClassName) {
this.beanClassName = beanClassName;
try {
this.beanClass = Class.forName(beanClassName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} public Object getBean() {
return bean;
} public PropertyValues getPropertyValues() {
return propertyValues;
} public void setPropertyValues(PropertyValues propertyValues) {
this.propertyValues = propertyValues;
}
}
/**
* 用于bean的属性注入
* @author yihua.huang@dianping.com
*/
public class PropertyValue { private final String name; private final Object value; public PropertyValue(String name, Object value) {
this.name = name;
this.value = value;
} public String getName() {
return name;
} public Object getValue() {
return value;
}
}
import java.util.ArrayList;
import java.util.List; /**
* 包装一个对象所有的PropertyValue。<br/>
* 为什么封装而不是直接用List?因为可以封装一些操作。
* @author yihua.huang@dianping.com
*/
public class PropertyValues { private final List<PropertyValue> propertyValueList = new ArrayList<PropertyValue>(); public PropertyValues() {
} public void addPropertyValue(PropertyValue pv) {
//TODO:这里可以对于重复propertyName进行判断,直接用list没法做到
this.propertyValueList.add(pv);
} public List<PropertyValue> getPropertyValues() {
return this.propertyValueList;
} }

2、BeanFactory的定义

/**
* bean的容器
* @author yihua.huang@dianping.com
*/
public interface BeanFactory { Object getBean(String name); void registerBeanDefinition(String name, BeanDefinition beanDefinition) throws Exception;
}
/**
* @author yihua.huang@dianping.com
*/
public abstract class AbstractBeanFactory implements BeanFactory { private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(); @Override
public Object getBean(String name) {
return beanDefinitionMap.get(name).getBean();
} @Override
public void registerBeanDefinition(String name, BeanDefinition beanDefinition) throws Exception {
Object bean = doCreateBean(beanDefinition);
beanDefinition.setBean(bean);
beanDefinitionMap.put(name, beanDefinition);
} /**
* 初始化bean
* @param beanDefinition
* @return
*/
protected abstract Object doCreateBean(BeanDefinition beanDefinition) throws Exception; }
/**
* 可自动装配内容的BeanFactory
*
* @author yihua.huang@dianping.com
*/
public class AutowireCapableBeanFactory extends AbstractBeanFactory { @Override
protected Object doCreateBean(BeanDefinition beanDefinition) throws Exception {
Object bean = createBeanInstance(beanDefinition);
applyPropertyValues(bean, beanDefinition);
return bean;
} protected Object createBeanInstance(BeanDefinition beanDefinition) throws Exception {
return beanDefinition.getBeanClass().newInstance();
} protected void applyPropertyValues(Object bean, BeanDefinition mbd) throws Exception {
for (PropertyValue propertyValue : mbd.getPropertyValues().getPropertyValues()) {
Field declaredField = bean.getClass().getDeclaredField(propertyValue.getName());
declaredField.setAccessible(true);
declaredField.set(bean, propertyValue.getValue());
}
}
}

此处增加了添加 属性的方法 applyPropertyValues;

此模型可概括为:

#1.step1-最基本的容器
*step-1-container-register-and-get*

单纯的map,有get和put bean的功能

# 2.step2-将bean创建放入工厂
*step-2-abstract-beanfactory-and-do-bean-initilizing-in-it*

1. 抽象beanfactory
2. 将bean初始化放入beanfactory

# 2.step3-为bean注入属性
*step-3-inject-bean-with-property*

4、接下来我们来看第四个模型,Spring是如何实现读取配置文件的bean属性的,Model4:

从图中可以看出多了几个模块,现在分别来介绍一下:

1、BD 是简化绘制版的 BeanDefiniton

2、UR 对应下面 IO类,用于读取xml文件

RL  是ResourceLoader,用于配置文件路径

3、BDR 是用来解析XML文件的模块类

4、最后交由BeanFactory创造bean,并提供bean.

1、BeanDefinition

BeanDefiniton

/**
* bean的内容及元数据,保存在BeanFactory中,包装bean的实体
*
* @author yihua.huang@dianping.com
*/
public class BeanDefinition { private Object bean; private Class beanClass; private String beanClassName; private PropertyValues propertyValues = new PropertyValues(); public BeanDefinition() {
} public void setBean(Object bean) {
this.bean = bean;
} public Class getBeanClass() {
return beanClass;
} public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
} public String getBeanClassName() {
return beanClassName;
} public void setBeanClassName(String beanClassName) {
this.beanClassName = beanClassName;
try {
this.beanClass = Class.forName(beanClassName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} public Object getBean() {
return bean;
} public PropertyValues getPropertyValues() {
return propertyValues;
} public void setPropertyValues(PropertyValues propertyValues) {
this.propertyValues = propertyValues;
}

PropertyValue

/**
* 用于bean的属性注入
* @author yihua.huang@dianping.com
*/
public class PropertyValue { private final String name; private final Object value; public PropertyValue(String name, Object value) {
this.name = name;
this.value = value;
} public String getName() {
return name;
} public Object getValue() {
return value;
}
}

PropertyValues

/**
* 包装一个对象所有的PropertyValue。<br/>
* 为什么封装而不是直接用List?因为可以封装一些操作。
* @author yihua.huang@dianping.com
*/
public class PropertyValues { private final List<PropertyValue> propertyValueList = new ArrayList<PropertyValue>(); public PropertyValues() {
} public void addPropertyValue(PropertyValue pv) {
//TODO:这里可以对于重复propertyName进行判断,直接用list没法做到
this.propertyValueList.add(pv);
} public List<PropertyValue> getPropertyValues() {
return this.propertyValueList;
} }

2、IO类

Resource

/**
* Resource是spring内部定位资源的接口。
* @author yihua.huang@dianping.com
*/
public interface Resource { InputStream getInputStream() throws IOException;
}
/**
* @author yihua.huang@dianping.com
*/
public class UrlResource implements Resource { private final URL url; public UrlResource(URL url) {
this.url = url;
} @Override
public InputStream getInputStream() throws IOException{
URLConnection urlConnection = url.openConnection();
urlConnection.connect();
return urlConnection.getInputStream();
}
}

ResourceLoader

/**
* @author yihua.huang@dianping.com
*/
public class ResourceLoader { public Resource getResource(String location){
URL resource = this.getClass().getClassLoader().getResource(location);
return new UrlResource(resource);
}
}

3、BeanDefinitionReader

/**
* 从配置中读取BeanDefinitionReader
* @author yihua.huang@dianping.com
*/
public interface BeanDefinitionReader { void loadBeanDefinitions(String location) throws Exception;
}
/**
* 从配置中读取BeanDefinitionReader
*
* @author yihua.huang@dianping.com
*/
public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader { private Map<String,BeanDefinition> registry; private ResourceLoader resourceLoader; protected AbstractBeanDefinitionReader(ResourceLoader resourceLoader) {
this.registry = new HashMap<String, BeanDefinition>();
this.resourceLoader = resourceLoader;
} public Map<String, BeanDefinition> getRegistry() {
return registry;
} public ResourceLoader getResourceLoader() {
return resourceLoader;
}
}

XmlBeanDefinitionReader

/**
* @author yihua.huang@dianping.com
*/
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader { public XmlBeanDefinitionReader(ResourceLoader resourceLoader) {
super(resourceLoader);
} @Override
public void loadBeanDefinitions(String location) throws Exception {
InputStream inputStream = getResourceLoader().getResource(location).getInputStream();
doLoadBeanDefinitions(inputStream);
} protected void doLoadBeanDefinitions(InputStream inputStream) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = factory.newDocumentBuilder();
Document doc = docBuilder.parse(inputStream);
// 解析bean
registerBeanDefinitions(doc);
inputStream.close();
} public void registerBeanDefinitions(Document doc) {
Element root = doc.getDocumentElement(); parseBeanDefinitions(root);
} protected void parseBeanDefinitions(Element root) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
processBeanDefinition(ele);
}
}
} protected void processBeanDefinition(Element ele) {
String name = ele.getAttribute("name");
String className = ele.getAttribute("class");
BeanDefinition beanDefinition = new BeanDefinition();
processProperty(ele,beanDefinition);
beanDefinition.setBeanClassName(className);
getRegistry().put(name, beanDefinition);
} private void processProperty(Element ele,BeanDefinition beanDefinition) {
NodeList propertyNode = ele.getElementsByTagName("property");
for (int i = 0; i < propertyNode.getLength(); i++) {
Node node = propertyNode.item(i);
if (node instanceof Element) {
Element propertyEle = (Element) node;
String name = propertyEle.getAttribute("name");
String value = propertyEle.getAttribute("value");
beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name,value));
}
}
}
}

此文件用来定义文名,并解析xml文件

未完,待续 。。。。。。

Spring源码加载过程图解(一)的更多相关文章

  1. Spring源码加载BeanDefinition过程

    本文主要讲解Spring加载xml配置文件的方式,跟踪加载BeanDefinition的全过程. 源码分析 源码的入口 ClassPathXmlApplicationContext构造函数 new C ...

  2. Spring源码-加载和IOC部分

    源代码和注释放在了github上,包括加载过程的注释和getBean部分的 地址: https://github.com/lvxingzhi/spring-framework-4.3.9-note.g ...

  3. 工厂模式模拟Spring的bean加载过程

    一.前言    在日常的开发过程,经常使用或碰到的设计模式有代理.工厂.单例.反射模式等等.下面就对工厂模式模拟spring的bean加载过程进行解析,如果对工厂模式不熟悉的,具体可以先去学习一下工厂 ...

  4. Spring Bean 的加载过程

    Spring Bean 的加载过程 一个是populateBean,一个是initializeBean,这两个方法完成了bean的赋值与初始化. 这里有一个BeanDefinitionValueRes ...

  5. Spring源码:Spring IoC容器加载过程(1)

    Spring源码版本:4.3.23.RELEASE 一.加载过程概览 Spring容器加载过程可以在org.springframework.context.support.AbstractApplic ...

  6. Spring源码:Spring IoC容器加载过程(2)

    Spring源码版本:4.3.23.RELEASE 一.加载XML配置 通过XML配置创建Spring,创建入口是使用org.springframework.context.support.Class ...

  7. Spring IOC bean加载过程

    首先我们不要在学习Spring的开始产生畏难情绪.Spring没有臆想的那么高深,相反,它帮我们再项目开发中制定项目框架,简化项目开发.它的主要功能是将项目开发中繁琐的过程流程化,模式化,使用户仅在固 ...

  8. 【学习底层原理系列】重读spring源码3-加载beanDefinition的方法obtainFreshBeanFactory

    obtainFreshBeanFactory()方法概述 定义BeanFactory,并加载以下两种bean的定义,装配到BeanFactory: 1.配置文件中定义的bean 2.通过<con ...

  9. spring的BeanFactory加载过程

    ApplicationContext spring = new ClassPathXmlApplicationContext("classpath*:spring/applicationCo ...

随机推荐

  1. Uncaught TypeError: Cannot read property 'ownerDocument' of null

    /********************************************************************* * Uncaught TypeError: Cannot ...

  2. xz文件的解压缩

    前情 偶然发现了一个新的压缩文件类型 .xz 解决 其实很简单 xz -d ***.xz之后文件将会变为tar后缀 tar xvf ***.tar即可 另外 tar解压缩的时候,j代表bzip2,z代 ...

  3. 【机器学习】集成学习之sklearn中的xgboost基本用法

    原创博文,转载请注明出处!本文代码的github地址    博客索引地址 1.数据集 数据集使用sklearn自带的手写数字识别数据集mnist,通过函数datasets导入.mnist共1797个样 ...

  4. Centos kvm+ceph

    Centos kvm+ceph 一. centos6.5 安装kvm 1. disable selinux 2. 确认支持intel虚拟化 3. 安装需要的包 4.设置桥接网络 5.运行kvm ins ...

  5. BZOJ1412 ZJOI2009 狼和羊的故事 【网络流-最小割】

    BZOJ1412 ZJOI2009 狼和羊的故事 Description “狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和 ...

  6. python(十二):网络编程之ISO/OSI模型

    互联网(Internet)是依据操作系统,在计算机硬件的基础上建立起的通讯机制.它依赖于TCP/IP协议栈. 一.ISO/OSI模型 1.ISO七层模型与OSI五层模型 它们将计算机抽象成了具有层级关 ...

  7. sublime自动格式化代码插件HTML-CSS-JS Prettify安装

    sublime自动格式化代码插件HTML-CSS-JS Prettify安装 问题: 用 Sublime Text 格式化代码(安装 HTML-CSS-JS Prettify 插件)时,格式化时却会提 ...

  8. SQL Server 2008 R2占用内存越来越大解决方法

    最近开发sql server数据库项目的过程中发现了这么一个问题,后台网站内存占用95%,通过任务管理器查看占内存的进程sqlserver.exe,是因为SQL Server 2008 R2运行越久, ...

  9. WPF自适应可关闭的TabControl 类似浏览器的标签页(转)

    效果如图: 虽然说是自适应可关闭的TabControl,但TabControl并不需要改动,不如叫自适应可关闭的TabItem. 大体思路:建一个用户控件,继承自TabItem,里面放个按钮,点击的时 ...

  10. 洛谷【P4551】最长异或路径

    浅谈\(Trie\):https://www.cnblogs.com/AKMer/p/10444829.html 题目传送门:https://www.luogu.org/problemnew/show ...