• 微信公众号:美女很有趣。 工作之余,放松一下,关注即送10G+美女照片!

简单Ioc

开发技术 开发技术 2周前 (04-30) 5次浏览
package com.etoak.student.framework;

import com.etoak.student.entity.School;
import com.etoak.student.entity.Student;
import com.etoak.student.service.IStudentService;
import com.mysql.jdbc.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.beans.PropertyDescriptor;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//Bean工厂 ==》生产Bean的
public class BeanFactory {
    public static void main(String[] args) {
        //new BeanFactory();
        BeanFactory f = new BeanFactory();
        Student stu = (Student )f.getBean("stu");
        System.out.println(stu);
       /* School sch = (School)f.getBean("sch");
        System.out.println(sch);
        IStudentService servcie = (IStudentService)f.getBean("service");
        System.out.println(servcie);*/

    }
    private static Map<String,BeanDefinition> beanDefinitions = new HashMap<>();
    public BeanFactory(){
        //读取配置文件
        //从包里边寻找
        //BeanFactory.class.getResourceAsStream("../../../../../bean.xml");
        //从包外边寻找
        InputStream is = BeanFactory.class.getClassLoader().
                getResourceAsStream("beans.xml");

        SAXReader reader = new SAXReader();
        try {
            Document doc = reader.read(is);
            //获得根元素<beans>
            Element root = doc.getRootElement();
            List<Element> beans = root.elements("bean");
            for (Element bean : beans) {
                //id 获得bean元素中的id属性的值
                String id = bean.attributeValue("id");
                //类名字
                String className = bean.attributeValue("class");

                BeanDefinition beanDefinition = new BeanDefinition();
                beanDefinition.setId(id);
                beanDefinition.setClassName(className);
                //获得bean的子元素
                List<Element> constructorArgsElements = bean.elements("constructor-args");
                if(constructorArgsElements!=null && constructorArgsElements.size()>0){
                    //需要带参数构造方法构造对象
                    List<ConstructorArgs> constructorArgsList = new ArrayList<>();
                    for(Element consEle:constructorArgsElements){
                        ConstructorArgs ca = new ConstructorArgs();
                        String name = consEle.attributeValue("name");
                        //不一定有值
                        ca.setName(name);
                        //取类型
                        String type = consEle.attributeValue("type");
                        //ConstructorArgs类中的type的类型就是Class
                        ca.setType(type!=null?Class.forName(type):null);
                        ca.setRef(consEle.attributeValue("ref"));
                        ca.setValue(consEle.attributeValue("value"));
                        constructorArgsList.add(ca);
                    }

                    beanDefinition.setConstructorArgsList(constructorArgsList);
                }else{
                    //不需要带参数的构造方法 1.无参构造 2.3.4.
                    List<Element> pros = bean.elements("property");
                    if(pros!=null && pros.size()>0){
                        //有<property>标签
                        List<PropertyDefinition> propertyDefinitions = new ArrayList<>();
                        for(Element pro:pros){
                            PropertyDefinition pd = new PropertyDefinition();
                            pd.setName(pro.attributeValue("name"));
                            pd.setValue(pro.attributeValue("value"));
                            pd.setRef(pro.attributeValue("ref"));
                            propertyDefinitions.add(pd);
                        }
                        beanDefinition.setProps(propertyDefinitions);
                    }
                }


                beanDefinitions.put(id,beanDefinition);
            }
        }catch(Exception e){
            e.printStackTrace();
        }

    }
    //该方法对外生产Bean对象 Student Dao Service QueryRunner
    public  Object getBean(String id){
        //1.new 2.newInstance()
        //newInstance()===>cls==>Class.forName()==>stu /sch
        BeanDefinition beanDefinition = beanDefinitions.get(id);
        String className = beanDefinition.getClassName();

        try {
            Class cls = Class.forName(className);
            Object target = null;
            List<ConstructorArgs> constructorArgsList = beanDefinition.getConstructorArgsList();
            if(constructorArgsList!=null && constructorArgsList.size()>0){
                Class[] parameterTypes = new Class[constructorArgsList.size()];
                Object[] params = new Object[constructorArgsList.size()];
                int k=0;
                for(ConstructorArgs constructorArgs:constructorArgsList){
                    //获得参数类型
                    Class type = constructorArgs.getType();
                    //这里type和name只能存在一个
                    if(type!=null){
                        parameterTypes[k]=type;
                        //如果<constructor-args name="" type="" value="" ref="" />
                        //是否存在value,不存在就拿ref(value和ref只会存在一个),如果用ref,递归这个bean,为什么递归?这里ref引用的bean很可能引用其他的bean,所以需要递归
                        params[k] = constructorArgs.getValue()==null?this.getBean(constructorArgs.getRef()):constructorArgs.getValue();
                    }else{
                        //形式参数的名字,也就是name有值而type为null的情况
                    }
                    k++;
                }
                //带参数的构方法构造对象
                Constructor con = cls.getDeclaredConstructor(parameterTypes);
                target = con.newInstance(params);
            //else是无参构造但是传值的
            }else {
                //if beanFactory BeanFactory

                //使用无参构造方法构造对象
               target = cls.newInstance();
               List<PropertyDefinition> pds = beanDefinition.getProps();
               if(pds!=null && pds.size()>0) {
                   for(PropertyDefinition pd:pds) {
                       //<property name="xxxx"
                       String name = pd.getName();
                       Class fieldType = cls.getDeclaredField(name).getType();
                       Object value = pd.getValue();
                       //name setName age setAge birth setBirth
                       String setter0 = "set"+name.substring(0,1).toUpperCase()+name.substring(1);
                       //setName setAge
                       //这里的fieldType是参数的类型,如int和Integer是并不一样的,存在方法重载,需要判断出哪个方法
                       Method setter = cls.getDeclaredMethod(setter0, fieldType);
                       //给属性赋值,value存在直接赋值,不存在再递归其他的Bean
                       setter.invoke(target, value==null?this.getBean(pd.getRef()):value);
                   }
               }
            }
            return target;

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

}

<?xml version="1.0"  encoding="GBK"?>
<beans>
    <bean id="stu" class="com.etoak.student.entity.Student">
        <constructor-args type="com.etoak.student.entity.School" ref="sch"></constructor-args>
    </bean>
    <bean id="sch" class="com.etoak.student.entity.School">
        <property name="name" value="山东大学"></property>
        <property name="phone" value="110"></property>
    </bean>
    <bean id="service" class="com.etoak.student.service.StudentServiceImpl">
        <property name="dao" ref="dao"></property>
    </bean>
    <bean id="dao" class="com.etoak.student.dao.StudentDaoImpl">
        <property name="qr" ref="qr"></property>
    </bean>
    <bean id="qr" class="org.apache.commons.dbutils.QueryRunner">
        <constructor-args type="javax.sql.DataSource" ref="ds"></constructor-args>
    </bean>
    <bean id="ds" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql:///et2101"></property>
        <property name="username" value="root"></property>
        <property name="password" value="etoak"></property>
    </bean>

</beans>

程序员灯塔
转载请注明原文链接:简单Ioc
喜欢 (0)