手写spring实例化bean源码,通过反射机制实现Object getBean(String beanId)方法

手写spring实例化bean源码,只实现了Object getBean(String beanId)这个方法。
也就是实现:

 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("xxx");
 Object o = applicationContext.getBean("xxx");
// 定义ApplicationContext 接口:
public interface ApplicationContext {
    Object getBean(String name);
}
// ClassPathXmlApplicationContext类
/**
* 解析xml文件,读取标签,实例化对象
* @param springPath spring.xml path
*/
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ClassPathXmlApplicationContext implements ApplicationContext{

    private final Map<String, Object> beanObjects = new HashMap<>();
    
    public ClassPathXmlApplicationContext(String springPath) {
        // 解析spring配置文件,然后实例化Bean,将Bean放到beanObjects中
        try {
            // 通过路径解析xml文件
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            // 获取类路径下的spring配置文件
            InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream(springPath);
            Document document = db.parse(in);
            // 获取所有的Bean标签
            NodeList beans = document.getElementsByTagName("bean");
            //System.out.println(beans.getLength());
            for (int i = 0; i < beans.getLength(); i++) {
                // 获取到某一个bean标签的所有属性的name和value存到map集合里
                NamedNodeMap attributes = beans.item(i).getAttributes();
                // 获取到bean标签里的id
                String beanId = attributes.getNamedItem("id").getNodeValue();
                // 获取到bean标签里的class
                String classValue = attributes.getNamedItem("class").getNodeValue();
                //System.out.println(beanId);
                //System.out.println(classValue);
                // 通过反射机制创建对象,并提前曝光
                Class<?> beanClazz = Class.forName(classValue);
                // 通过构造方法创建对象
                Object beanObject = beanClazz.getConstructor().newInstance();
                // 曝光bean
                beanObjects.put(beanId, beanObject);
//                System.out.println(beanObject);

            }

            // 再次遍历所有的bean标签,给属性赋值
            for (int i = 0; i < beans.getLength(); i++) {
                // 获取到某一个bean标签的所有属性的name和value存到map集合里
                NamedNodeMap attributes = beans.item(i).getAttributes();
                // 获取到bean标签里的id
                String beanId = attributes.getNamedItem("id").getNodeValue();
                // 获取到bean标签里的class
                String classValue = attributes.getNamedItem("class").getNodeValue();
                // 获取该bean标签下的所有property标签, 注意这里面包含回车, 需要进行筛选
                NodeList childNodes = beans.item(i).getChildNodes();
                List<Node> propertyNodes = new ArrayList<>();
                for(int j=0; j<childNodes.getLength(); j++){
                    if (childNodes.item(j).getAttributes() !=null) {
                        propertyNodes.add(childNodes.item(j));
                    }
                    // 如果是回车话,这个会是null
                    //System.out.println(childNodes.item(j).getAttributes());
                }
                // 获取property属性的name和value属性  或者name和ref的属性
                if (propertyNodes.size() != 0) {
                    propertyNodes.forEach(propertyNode -> {
                        // 获取property标签的属性名和属性值map
                        NamedNodeMap propertyNodeAttributes = propertyNode.getAttributes();
                        // 获取name属性值
                        Node nameNode = propertyNodeAttributes.getNamedItem("name");
                        // 获取value属性值
                        Node valueNode = propertyNodeAttributes.getNamedItem("value");
                        // 获取ref属性
                        Node refNode = propertyNodeAttributes.getNamedItem("ref");
                        // 给bean标签实例化出来的对象赋值
                        // 从beanObjects中根据beanId获取到已经创建出来的对象
                        Object beanObject = beanObjects.get(beanId);
                        if (nameNode != null && valueNode != null) {
                            try {
                                // 拼接set方法
                                String name = nameNode.getNodeValue();
                                String value = valueNode.getNodeValue();
                                String setMethod = "set" + name.toUpperCase().charAt(0) + name.substring(1);
                                // 通过反射机制调用set方法
                                Class<?> clazz1 = Class.forName(classValue);
                                Method method = clazz1.getDeclaredMethod(setMethod, String.class);
                                method.invoke(beanObject, value);
                            } catch (ClassNotFoundException e) {
                                e.printStackTrace();
                            } catch (NoSuchMethodException e) {
                                e.printStackTrace();
                            } catch (InvocationTargetException e) {
                                e.printStackTrace();
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            }
                        }

                        if (nameNode != null && refNode != null){
                            try {
                                // 拼接set方法
                                String name = nameNode.getNodeValue();
                                String ref = refNode.getNodeValue();
                                String setMethod = "set" + name.toUpperCase().charAt(0) + name.substring(1);
                                //System.out.println(setMethod);
                                // 根据ref找到对应beanObject
                                Object refObject = beanObjects.get(ref);
                                //System.out.println(refObject.getClass().getName());
                                // 使用反射机制调用方法
                                Class.forName(classValue).getDeclaredMethod(setMethod, refObject.getClass()).invoke(beanObject, refObject);
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            } catch (InvocationTargetException e) {
                                e.printStackTrace();
                            } catch (NoSuchMethodException e) {
                                e.printStackTrace();
                            } catch (ClassNotFoundException e) {
                                e.printStackTrace();
                            }
                        }

                    });
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Override
    public Object getBean(String name) {
        return beanObjects.get(name);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值