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

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

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

     种子 =  BeanDefinition        工厂=BeanFactory

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

  1. public class BeanDefinition {
  2.  
  3. private Object bean;
  4.  
  5. public BeanDefinition(Object bean) {
  6. this.bean = bean;
  7. }
  8.  
  9. public Object getBean() {
  10. return bean;
  11. }
  12.  
  13. }
  1. public class BeanFactory {
  2.  
  3. private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
  4.  
  5. public Object getBean(String name) {
  6. return beanDefinitionMap.get(name).getBean();
  7. }
  8.  
  9. public void registerBeanDefinition(String name, BeanDefinition beanDefinition) {
  10. beanDefinitionMap.put(name, beanDefinition);
  11. }
  12.  
  13. }

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

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

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

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

  1. public class BeanDefinition {
  2.  
  3. private Object bean;
  4.  
  5. private Class beanClass;
  6.  
  7. private String beanClassName;
  8.  
  9. public BeanDefinition() {
  10. }
  11.  
  12. public void setBean(Object bean) {
  13. this.bean = bean;
  14. }
  15.  
  16. public Class getBeanClass() {
  17. return beanClass;
  18. }
  19.  
  20. public void setBeanClass(Class beanClass) {
  21. this.beanClass = beanClass;
  22. }
  23.  
  24. public String getBeanClassName() {
  25. return beanClassName;
  26. }
  27.  
  28. public void setBeanClassName(String beanClassName) {
  29. this.beanClassName = beanClassName;
  30. try {
  31. this.beanClass = Class.forName(beanClassName);
  32. } catch (ClassNotFoundException e) {
  33. e.printStackTrace();
  34. }
  35. }
  36.  
  37. public Object getBean() {
  38. return bean;
  39. }
  40.  
  41. }
  1. public interface BeanFactory {
  2.  
  3. Object getBean(String name);
  4.  
  5. void registerBeanDefinition(String name, BeanDefinition beanDefinition);
  6. }

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

  1. public abstract class AbstractBeanFactory implements BeanFactory {
  2.  
  3. private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
  4.  
  5. @Override
  6. public Object getBean(String name) {
  7. return beanDefinitionMap.get(name).getBean();
  8. }
  9.  
  10. @Override
  11. public void registerBeanDefinition(String name, BeanDefinition beanDefinition) {
  12. Object bean = doCreateBean(beanDefinition);
  13. beanDefinition.setBean(bean);
  14. beanDefinitionMap.put(name, beanDefinition);
  15. }
  16.  
  17. /**
  18. * 初始化bean
  19. * @param beanDefinition
  20. * @return
  21. */
  22. protected abstract Object doCreateBean(BeanDefinition beanDefinition);
  23.  
  24. }

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

  1. public class AutowireCapableBeanFactory extends AbstractBeanFactory {
  2.  
  3. @Override
  4. protected Object doCreateBean(BeanDefinition beanDefinition) {
  5. try {
  6. Object bean = beanDefinition.getBeanClass().newInstance();
  7. return bean;
  8. } catch (InstantiationException e) {
  9. e.printStackTrace();
  10. } catch (IllegalAccessException e) {
  11. e.printStackTrace();
  12. }
  13. return null;
  14. }
  15. }

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

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

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

