IoC底层原理

读取配置文件,解析XML.
通过反射机制实例化配置文件中所配置所有的bean.

package com.southwind.ioc;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.xml.sax.SAXException;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class ClassPathXmlApplicationContext implements ApplicationContext{
    private Map<String,Object> ioc = new HashMap<String,Object>();
    public ClassPathXmlApplicationContext(String path) {
        try {
            SAXReader reader = new SAXReader();
            Document document = reader.read("./src/main/resources/spring.xml");
            Element root = document.getRootElement();
            Iterator<Element> iterator =  root.elementIterator();
            while(iterator.hasNext()){
                Element element = iterator.next();
//                System.out.println(element);
                String id = element.attributeValue("id");
                String className = element.attributeValue("class");
                System.out.println(id);
                System.out.println(className);
//                通过反射机制创建对象
                Class clazz = Class.forName(className);
//                获取无参构造函数
                Constructor constructor = clazz.getConstructor();
//                System.out.println(constructor);
                Object object = constructor.newInstance();
//                System.out.println(object);

//                给目标对象赋值
                Iterator<Element> beanIter = element.elementIterator();
                while(beanIter.hasNext()){
                    Element property = beanIter.next();
                    String name = property.attributeValue("name");
                    String valueStr = property.attributeValue("value");
                    String ref = property.attributeValue("ref");
//                    System.out.println(ref);
                    if(ref == null){
                        String methodName = "set"+name.substring(0,1).toUpperCase()+name.substring(1);
//                    System.out.println(methodName);
                        Field field = clazz.getDeclaredField(name);
                        System.out.println(field.getType().getName());
                        Method method = clazz.getDeclaredMethod(methodName,field.getType());
//                    System.out.println(method);
//                    method.invoke(object,value);

//                    根据成员变量的数据类型将value 进行转换
                        Object value = null;
                        if(field.getType().getName() == "long"){
                            value = Long.parseLong(valueStr);
                        }
                        if(field.getType().getName() == "java.lang.String"){
                            value = valueStr;
                        }
                        if(field.getType().getName() == "int"){
                            value = Integer.parseInt(valueStr);
                        }
                        method.invoke(object,value);
                    }
                    ioc.put(id,object);
                }

            }
            Object obj1 = ioc.get("address");
            Object obj2 = ioc.get("student");
            System.out.println(obj1);
            System.out.println(obj2);
        } catch (DocumentException e) {
            e.printStackTrace();
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }catch (NoSuchMethodException e){
            e.printStackTrace();
        }catch (InstantiationException e){
            e.printStackTrace();
        }catch(IllegalAccessException e){
            e.printStackTrace();
        }catch(InvocationTargetException e){
            e.printStackTrace();
        }catch(NoSuchFieldException e){
            e.printStackTrace();
        }
    }

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

通过运行时类获取bean

//        加载配置文件
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
//        Student student = (Student) applicationContext.getBean("student");
        Student student = (Student) applicationContext.getBean(Student.class);

        System.out.println(student);

这种方式存在一个问题,配置文件中一个数据类型的对象只能有一个实例,否则会抛出异常,因为没有唯一的bean.
通过有参构造创建bean

  • 在实体类中创建对应的有参构造函数
  • 配置文件
<bean id="student3" class="com.southwind.entity.Student">
    <constructor-arg name="id" value="3"></constructor-arg>
    <constructor-arg name="name" value="小明"></constructor-arg>
    <constructor-arg name="age" value="18"></constructor-arg>
    <constructor-arg name="address" ref="address"></constructor-arg>
</bean>

给Bean注入集合

<bean id="student" class="com.southwind.entity.Student">
        <property name="id" value="2"></property>
        <property name="name" value="李四"></property>
        <property name="age" value="33"></property>
<!--        <property name="address" ref="address"></property>-->
       <property name="addresses">
           <list>
               <ref bean="address"></ref>
               <ref bean="address2"></ref>
           </list>
       </property>
    </bean>
<bean id="address" class="com.southwind.entity.Address">
        <property name="id"  value="1"></property>
        <property name="name" value="科技路"></property>
    </bean>
    <bean id="address2" class="com.southwind.entity.Address">
        <property name="id" value="2"></property>
        <property name="name" value="高新区"></property>
    </bean>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值