模拟Spring源码思想,读取Spring Config配置文件,创建IOC容器,解析spring.xml,创建对象,放入IOC容器,注入依赖

1、Spring.xml


    
        
    
    
        
    
    

2、ApplicationContext.java

package com.atguigu.ioc;
import java.util.HashMap;
import java.util.Map;
public interface ApplicationContext {
     Map beanMap = new HashMap<>();

     public void registryBean(String beanName,Object component);

     public Map getIocContainer();

     Object getBean(String beanName);
}

3、ClassPathXmlApplicationContext.java

package com.atguigu.ioc;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class ClassPathXmlApplicationContext implements ApplicationContext{

    private static final String BEAN_LABEL = "bean";
    private static final String ATTR_ID_LABEL = "id";
    private static final String ATTR_CLAZZ_LABEL = "class";
    private static final String PROPERTY_LABEL = "property";
    private static final String PROPERTY_NAME_LABEL = "name";
    private static final String PROPERTY_REF_LABEL = "ref";
    /**
     *        beans
     *    bean  bean  bean
     */
    public ClassPathXmlApplicationContext(String resolvedFilePath) {
        SAXReader saxReader = new SAXReader();
        InputStream is = this.getClass().getClassLoader().getResourceAsStream(resolvedFilePath);
        try {
            Document document = saxReader.read(new BufferedInputStream(is));
            Element rootElement = document.getRootElement();
            List beanList = rootElement.elements().stream().filter(element -> element.getName().compareTo(BEAN_LABEL) == 0).collect(Collectors.toList());
            if (beanList == null || beanList.size() == 0){
                return;
            }
            beanList.forEach(beanElement -> {
                Attribute idAttr = beanElement.attribute(ATTR_ID_LABEL);
                Attribute clazzAttr = beanElement.attribute(ATTR_CLAZZ_LABEL);
                String id = idAttr.getData().toString();
                String clazzName = clazzAttr.getData().toString();
                try {
                    Object beanInstance = Class.forName(clazzName).getDeclaredConstructor().newInstance();
                    registryBean(id,beanInstance);
                } catch (InstantiationException e) {
                    throw new RuntimeException(e);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                } catch (InvocationTargetException e) {
                    throw new RuntimeException(e);
                } catch (NoSuchMethodException e) {
                    throw new RuntimeException(e);
                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                }

            });

           beanList.forEach(beanElement -> {
               String componentClazzName = beanElement.attributeValue(ATTR_CLAZZ_LABEL);
               String componentId = beanElement.attributeValue(ATTR_ID_LABEL);
               try {
                   Class componentClazz = Class.forName(componentClazzName);
                   List propertyList = beanElement.elements().stream().filter(element -> element.getName().compareTo(PROPERTY_LABEL) == 0).collect(Collectors.toList());
                   propertyList.stream().forEach(property -> {
                       String name = property.attributeValue(PROPERTY_NAME_LABEL);
                       String ref = property.attributeValue(PROPERTY_REF_LABEL);
                       try {
                           Field targetInvokeField = componentClazz.getDeclaredField(name);
                           targetInvokeField.setAccessible(true);
                           targetInvokeField.set(getBean(componentId),getBean(ref));
                       } catch (NoSuchFieldException e) {
                           throw new RuntimeException(e);
                       } catch (IllegalAccessException e) {
                           throw new RuntimeException(e);
                       }


                   });
               } catch (Exception e) {
                   throw new RuntimeException(e);
               }

           });

        } catch (DocumentException e) {
            throw new RuntimeException(e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        System.out.println(beanMap);
    }

    @Override
    public void registryBean(String beanName, Object component) {
         beanMap.put(beanName,component);
    }

    @Override
    public Map getIocContainer() {
        return beanMap;
    }

    @Override
    public Object getBean(String beanName) {
        return beanMap.get(beanName);
    }
}

4、OrderDao.java

package com.atguigu.dao;

public interface OrderDao {
    void start();
}

4.1、OrderDaoImpl.java

package com.atguigu.dao.impl;
import com.atguigu.dao.OrderDao;
public class OrderDaoImpl implements OrderDao {
    @Override
    public void start() {
        System.out.println("orderDao start...");
    }
}

5、OrderService.java

package com.atguigu.service;
public interface OrderService {
    void progress();
}

5.1、OrderServiceImpl.java

package com.atguigu.service.impl;
import com.atguigu.dao.OrderDao;
import com.atguigu.service.OrderService;
public class OrderServiceImpl implements OrderService {
    private OrderDao orderDao;
    @Override
    public void progress() {
        System.out.println("orderService start...");
        orderDao.start();
    }
}

6、OrderController

package com.atguigu.controller;
import com.atguigu.service.OrderService;
public class OrderController {
    private OrderService orderService;
    public void save(){
        System.out.println("orderController start...");
        orderService.progress();
    }
}

7、Client

package com.atguigu.client;
import com.atguigu.controller.OrderController;
import com.atguigu.ioc.ApplicationContext;
import com.atguigu.ioc.ClassPathXmlApplicationContext;
public class Client {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Spring.xml");
        OrderController orderController = (OrderController) applicationContext.getBean("orderController");
        orderController.save();
    }
}

8、pom.xml 

    
        
            org.dom4j
            dom4j
            2.1.4
        
    

模拟Spring源码思想,读取Spring Config配置文件,创建IOC容器,解析spring.xml,创建对象,放入IOC容器,注入依赖_第1张图片

可以使用以下代码来查看 IOC 容器中有哪些 bean 对象:

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
String[] beans = context.getBeanDefinitionNames();
for(String bean: beans) {
    System.out.println(bean);
}

其中,getBeanDefinitionNames() 方法返回一个字符串数组,里面存放了所有在 IOC 容器中注册的 bean 对象的名称。遍历输出这个数组就能够查看当前 IOC 容器中有哪些 bean 对象。

 

你可能感兴趣的:(#,Spring,Framework,spring,xml,java,dom4j,spring,config)