1、BeanDefinition类的定义

  1. public class BeanDefinition {
  2.  
  3. private Object bean;
  4.  
  5. private Class beanClass;
  6.  
  7. private String beanClassName;
  8.  
  9. private PropertyValues propertyValues;
  10.  
  11. public BeanDefinition() {
  12. }
  13.  
  14. public void setBean(Object bean) {
  15. this.bean = bean;
  16. }
  17.  
  18. public Class getBeanClass() {
  19. return beanClass;
  20. }
  21.  
  22. public void setBeanClass(Class beanClass) {
  23. this.beanClass = beanClass;
  24. }
  25.  
  26. public String getBeanClassName() {
  27. return beanClassName;
  28. }
  29.  
  30. public void setBeanClassName(String beanClassName) {
  31. this.beanClassName = beanClassName;
  32. try {
  33. this.beanClass = Class.forName(beanClassName);
  34. } catch (ClassNotFoundException e) {
  35. e.printStackTrace();
  36. }
  37. }
  38.  
  39. public Object getBean() {
  40. return bean;
  41. }
  42.  
  43. public PropertyValues getPropertyValues() {
  44. return propertyValues;
  45. }
  46.  
  47. public void setPropertyValues(PropertyValues propertyValues) {
  48. this.propertyValues = propertyValues;
  49. }
  50. }
  1. /**
  2. * 用于bean的属性注入
  3. * @author yihua.huang@dianping.com
  4. */
  5. public class PropertyValue {
  6.  
  7. private final String name;
  8.  
  9. private final Object value;
  10.  
  11. public PropertyValue(String name, Object value) {
  12. this.name = name;
  13. this.value = value;
  14. }
  15.  
  16. public String getName() {
  17. return name;
  18. }
  19.  
  20. public Object getValue() {
  21. return value;
  22. }
  23. }
  1. import java.util.ArrayList;
  2. import java.util.List;
  3.  
  4. /**
  5. * 包装一个对象所有的PropertyValue。<br/>
  6. * 为什么封装而不是直接用List?因为可以封装一些操作。
  7. * @author yihua.huang@dianping.com
  8. */
  9. public class PropertyValues {
  10.  
  11. private final List<PropertyValue> propertyValueList = new ArrayList<PropertyValue>();
  12.  
  13. public PropertyValues() {
  14. }
  15.  
  16. public void addPropertyValue(PropertyValue pv) {
  17. //TODO:这里可以对于重复propertyName进行判断,直接用list没法做到
  18. this.propertyValueList.add(pv);
  19. }
  20.  
  21. public List<PropertyValue> getPropertyValues() {
  22. return this.propertyValueList;
  23. }
  24.  
  25. }

2、BeanFactory的定义

  1. /**
  2. * bean的容器
  3. * @author yihua.huang@dianping.com
  4. */
  5. public interface BeanFactory {
  6.  
  7. Object getBean(String name);
  8.  
  9. void registerBeanDefinition(String name, BeanDefinition beanDefinition) throws Exception;
  10. }
  1. /**
  2. * @author yihua.huang@dianping.com
  3. */
  4. public abstract class AbstractBeanFactory implements BeanFactory {
  5.  
  6. private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
  7.  
  8. @Override
  9. public Object getBean(String name) {
  10. return beanDefinitionMap.get(name).getBean();
  11. }
  12.  
  13. @Override
  14. public void registerBeanDefinition(String name, BeanDefinition beanDefinition) throws Exception {
  15. Object bean = doCreateBean(beanDefinition);
  16. beanDefinition.setBean(bean);
  17. beanDefinitionMap.put(name, beanDefinition);
  18. }
  19.  
  20. /**
  21. * 初始化bean
  22. * @param beanDefinition
  23. * @return
  24. */
  25. protected abstract Object doCreateBean(BeanDefinition beanDefinition) throws Exception;
  26.  
  27. }
  1. /**
  2. * 可自动装配内容的BeanFactory
  3. *
  4. * @author yihua.huang@dianping.com
  5. */
  6. public class AutowireCapableBeanFactory extends AbstractBeanFactory {
  7.  
  8. @Override
  9. protected Object doCreateBean(BeanDefinition beanDefinition) throws Exception {
  10. Object bean = createBeanInstance(beanDefinition);
  11. applyPropertyValues(bean, beanDefinition);
  12. return bean;
  13. }
  14.  
  15. protected Object createBeanInstance(BeanDefinition beanDefinition) throws Exception {
  16. return beanDefinition.getBeanClass().newInstance();
  17. }
  18.  
  19. protected void applyPropertyValues(Object bean, BeanDefinition mbd) throws Exception {
  20. for (PropertyValue propertyValue : mbd.getPropertyValues().getPropertyValues()) {
  21. Field declaredField = bean.getClass().getDeclaredField(propertyValue.getName());
  22. declaredField.setAccessible(true);
  23. declaredField.set(bean, propertyValue.getValue());
  24. }
  25. }
  26. }

