zoukankan      html  css  js  c++  java
  • Spring源码加载过程图解(一)

    最近看了一下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;
        }
    }
    View Code
    /**
     * 用于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;
        }
    
    }
    View Code

    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;
        }
    View Code

    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;
        }
    }
    View Code

    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;
        }
    
    }
    View Code

    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));
                }
            }
        }
    }
    View Code

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

     未完,待续 。。。。。。

  • 相关阅读:
    Fragment 总结
    Varnish缓存服务器的搭建配置手册
    关于页面缓存服务器的研究报告
    基于Html5的移动端开发框架的研究
    C#的Process类的一些用法
    c#中进程的使用
    C#反射(转载)
    进制的转换 以及十进制转换成x进制的代码
    算法及其复杂度
    cocos总结
  • 原文地址:https://www.cnblogs.com/nangonghui/p/8719551.html
Copyright © 2011-2022 走看看