IOC案例

1、读取配置文件中的bean标签,此时IOC工厂会根据id返回对应的对象,但是此时对象里面的参数没有被进行赋值。

<beans>
    <bean id="stu" name="com.etoak.entity.Student"></bean>
</beans>
//BeanUtil类存放bean标签中的信息
public class BeanUtil {
    private String id;//表示配置文件中bean中的id,是为了表示用户根据传入的id值来得到对用的对象
    private String classname;//表示配置文件中bean中的name,为了工厂根据反射的原理来加载此类
    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 class IOCFactory {
    //配置文件中可能又多个bean标签,所以用List集合来装这些属性
    private List<BeanUtil> beanUtils=new ArrayList<>();
    //创建该对象时,就把配置文件的内容读取到beanUtils列表中
    public IOCFactory(){
        //解析Xml文件,需要第三方插件
        SAXReader reader=new SAXReader();
        InputStream url=BeanUtil.class.getClassLoader().getResourceAsStream("conf.xml");
        try {
            Document doc=reader.read(url);
            //得到根元素也就是beans
            Element rootElement = doc.getRootElement();
            //根据bean找到配置文件中根标签底下标签为bean的所有元素
            List<Element> beans = rootElement.elements("bean");
            for(Element bean:beans){
                BeanUtil beanUtil=new BeanUtil();
                //根据bean标签中属性id拿到id所对应的值
                beanUtil.setId(bean.attributeValue("id"));
                //根据bean标签中属性name拿到对应的值
                beanUtil.setClassname(bean.attributeValue("name"));
                //把此时根据bean标签中的内容读取到的值拿到集合中
                beanUtils.add(beanUtil);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //根据id拿到对应的实例对象
    public Object getBean(String id){
        Object target=null;
        //判断beanUtils是否包含bean标签
        if(beanUtils.size()>0){
            for (BeanUtil bean:beanUtils){
                //判断是否存在该id
                if(bean.getId().equals(id)){
                    try {
                        //根据name获得class对象
                        Class cla=Class.forName(bean.getClassname());
                        //根据cla创建一个无参实例
                        target=cla.newInstance();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return target;
    }
}

2、在bean标签中添加一些对应的属性名和属性值

<beans>
    <bean id="stu" name="com.etoak.entity.Student">
        <property name="user" value="et2201"></property>
        <property name="pwd" value="gt"></property>
    </bean>
</beans>

此时要在BeanUtil类中添加一个新的属性,用来存放property标签的内容,并创建一个PropertyUtil

//此列表代表该bean标签内的property中的标签,可能不唯一,所有用列表存
    private List<PropertyUtil> propertyUtils;
    public List<PropertyUtil> getPropertyUtils() {
        return propertyUtils;
    }
    public void setPropertyUtils(List<PropertyUtil> propertyUtils) {
        this.propertyUtils = propertyUtils;
    }
//存放property标签中的信息
public class PropertyUtil {
    private String name;
    private String value;

    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;
    }
}

构造方法中为了获取property值的代码改动
注释是******之间是改动的内容

public IOCFactory(){
        //解析Xml文件,需要第三方插件
        SAXReader reader=new SAXReader();
        InputStream url=BeanUtil.class.getClassLoader().getResourceAsStream("conf.xml");
        try {
            Document doc=reader.read(url);
            //得到根元素也就是beans
            Element rootElement = doc.getRootElement();
            //根据bean找到配置文件中根标签底下标签为bean的所有元素
            List<Element> beans = rootElement.elements("bean");
            for(Element bean:beans){
                BeanUtil beanUtil=new BeanUtil();
                //根据bean标签中属性id拿到id所对应的值
                beanUtil.setId(bean.attributeValue("id"));
                //根据bean标签中属性name拿到对应的值
                beanUtil.setClassname(bean.attributeValue("name"));
                //******************************************
                //创建一个List集合来存放property标签中的属性,并把这些属性放到bean中
                List<PropertyUtil> propertyUtils=new ArrayList<>();
                //得到elements为property的所有信息
                List<Element> pros=bean.elements("property");
                for (Element pro:pros){
                    PropertyUtil propertyUtil=new PropertyUtil();
                    //根据property标签中name,value属性获取所对应的值
                    propertyUtil.setName(pro.attributeValue("name"));
                    propertyUtil.setValue(pro.attributeValue("value"));
                    propertyUtils.add(propertyUtil);
                }
                beanUtil.setPropertyUtils(propertyUtils);
                //******************************************
                //把此时根据bean标签中的内容读取到的值拿到集合中
                beanUtils.add(beanUtil);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

此时要改变getBean方法中获得对象+对象的方法赋值,首先我们要知道对于private私有属性赋值取值用getter和setter方法,jdk中有一个PropertyDescription类可以根据get,set方法来进行字段取值赋值。
在这里插入图片描述
知道这个之后就可以继续往下探究

 public Object getBean(String id){
        Object target=null;
        //判断beanUtils是否包含bean标签
        if(beanUtils.size()>0){
            for (BeanUtil bean:beanUtils){
                //判断是否存在该id
                if(bean.getId().equals(id)){
                    try {
                        //根据name获得class对象
                        Class cla=Class.forName(bean.getClassname());
                        //根据cla创建一个无参实例,本案例中代表Student对象
                        target=cla.newInstance();
                        //****************************************
                        //获得对象要给此对象的属性进行赋值
                        List<PropertyUtil> propertyUtils = bean.getPropertyUtils();
                        for (PropertyUtil propertyUtil:propertyUtils){
                            //获得PropertyUtil类中的name属性,也就是标签property中的name的值
                            String name=propertyUtil.getName();
                            //获得标签中value值
                            String value=propertyUtil.getValue();
                            //构造方法两个参数,第一个代表属性名,第二个表示Class对象,此案例表示Student的class对象
                            PropertyDescriptor propertyDescriptor=new PropertyDescriptor(name,cla);
                            //这句话表示给target对象调用了关于属性名为name的set方法,并把此时的value值传进去
                            propertyDescriptor.getWriteMethod().invoke(target,value);
                            //*************************************
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return target;
    }

我们测试一下看看书否能Student类可以获取到配置文件中的参数

 public static void main(String[] args) {
        IOCFactory iocFactory=new IOCFactory();
        Student stu=(Student)iocFactory.getBean("stu");
        System.out.println(stu);//Student{user='et2201', pwd='gt'}
    }

此时我们就获得了配置文件中Student类中的属性和值。
3、我们此时的Student类中的参数只有user和pwd两个属性,并且这两个属性的类型是基本数据类型,但是问题是如果在此类中添加另一个对象应该如何做呢?如图在Student类中添加一个School学校类。
在这里插入图片描述
我们既然需要一个School类那我们就可以在配置文件添加一个新的标签ref,此标签中的name值则表示getBean(id)方法中的id值

<beans>
    <bean id="stu" name="com.etoak.entity.Student">
        <property name="user" value="et2201"></property>
        <property name="pwd" value="gt"></property>
        <ref name="school"></ref>
    </bean>
    <bean id="school" name="com.etoak.entity.School">
        <property name="name" value="etoak"></property>
    </bean>
</beans>

所以我们要在BeanUtil中添加一个集合关于存放其他复杂数据类型的对象,无参构造对象改造

//BeanUtil类中添加的代码
//用来存放复杂数据类型变量的集合
 private List<RefUtil> refUtils;

    public List<RefUtil> getRefUtils() {
        return refUtils;
    }

    public void setRefUtils(List<RefUtil> refUtils) {
        this.refUtils = refUtils;
    }
//RefUtil类中
public class RefUtil {
    //此name表示想要创建其他对象实例中bean标签的id
    private String name;
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public IOCFactory(){
        //解析Xml文件,需要第三方插件
        SAXReader reader=new SAXReader();
        InputStream url=BeanUtil.class.getClassLoader().getResourceAsStream("conf.xml");
        try {
            Document doc=reader.read(url);
            //得到根元素也就是beans
            Element rootElement = doc.getRootElement();
            //根据bean找到配置文件中根标签底下标签为bean的所有元素
            List<Element> beans = rootElement.elements("bean");
            for(Element bean:beans){
                BeanUtil beanUtil=new BeanUtil();
                //根据bean标签中属性id拿到id所对应的值
                beanUtil.setId(bean.attributeValue("id"));
                //根据bean标签中属性name拿到对应的值
                beanUtil.setClassname(bean.attributeValue("name"));
                //******************************
                //在bean标签中找到所有的ref标签
                List<Element> refs = bean.elements("ref");
                List<RefUtil> refUtils=new ArrayList<>();
                //存在其他类对象,则进入for循环
                for (Element ref:refs){
                    RefUtil refUtil=new RefUtil();
                    //把ref标签中name属性值放在RefUtil的属性name中
                    refUtil.setName(ref.attributeValue("name"));
                    refUtils.add(refUtil);
                }
                //把refUtils添加完集合放在BeanUtil中属性refUtils中
                beanUtil.setRefUtils(refUtils);
                //*******************************
                //创建一个List集合来存放property标签中的属性,并把这些属性放到bean中
                List<PropertyUtil> propertyUtils=new ArrayList<>();
                //得到elements为property的所有信息
                List<Element> pros=bean.elements("property");
                for (Element pro:pros){
                    PropertyUtil propertyUtil=new PropertyUtil();
                    //根据property标签中name,value属性获取所对应的值
                    propertyUtil.setName(pro.attributeValue("name"));
                    propertyUtil.setValue(pro.attributeValue("value"));
                    propertyUtils.add(propertyUtil);
                }
                beanUtil.setPropertyUtils(propertyUtils);
                //把此时根据bean标签中的内容读取到的值拿到集合中
                beanUtils.add(beanUtil);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

接下来要对getBean()方法中代码进行修改

 public Object getBean(String id){
        Object target=null;
        //判断beanUtils是否包含bean标签
        if(beanUtils.size()>0){
            for (BeanUtil bean:beanUtils){
                //判断是否存在该id
                if(bean.getId().equals(id)){
                    try {
                        //根据name获得class对象
                        Class cla=Class.forName(bean.getClassname());
                        //根据cla创建一个无参实例,本案例中代表Student对象
                        target=cla.newInstance();
                        //获得对象要给此对象的属性进行赋值
                        List<PropertyUtil> propertyUtils = bean.getPropertyUtils();
                        for (PropertyUtil propertyUtil:propertyUtils){
                            //获得PropertyUtil类中的name属性,也就是标签property中的name的值
                            String name=propertyUtil.getName();
                            //获得标签中value值
                            String value=propertyUtil.getValue();
                            //构造方法两个参数,第一个代表属性名,第二个表示Class对象,此案例表示Student的class对象
                            PropertyDescriptor propertyDescriptor=new PropertyDescriptor(name,cla);
                            //这句话表示给target对象调用了关于属性名为name的set方法,并把此时的value值传进去
                            propertyDescriptor.getWriteMethod().invoke(target,value);
                        }
                        //********************************
                        //获得RefUtil集合中的name属性
                        List<RefUtil> refUtils=bean.getRefUtils();
                        //表示此时没有引用数据类型
                        if(refUtils!=null){
                            //表示集合中有数据
                            for(RefUtil refUtil:refUtils){
                                String name=refUtil.getName();
                                //此时采用递归的办法调用getBean(),返回该类的实例对象,并把该实例对象添加到target对象中
                                Object obj=this.getBean(name);
                                //构造方法两个参数,第一个代表属性名,第二个表示Class对象,此案例表示Student的class对象
                                PropertyDescriptor propertyDescriptor=new PropertyDescriptor(name,cla);
                                //这句话表示给target对象调用了关于属性名为name的set方法,并把此时的value值传进去
                                propertyDescriptor.getWriteMethod().invoke(target,obj);
                                //********************************

                            }
                        }

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return target;
    }

测试

 public static void main(String[] args) {
        IOCFactory iocFactory=new IOCFactory();
        Student stu=(Student)iocFactory.getBean("stu");
        System.out.println(stu);//Student{user='et2201', pwd='gt', school=School{name='etoak'}}
    }

这样我们就可以根据配置文件,来创建对象,而不用自己手动new

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值