此处增加了添加 属性的方法 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

  1. /**
  2. * bean的内容及元数据,保存在BeanFactory中,包装bean的实体
  3. *
  4. * @author yihua.huang@dianping.com
  5. */
  6. public class BeanDefinition {
  7.  
  8. private Object bean;
  9.  
  10. private Class beanClass;
  11.  
  12. private String beanClassName;
  13.  
  14. private PropertyValues propertyValues = new PropertyValues();
  15.  
  16. public BeanDefinition() {
  17. }
  18.  
  19. public void setBean(Object bean) {
  20. this.bean = bean;
  21. }
  22.  
  23. public Class getBeanClass() {
  24. return beanClass;
  25. }
  26.  
  27. public void setBeanClass(Class beanClass) {
  28. this.beanClass = beanClass;
  29. }
  30.  
  31. public String getBeanClassName() {
  32. return beanClassName;
  33. }
  34.  
  35. public void setBeanClassName(String beanClassName) {
  36. this.beanClassName = beanClassName;
  37. try {
  38. this.beanClass = Class.forName(beanClassName);
  39. } catch (ClassNotFoundException e) {
  40. e.printStackTrace();
  41. }
  42. }
  43.  
  44. public Object getBean() {
  45. return bean;
  46. }
  47.  
  48. public PropertyValues getPropertyValues() {
  49. return propertyValues;
  50. }
  51.  
  52. public void setPropertyValues(PropertyValues propertyValues) {
  53. this.propertyValues = propertyValues;
  54. }

PropertyValue

  1. /**
  2. * 用于bean的属性注入
  3. * @author yihua.huang@dianping.com
  4. */
  5. public class PropertyValue {
  6.  
  7. private final String name;
  8.  
  9. private final Object value;
  10.  
  11. public PropertyValue(String name, Object value) {
  12. this.name = name;
  13. this.value = value;
  14. }
  15.  
  16. public String getName() {
  17. return name;
  18. }
  19.  
  20. public Object getValue() {
  21. return value;
  22. }
  23. }

PropertyValues

  1. /**
  2. * 包装一个对象所有的PropertyValue。<br/>
  3. * 为什么封装而不是直接用List?因为可以封装一些操作。
  4. * @author yihua.huang@dianping.com
  5. */
  6. public class PropertyValues {
  7.  
  8. private final List<PropertyValue> propertyValueList = new ArrayList<PropertyValue>();
  9.  
  10. public PropertyValues() {
  11. }
  12.  
  13. public void addPropertyValue(PropertyValue pv) {
  14. //TODO:这里可以对于重复propertyName进行判断,直接用list没法做到
  15. this.propertyValueList.add(pv);
  16. }
  17.  
  18. public List<PropertyValue> getPropertyValues() {
  19. return this.propertyValueList;
  20. }
  21.  
  22. }

2、IO类

Resource

  1. /**
  2. * Resource是spring内部定位资源的接口。
  3. * @author yihua.huang@dianping.com
  4. */
  5. public interface Resource {
  6.  
  7. InputStream getInputStream() throws IOException;
  8. }
  1. /**
  2. * @author yihua.huang@dianping.com
  3. */
  4. public class UrlResource implements Resource {
  5.  
  6. private final URL url;
  7.  
  8. public UrlResource(URL url) {
  9. this.url = url;
  10. }
  11.  
  12. @Override
  13. public InputStream getInputStream() throws IOException{
  14. URLConnection urlConnection = url.openConnection();
  15. urlConnection.connect();
  16. return urlConnection.getInputStream();
  17. }
  18. }

ResourceLoader

  1. /**
  2. * @author yihua.huang@dianping.com
  3. */
  4. public class ResourceLoader {
  5.  
  6. public Resource getResource(String location){
  7. URL resource = this.getClass().getClassLoader().getResource(location);
  8. return new UrlResource(resource);
  9. }
  10. }

3、BeanDefinitionReader

  1. /**
  2. * 从配置中读取BeanDefinitionReader
  3. * @author yihua.huang@dianping.com
  4. */
  5. public interface BeanDefinitionReader {
  6.  
  7. void loadBeanDefinitions(String location) throws Exception;
  8. }
  1. /**
  2. * 从配置中读取BeanDefinitionReader
  3. *
  4. * @author yihua.huang@dianping.com
  5. */
  6. public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader {
  7.  
  8. private Map<String,BeanDefinition> registry;
  9.  
  10. private ResourceLoader resourceLoader;
  11.  
  12. protected AbstractBeanDefinitionReader(ResourceLoader resourceLoader) {
  13. this.registry = new HashMap<String, BeanDefinition>();
  14. this.resourceLoader = resourceLoader;
  15. }
  16.  
  17. public Map<String, BeanDefinition> getRegistry() {
  18. return registry;
  19. }
  20.  
  21. public ResourceLoader getResourceLoader() {
  22. return resourceLoader;
  23. }
  24. }

XmlBeanDefinitionReader

  1. /**
  2. * @author yihua.huang@dianping.com
  3. */
  4. public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
  5.  
  6. public XmlBeanDefinitionReader(ResourceLoader resourceLoader) {
  7. super(resourceLoader);
  8. }
  9.  
  10. @Override
  11. public void loadBeanDefinitions(String location) throws Exception {
  12. InputStream inputStream = getResourceLoader().getResource(location).getInputStream();
  13. doLoadBeanDefinitions(inputStream);
  14. }
  15.  
  16. protected void doLoadBeanDefinitions(InputStream inputStream) throws Exception {
  17. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  18. DocumentBuilder docBuilder = factory.newDocumentBuilder();
  19. Document doc = docBuilder.parse(inputStream);
  20. // 解析bean
  21. registerBeanDefinitions(doc);
  22. inputStream.close();
  23. }
  24.  
  25. public void registerBeanDefinitions(Document doc) {
  26. Element root = doc.getDocumentElement();
  27.  
  28. parseBeanDefinitions(root);
  29. }
  30.  
  31. protected void parseBeanDefinitions(Element root) {
  32. NodeList nl = root.getChildNodes();
  33. for (int i = 0; i < nl.getLength(); i++) {
  34. Node node = nl.item(i);
  35. if (node instanceof Element) {
  36. Element ele = (Element) node;
  37. processBeanDefinition(ele);
  38. }
  39. }
  40. }
  41.  
  42. protected void processBeanDefinition(Element ele) {
  43. String name = ele.getAttribute("name");
  44. String className = ele.getAttribute("class");
  45. BeanDefinition beanDefinition = new BeanDefinition();
  46. processProperty(ele,beanDefinition);
  47. beanDefinition.setBeanClassName(className);
  48. getRegistry().put(name, beanDefinition);
  49. }
  50.  
  51. private void processProperty(Element ele,BeanDefinition beanDefinition) {
  52. NodeList propertyNode = ele.getElementsByTagName("property");
  53. for (int i = 0; i < propertyNode.getLength(); i++) {
  54. Node node = propertyNode.item(i);
  55. if (node instanceof Element) {
  56. Element propertyEle = (Element) node;
  57. String name = propertyEle.getAttribute("name");
  58. String value = propertyEle.getAttribute("value");
  59. beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name,value));
  60. }
  61. }
  62. }
  63. }

