zoukankan      html  css  js  c++  java
  • 手动编写spring

    感谢作者:https://blog.csdn.net/aa1358075776/article/details/80188952

    spring 原理,好处,以后在详细述说,这里主要是想要手动写一个简单的IOC容器。借此可以更好的了解spring .

    spring 的架

     基本思路

      1. 解析配置文件

      2. 根据配置文件申城相应的对象

      3. 将文件放入IOC容器中

    IOC  容器实现图解

      1. 创建一个java 工程,

      2. 导入dom4j.jar,jaxen.jar

      3. 创建测试用的类

    package com.myspring.bean;
     
    public class User {
     
        private String userName;
        private Address address;
     
        public String getUserName() {
            return userName;
        }
        public void setUserName(String userName) {
            this.userName = userName;
        }
        public Address getAddress() {
            return address;
        }
        public void setAddress(Address address) {
            this.address = address;
        }
        @Override
        public String toString() {
            return "User [userName=" + userName + ", address=" + address + "]";
        }
     
    

      

    package com.myspring.bean;
     
    public class Address {
     
        private String city;
     
        public String getCity() {
            return city;
        }
        public void setCity(String city) {
            this.city = city;
        }
     
        @Override
        public String toString() {
            return "Address [city=" + city + "]";
        }
     
    

      

    <?xml version="1.0" encoding="UTF-8"?>
    <beans>
        <bean id="address" class="com.myspring.bean.Address">
            <property name="city" value="fuzhou"></property>
        </bean>
     
        <bean id="user" class="com.myspring.bean.User">
            <property name="userName" value="tom"></property>
            <property name="address" ref="address"></property>
        </bean>
     
    </beans>
    

      

    package com.myspring.config;
     
    import java.util.ArrayList;
    import java.util.List;
     
    /**
     * 封装配置文件中的bean节点
     * @author 周君
     */
    public class Bean {
     
        private String id;
        private String className;
        private List<Property> properties = new ArrayList<Property>();//bean节点下可以有多个property节点
     
        public String getId() {
            return id;
        }
        public void setId(String id) {
            this.id = id;
        }
        public String getClassName() {
            return className;
        }
        public void setClassName(String className) {
            this.className = className;
        }
        public List<Property> getProperties() {
            return properties;
        }
        public void setProperties(List<Property> properties) {
            this.properties = properties;
        }
        @Override
        public String toString() {
            return "Bean [id=" + id + ", className=" + className
                    + ", properties=" + properties + "]";
        }
     
    

      

    package com.myspring.config;
    /**
     * 封装配置文件中的property节点
     * 
     * @author 周君
     */
    public class Property {
     
        private String name;
        //使用value属性直接指定值,也可以使用ref属性来指定依赖的对象
        private String value;
        private String ref;
     
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getValue() {
            return value;
        }
        public void setValue(String value) {
            this.value = value;
        }
        public String getRef() {
            return ref;
        }
        public void setRef(String ref) {
            this.ref = ref;
        }
    

      

    package com.myspring.config;
     
    import java.io.InputStream;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
     
    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    /**
     * 读取xml配置文件的类
     * @author 周君
     */
    public class XmlConfig {
     
        /**
         * 读取配置文件
         * @param path 配置文件路径
         * @return
         */
        public static Map<String, Bean> getConfig(String path){
     
            Map<String, Bean> configMap = new HashMap<String, Bean>();
            //使用dom4j和xpath读取xml文件
            Document doc = null;
            SAXReader reader = new SAXReader();
            InputStream in = XmlConfig.class.getResourceAsStream(path);
            try {
                doc = reader.read(in);
            } catch (DocumentException e) {
                e.printStackTrace();
                throw new RuntimeException("请检查您的xml配置文件路径是否正确!");
            }
            //定义xpath,取出所有的bean
            String xpath = "//bean";
            //对bean进行遍历
            List<Element> list = doc.selectNodes(xpath);
            if(list!=null){
                for (Element beanEle : list) {
                    Bean bean = new Bean();
                    //bean节点的id
                    String id = beanEle.attributeValue("id");
                    //bean节点的class属性
                    String className = beanEle.attributeValue("class");
                    //封装到bean对象中
                    bean.setId(id);
                    bean.setClassName(className);
     
                    //获取bean节点下所有的property节点
                    List<Element> proList = beanEle.elements("property");
                    if(proList != null){
                        for (Element proEle : proList) {
                            Property prop = new Property();
                            String propName = proEle.attributeValue("name");
                            String propValue = proEle.attributeValue("value");
                            String propRef = proEle.attributeValue("ref");
                            //封装到property属性中
                            prop.setName(propName);
                            prop.setValue(propValue);
                            prop.setRef(propRef);
     
                            bean.getProperties().add(prop);
                        }
                    }
                    //id是不应重复的
                    if(configMap.containsKey(id)){
                        throw new RuntimeException("bean节点ID重复:" + id);
                    }
                    //将bean封装到map中
                    configMap.put(id, bean);
                }
            }
            return configMap;
        }
    

      

    package com.myspring.core;
     
    public interface BeanFactory {
     
        Object getBean(String beanName);
    }
    

      

    实现类,作用是初始化IOC容器,生成对象放入容器中,

    所谓的容器,在代码的表现中其实是个集合,我们用hashmap 来作为容器。

    package com.myspring.core;
     
    import java.lang.reflect.Method;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Map.Entry;
     
    import com.myspring.config.Bean;
    import com.myspring.config.Property;
    import com.myspring.config.XmlConfig;
    import com.myspring.utils.BeanUtil;
     
    public class ClassPathXmlApplicationContext implements BeanFactory{
     
        //定义一个IOC容器
        private Map<String, Object> ioc;
     
        private Map<String, Bean> config;
     
        /**
         * 构造函数
         * 1. 初始化IOC容器
         * 2. 加载配置文件,生成bean对象放入IOC容器
         * @param path
         */
        public ClassPathXmlApplicationContext(String path){
            //初始化IOC容器
            ioc = new HashMap<String, Object>();
            //读取配置文件
            config = XmlConfig.getConfig(path);
            if(config!=null){
                for(Entry<String, Bean> entry : config.entrySet()){
                    String beanId = entry.getKey();
                    Bean bean = entry.getValue();
     
                    //根据bean生成相应的对象
                    Object object = createBean(bean);
                    ioc.put(beanId, object);
                }
            }
        }
        /**
         * 根据bean生成对象实例
         * @param bean
         * @return
         */
        private Object createBean(Bean bean) {
            String beanId = bean.getId();
            String className = bean.getClassName();
     
            Class c = null;
            Object object = null;
     
            try {
                //根据bean的calss属性生成对象
                c = Class.forName(className);
            } catch (ClassNotFoundException e) {
                throw new RuntimeException("您配置的class属性不合法:"+className);
            }
     
            try {
                //该方法调用的是类的无参构造方法
                object = c.newInstance();
            } catch (Exception e) {
                throw new RuntimeException("该类缺少一个无参构造方法:"+className);
            } 
            //将bean的属性封装到对象中
            if(bean.getProperties() != null){
                for(Property p : bean.getProperties()){
                    //情况一:配置文件中使用的是value属性注入
                    if(p.getValue() != null){
                        //获取属性对应的setter方法
                        Method getMethod = BeanUtil.getSetterMethod(object,p.getName());
                        try {
                            //调用set方法注入
                            getMethod.invoke(object, p.getValue());
                        } catch (Exception e) {
                            throw new RuntimeException("属性名称不合法或者没有相应的getter方法:"+p.getName());
                        } 
                    }
                    //情况二:配置文件中使用的是ref属性注入
                    if(p.getRef() != null){
                        //获取属性对应的setter方法
                        Method getMethod = BeanUtil.getSetterMethod(object,p.getName());
                        //从容器中找到依赖的对象
                        Object obj = ioc.get(p.getRef());
                        if(obj == null){
                            throw new RuntimeException("没有找到依赖的对象:"+p.getRef());
                        }else{
                            //调用set方法注入
                            try {
                                getMethod.invoke(object, obj);
                            } catch (Exception e) {
                                throw new RuntimeException("属性名称不合法或者没有相应的getter方法:"+p.getName());
                            }
                        }
                    }
                }
            }
            return object;
        }
     
        @Override
        public Object getBean(String beanName) {
            return ioc.get(beanName);
        }
     
    }
    

      

    1. package com.myspring.bean;
    2.  
       
    3.  
      public class Address {
    4.  
       
    5.  
      private String city;
    6.  
       
    7.  
      public String getCity() {
    8.  
      return city;
    9.  
      }
    10.  
      public void setCity(String city) {
    11.  
      this.city = city;
    12.  
      }
    13.  
       
    14.  
      @Override
    15.  
      public String toString() {
    16.  
      return "Address [city=" + city + "]";
    17.  
      }
    18.  
       
    19.  
  • 相关阅读:
    css添加方法
    node + vue 实现服务端单向推送消息,利用EventSource
    获取公众号openid,通过unionid 和小程序用户绑定起来
    小程序 构建npm
    powershell禁止系统运行脚本
    mongoose 删除
    mongoose 查询
    moogoose 更新
    小程序,用户授权手机号,node需要检验和解析
    小程序:支付的时候缺少参数:total_fee,支付失败
  • 原文地址:https://www.cnblogs.com/dousil/p/15464495.html
Copyright © 2011-2022 走看看