手写一个简单的spring IOC容器

加载解析配置bean文件

利用反射实例化bean

通过工厂模式获取实例

 用map表示容器

一、加载xml配置文件

public class XmlConfig {
    /**
     * 功能描述:加载配置文件,获取所有的bean
     * @param path 配置路径
     * @return 所有bean的map
     */
    public static Map<String, Bean> getConfig(String path){
        Map<String, Bean> config = new HashMap<String, Bean>();
        // 1、读取applicationContext
        InputStream inputStream = XmlConfig.class.getResourceAsStream(path);
        SAXReader reader = new SAXReader();
        Document read = null;
        try {
            read = reader.read(inputStream);
        } catch (DocumentException e) {
            e.printStackTrace();
            throw new RuntimeException("配置文件错误,请检查");
        }
        Element rootElement = read.getRootElement();
        List<Element> elements = rootElement.elements("bean");
        if (elements == null){
            return config;
        }
        for (Element element : elements) {
            Bean bean = new Bean();
            // 获取bean的id和class
            String id = element.attributeValue("id");
            String className = element.attributeValue("class");
            bean.setId(id);
            bean.setClassName(className);

            List<Element> properties = element.elements("property");
            List<Property> pros = new ArrayList<Property>();
            if (properties != null){
                for (Element property : properties) {
                    Property pro = new Property();
                    // 加载参数
                    String name = property.attributeValue("name");
                    String value = property.attributeValue("value");
                    String ref = property.attributeValue("ref");
                    pro.setName(name);
                    pro.setValue(value);
                    pro.setRef(ref);
                    bean.getProperties().add(pro);
                }
            }

            // 校验id不重复
            if (config.containsKey(id)){
                throw new RuntimeException("bean节点ID重复:" + id);
            }
            config.put(id, bean);
        }
        return config;
    }
}

 二、实例化bean

public class ClassPathXmlApplicationContext implements BeanFactory {
    private Map<String, Object> ioc;
    private Map<String, Bean> config;
    /**
     * 功能描述:初始化
     */
    public ClassPathXmlApplicationContext(String path){
        this.ioc = new HashMap<String, Object>();
        this.config = XmlConfig.getConfig(path);
        for (Map.Entry<String, Bean> entry : this.config.entrySet()) {
            String key = entry.getKey();
            Bean bean = entry.getValue();
            Object value = createBean(bean);
            this.ioc.put(key, value);
        }
    }

    /**
     * 功能描述:创建bean实例
     * @param bean
     * @return
     */
    public Object createBean(Bean bean){
        // 利用反射,获取bean实例
        Class<?> clazz = null;
        try {
            clazz = Class.forName(bean.getClassName());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("配置的class不合理");
        }
        Object instance = null;
        try {
            instance = clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("创建bean实例失败");
        }
        List<Property> properties = bean.getProperties();
        if (properties == null){
            return instance;
        }
        for (Property property : properties) {
            String name = property.getName();
            String value = property.getValue();
            String ref = property.getRef();
            if(value != null){
                Field field = null;
                try {
                    field = clazz.getDeclaredField(name);
                    field.setAccessible(true);
                    field.set(instance, value);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new RuntimeException("属性名称不合法");
                }
            }
            if(ref != null){
                try{
                    Field field = clazz.getDeclaredField(name);
                    field.setAccessible(true);
                    Object obj = ioc.get(ref);
                    field.set(instance, obj);
                }catch (Exception e){
                    e.printStackTrace();
                    throw new RuntimeException("没有找到依赖的对象");
                }
            }
        }
        return instance;
    }

    public Object getBean(String id){
        return this.ioc.get(id);
    }

}

三、工厂模式获取实例

public interface BeanFactory {
    Object getBean(String beanName);
}

四、测试类

/**
 * IOC容器
 * 工厂模式
 *
 */
public class AppTest {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/AppContext.xml");

        User fundUser = (User)context.getBean("user");
        System.out.println(fundUser.toString());
    }
}

五、其它类

// Bean
public class Bean {
    private String id;
    private String className;
    private List<Property> properties = new ArrayList<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;
    }
}
// Property
public class Property {
    private String name;
    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;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值