此文件用来定义文名,并解析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. 基于tensorflow的增强学习

    可以通过下面的连接查看这个项目工程: https://github.com/reinforceio/tensorforce 通过这遍文章来了这个项目的使用: https://reinforce.io/ ...

  2. Faster R-CNN改进篇(一): ION ● HyperNet ● MS CNN

    一. 源起于Faster 深度学习于目标检测的里程碑成果,来自于这篇论文: Ren, Shaoqing, et al. "Faster R-CNN: Towards real-time ob ...

  3. 密钥库文件格式[keystore]代码

    密钥库文件格式[keystore]代码 格式    :     JKS 扩展名  :      .jks/.ks 描述    :     [Java Keystore]密钥库的Java实现版本,pro ...

  4. caffe 一些网络参数

    caffe一些网络参数的:http://www.docin.com/p-871820919.html

  5. iOS内存管理(objective-c)

    移动app开发中,由于移动设备内存的限制,内存管理是一个非常重要的话题.objective-c的内存管理,不仅是面试当中老生常谈的一个必问话题,也是日常项目开发中,特别需要重视的环节.对于笔者这种以j ...

  6. NGUI动态给EventDelegate加参数

    示例代码如下: 响应的函数声明为: void OnChange(UIToggle toggle) { if(toggle.value) { // do something } }   添加响应的代码如 ...

  7. BZOJ3141 Hnoi2013 游走 【概率DP】【高斯消元】*

    BZOJ3141 Hnoi2013 Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点 ...

  8. 在iOS中使用ZBar扫描二维码

    最近在做的项目中需要用到二维码扫描功能,之前在Android中使用过ZXing识别二维码,ZXing也有对应的iOS版本,经过了解,ZBar也是一个常用的二维码识别软件,并分别提供了iOS和Andro ...

  9. ambassador kubernetes native api gateway

    github 上的介绍: Ambassador is an open source Kubernetes-native API Gateway built on Envoy, designed for ...

  10. Extjs tree1

    1.代码如下: 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://w ...