zoukankan      html  css  js  c++  java
  • spring-5-spring源码(模拟自动注入)

    简单模拟spring中xml方式注入

    1、定义接口

    package com.service;
    public interface Service {
        public void queryDao();
    }
    
    
    package com.dao;
    public interface Dao {
        public void query();
    }
    

      

    2、实现类

    package com.service;
    import com.dao.Dao;
    public class ServiceImpl implements Service {
         Dao dao ;
         
         Dao getDao() {
            return dao;
        }
    
        public void setDao(Dao dao) {
            this.dao = dao;
        }
    
        public void queryDao() {
            System.out.println("开始调用Dao!");
            dao.query();
        }
    }
    
    
    
    
    
    
    package com.dao;
    
    public class DaoImpl implements Dao {
        @Override
        public void query(){
            System.out.println("操作数据库!");
        }
    }
    

      

    3、工厂类

    package com.util;
    
    import org.dom4j.Attribute;
    import org.dom4j.Document;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    
    import java.io.File;
    import java.lang.reflect.Field;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    
    public class BeanFactory {
        public Map map = new HashMap<String,Object>();
    
        public BeanFactory(String xml) {
            parseXml(xml);
        }
    
        public void parseXml(String xml){
            try {
                File file = new File(this.getClass().getResource("/").getPath()+"//"+xml);
                SAXReader reader = new SAXReader();
                Document document = reader.read(file);
                Element root = document.getRootElement();
    
                for (Iterator<Element> it1 = root.elementIterator(); it1.hasNext();) {
                    Element element = it1.next();
                    Attribute elementAttrId = element.attribute("id");
                    String elementId = elementAttrId.getValue();
                    Attribute elementAttrClass = element.attribute("class");
                    String elementClass = elementAttrClass.getValue();
    
                    //实例化对象
                    Class clazz = Class.forName(elementClass);
                    Object beanObject = clazz.newInstance();
                    map.put(elementId,beanObject);
    
                    for (Iterator<Element> it2 = element.elementIterator(); it2.hasNext();) {
                        Element element2 = it2.next();
                        if("property".equals(element2.getName())){
                            String attributeName = element2.attribute("name").getValue();
                            String attributeRef =  element2.attribute("ref").getValue();
    
                            //获取目标对象中的所有属性,[规则:属性的名字一定和property中的那么保持一致]
                            Field field = beanObject.getClass().getDeclaredField(attributeName);
    
                            //说明依赖已经存在map中,需要将依赖注入到目标中的属性中
                            Object injectInObject = map.get(attributeRef);
                            if(map.get(attributeRef)==null){
                                System.out.println("依赖还没有注入,请检查以来是否在"+clazz.getName()+"对象之前已经注入!");
                            }
                   //使用反射set方法必须传的值,否则会报IllegalAccessException:"BeanFactory不能访问com.service类的成员。ServiceImpl与修饰符" field.setAccessible(true); field.set(beanObject,injectInObject); } } } } catch (Exception e) { e.printStackTrace(); } } public Object getBean(String beanName){ if(map == null || map.get(beanName)==null){ return null; } return map.get(beanName); } }

      

    4、测试类

    public static void main(String args[]){
            BeanFactory beanFactory = new BeanFactory("spring.xml");
            System.out.println(beanFactory.map);
            Service service = (ServiceImpl)beanFactory.getBean("service");
            service.queryDao();
        }
    

      

    使用构造方式依赖注入

    package com.util;
    
    import org.dom4j.Attribute;
    import org.dom4j.Document;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    
    import java.io.File;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    
    public class BeanFactory {
        public Map map = new HashMap<String,Object>();
    
        public BeanFactory(String xml) {
            parseXml(xml);
        }
    
        public void parseXml(String xml){
            try {
                File file = new File(this.getClass().getResource("/").getPath()+"//"+xml);
                SAXReader reader = new SAXReader();
                Document document = reader.read(file);
                Element root = document.getRootElement();
    
                for (Iterator<Element> it1 = root.elementIterator(); it1.hasNext();) {
                    Element element = it1.next();
                    Attribute elementAttrId = element.attribute("id");
                    String elementId = elementAttrId.getValue();
                    Attribute elementAttrClass = element.attribute("class");
                    String elementClass = elementAttrClass.getValue();
                    //实例化对象
                    Class clazz = Class.forName(elementClass);
                    Object beanObject = clazz.newInstance();
    
                    for (Iterator<Element> it2 = element.elementIterator(); it2.hasNext();) {
                        Element element2 = it2.next();
                        //实例化对象,如果子标签是property则默认使用setter方法,并且默认构造
                        String attributeName = element2.attribute("name").getValue();
                        String attributeRef =  element2.attribute("ref").getValue();
                        Object injectInObject = null;
                        if("property".equals(element2.getName())){
                            injectInObject = map.get(attributeRef);
                            //说明依赖不存在map中,需要将依赖注入到目标中的属性中
                            if(injectInObject==null){
                                System.out.println("依赖对象还没有注册到容器!");
                            }
    
                            //获取目标对象中的所有属性,[规则:属性的名字一定和property中的那么保持一致]
                            Field field = beanObject.getClass().getDeclaredField(attributeName);
    
                            field.setAccessible(true);
                            field.set(beanObject,injectInObject);
    
                        //当然构造方法中可以有多个参数,这里只默认为一个注入对象
                        }else if("constructor-arg".equals(element2.getName())){
                            injectInObject = map.get(attributeRef);
                            if(injectInObject==null){
                                System.out.println("依赖对象还没有注册到容器!");
                            }
                            Constructor constructor= clazz.getConstructor(injectInObject.getClass().getInterfaces()[0]);
                            beanObject = constructor.newInstance(injectInObject);
                        }else{
                            System.out.println("解析中出现特殊子标签,请继续编写!");
                        }
                    }
    
                    if(beanObject==null){
                        beanObject = clazz.newInstance();
                    }
                    map.put(elementId,beanObject);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public Object getBean(String beanName){
            if(map == null || map.get(beanName)==null){
              return null;
            }
            return map.get(beanName);
        }
    }
    

      

    模拟自动装配方式,并且属性方式>自动装配,自定义异常

    1、自动装配

      byType方式:如果xml中beans标签中包含自动装配属性并且value=byType,我们要循环目标对象的属性,并且使用属性查找map(已注入的对象)是否一致(这里判断的是接口名字),如果一致使用set方式注入,如果map中出现两个则需要抛出自定义异常(再容器中找到两个一样的注入对象)

     

  • 相关阅读:
    moment.js相关知识总结
    git相关使用解释
    .我的第一篇博客
    QT项目配置
    重载->
    内核对象同步
    模式对话框与非模式对话框
    显示与隐式类型转换
    size_t与size_type
    系统级源代码:系统裁剪
  • 原文地址:https://www.cnblogs.com/gnwzj/p/11128173.html
Copyright © 2011-2022 走看看