简单的模拟一个Spring IOC (非源码)

在使用spring框架时,不在程序里new对象,而是将对象都交给了spring去管理,在需要对象时,去spring容器里获取

例如,在spring配置文件里定义一个bean

<bean id="userDao" class="com.wh.dao.impl.UserDaoImpl"></bean>

在需要UserDaoImpl对象时,不在去new,而是直接问容器要

public void testInversion(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) applicationContext.getBean("userDao");
        userDao.save();
    }

可以看出来对象一定是都放在了applicationContext里,bean对象就是它管理的
工作原理应该就是applicationContext解析了applicationContext.xml文件后,拿到了类的全路径,通过反射创建对象并保存到了貌似是一个map的集合里
该map的key就是的id属性,value就是value或rel属性

模拟一个简单的ApplicationContext

假设已有bean配置文件bean.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <bean id="personDao" class="com.wh.dao.impl.PersonDaoImpl"></bean>
    <bean id="personService" class="com.wh.service.impl.PersonServiceImpl">
        <property name="personDao" ref="personDao"></property>
    </bean>
</beans>

SpringXmlApplicationContext

public class SpringXmlApplicationContext {
    // 模仿spring存储对象的容器, key就是<bean id="">, value就是<bean class="">
    private Map<String,Object> map=new HashMap<String,Object>();

    public SpringXmlApplicationContext(String file){
        try {
            SAXReader saxReader=new SAXReader();
            InputStream inputStream= SpringXmlApplicationContext.class.getClassLoader().getResourceAsStream(file);
            Document document = saxReader.read(inputStream);
            // 获取根元素
            Element rootElement = document.getRootElement();
            // 获取根元素下所有子元素
            List<Element> elements = rootElement.elements();
            // 循环所有的bean
            for (Element element : elements) {
                String key=element.attributeValue("id");
                String className=element.attributeValue("class");
                Class clazz=Class.forName(className);
                // 通过反射创建对象
                Object value=clazz.newInstance();
                // 将创建的对象放到spring容器
                map.put(key,value);
                // 找到每个bean标签下的所有property子元素
                List<Element> propertyList= element.elements("property");
                // 依赖注入
                if(propertyList!=null && propertyList.size()>0){
                    // 循环propertyList
                    for (Element propertyElement : propertyList) {
                        //找到property标签中的name属性的值
                        String name= propertyElement.attributeValue("name");
                        //找到property标签中的ref属性的值
                        String ref=propertyElement.attributeValue("ref");
                        byte[] names=name.getBytes();
                        names[0]=(byte)(names[0]-32);
                        // set方法的形式注入属性值
                        String methodName="set"+new String(names);
                        Method method= clazz.getDeclaredMethod(methodName,clazz.getDeclaredField(name).getType());
                        method.invoke(value,map.get(ref));
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public Object getBean(String key){
        return map.get(key);
    }
}

Spring IOC工作原理就是将xml文件解析后,获得类全路径,通过反射技术创建对象,然后将对象存到了spring容器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值