我是靠谱客的博主 糊涂柠檬,最近开发中收集的这篇文章主要介绍手写ioc代码,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

bean.xml

<beans>

    <bean id="studentService" class="com.hgd.spring.service.StudentServiceImpl">
        <property name="studentDao" ref="studentDao"/>
    </bean>

    <bean id="userService" class="com.hgd.spring.service.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
    </bean>

    <bean id="userDao" class="com.hgd.spring.dao.UserDaoImpl"></bean>

    <bean id="studentDao" class="com.hgd.spring.dao.StudentDaoImpl">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/test3?characterEncoding=utf-8"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>

</beans>

封装beans标签数据类(BeanDefinition)

public class BeanDefinition {
    private String className;//class
    private String beanName; //id
    private String initMethod; //init_method
    //该配置是默认配置,单例
    private String scope;
    private static final String SCOPE_SINGLETON = "singleton";
    private static final String SCOPE_PROTOTYPE = "prototype";
    /**
     * bean中的属性信息
     */
    private List<PropertyValue> propertyValues = new ArrayList<PropertyValue>();

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public BeanDefinition(String className, String beanName) {
        this.className = className;
        this.beanName = beanName;
    }

    public String getBeanName() {
        return beanName;
    }

    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }

    public String getInitMethod() {
        return initMethod;
    }

    public void setInitMethod(String initMethod) {
        this.initMethod = initMethod;
    }

    public List<PropertyValue> getPropertyValues() {
        return propertyValues;
    }

    public void addPropertyValue(PropertyValue propertyValue) {
        this.propertyValues.add(propertyValue);
    }

    public String getScope() {
        return scope;
    }

    public void setScope(String scope) {
        this.scope = scope;
    }

    public void setPropertyValues(List<PropertyValue> propertyValues) {
        this.propertyValues = propertyValues;
    }

    public boolean isSingleton() {
        return SCOPE_SINGLETON.equals(this.scope);
    }

    public boolean isPrototype() {
        return SCOPE_PROTOTYPE.equals(this.scope);
    }

    @Override
    public String toString() {
        return "BeanDefinition{" +
                "className='" + className + ''' +
                ", beanName='" + beanName + ''' +
                ", initMethod='" + initMethod + ''' +
                ", scope='" + scope + ''' +
                ", propertyValues=" + propertyValues +
                '}';
    }
}

封装properties的数据信息(PropertyValue)

public class PropertyValue {
    private String name;
    private Object value;

    public PropertyValue(String name, Object value) {
        this.name = name;
        this.value = value;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "PropertyValue{" +
                "name='" + name + ''' +
                ", value=" + value +
                '}';
    }
}

封装ref的数据类(RuntimeBeanReference)

public class RuntimeBeanReference {
    private String ref;

    public RuntimeBeanReference(String ref) {
        this.ref = ref;
    }

    public String getRef() {
        return ref;
    }

    public void setRef(String ref) {
        this.ref = ref;
    }
}

封装value的数据类(TypedStringValue)

public class TypedStringValue {
    private String value;

    private Class<?> targetType;

    public TypedStringValue(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public Class<?> getTargetType() {
        return targetType;
    }

    public void setTargetType(Class<?> targetType) {
        this.targetType = targetType;
    }
}

解析ioc和封装ioc思路

public class IocDemo {

    //单例bean存放map集合
    private static Map<String,Object> singletonObjects=new HashMap<String, Object>();

    //封装xml中的bean标签表示的信息
    private Map<String, BeanDefinition> beanDefinitionMap=new HashMap<String, BeanDefinition>();

    @Before
    public void demo(){
        loadAndRegisterBeanDefinitions("beans.xml");
        Set<Map.Entry<String, BeanDefinition>> entries = beanDefinitionMap.entrySet();
        for (Map.Entry<String, BeanDefinition> entry : entries) {
            System.out.println(entry.getKey()+"="+entry.getValue());
        }
    }

    @Test
    public void iocTest(){
//        StudentService studentService = (StudentService)getBean("studentService");
//        List<Student> all = studentService.findAll();
//        for (Student student : all) {
//            System.out.println("student = " + student);
//        }
        UserService userService=(UserService)getBean("userService");
        userService.say();
        //UserDao userDao=(UserDao)getBean("userDao");
        //userDao.say();
//        BasicDataSource basicDataSource=(BasicDataSource)getBean("dataSource");
//        System.out.println(basicDataSource.getDriverClassName());
//        System.out.println(basicDataSource.getUrl());
//        System.out.println(basicDataSource.getUsername());
//        System.out.println(basicDataSource.getPassword());
    }

    private Object getBean(String beanName) {
        System.out.println("beanName = " + beanName);
        Object  singletonObject= singletonObjects.get(beanName);
        if (singletonObject != null) {
            return singletonObject;
        }
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if (beanDefinition == null) {
            return null;
        }
        List<PropertyValue> propertyValues = beanDefinition.getPropertyValues();
        System.out.println("propertyValues = " + propertyValues);
        //判断是否是单例还是多例
        if (beanDefinition.isSingleton()){
            //单例
            singletonObject=createBean(beanDefinition);
            this.singletonObjects.put(beanName, singletonObject);
        }else if (beanDefinition.isPrototype()){
            //多例
            singletonObject=createBean(beanDefinition);
        }
        return singletonObject;
    }

    private Object createBean(BeanDefinition beanDefinition) {
        String className = beanDefinition.getClassName();
        Class<?> clazz = resolveClass(className);
        if (clazz == null) {
            return null;
        }
        //实例化 new
        Object bean=createBeanInstance(clazz);
        // 属性填充 set
        populateBean(bean, beanDefinition);
        // 初始化 init
        initBean(bean, beanDefinition);
        return bean;
    }

    //实例化
    private Object createBeanInstance(Class<?> clazz) {
        // TODO 可以根据bean标签的配置选择使用实例工厂去创建Bean
        // TODO 可以根据bean标签的配置选择使用静态工厂去创建Bean

        // 还可以选择使用我们的构造方法去创建Bean
        return createObject(clazz);
    }

    private Object createObject(Class<?> clazz, Object... args) {
        try {
            System.out.println("args = " + args);
            // TODO 可以根据输入参数获取指定构造参数的构造方法
            Constructor<?> constructor = clazz.getDeclaredConstructor();
            // 默认调用无参构造进行对象的创建
            return constructor.newInstance(args);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    //实例化
//    private Object createInstance(BeanDefinition beanDefinition) {
//        try {
//            String clazzName = beanDefinition.getClassName();
//            Class<?> clazzType = resolveClass(clazzName);
//            Constructor<?> constructor = clazzType.getConstructor();
//            Object bean = constructor.newInstance();
//            return bean;
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return null;
//    }

    private Class<?> resolveClass(String className) {
        try {
            Class<?> clazz = Class.forName(className);
            return clazz;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    //属性填充
    private void populateBean(Object bean, BeanDefinition beanDefinition) {
        List<PropertyValue> propertyValues = beanDefinition.getPropertyValues();
        for (PropertyValue propertyValue : propertyValues) {
            String name = propertyValue.getName();
            Object value = propertyValue.getValue();
            Object valueToUse = null;
            if (value instanceof TypedStringValue) {
                TypedStringValue typedStringValue = (TypedStringValue) value;
                String stringValue = typedStringValue.getValue();
                Class<?> targetType = typedStringValue.getTargetType();
                if (targetType == String.class) {
                    valueToUse = stringValue;
                } else if (targetType == Integer.class) {
                    valueToUse = Integer.parseInt(stringValue);
                } // ....
            } else if (value instanceof RuntimeBeanReference) {
                RuntimeBeanReference reference = (RuntimeBeanReference) value;
                String ref = reference.getRef();

                // 创建一个bean的时候,根据依赖注入情况,自动去创建另一个bean去注入
                valueToUse = getBean(ref);
            }
            setProperty(bean, name, valueToUse);
        }
    }

    private void setProperty(Object bean, String name, Object valueToUse) {
        try {
            Class<?> clazz = bean.getClass();
            System.out.println("clazz = " + clazz);
            //返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
            //name 参数是一个 String,它指定所需字段的简称
            Field field = clazz.getDeclaredField(name);
            field.setAccessible(true);
            field.set(bean, valueToUse);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //初始化
    private void initBean(Object bean, BeanDefinition beanDefinition) {
        // TODO Aware接口会在此时被处理

        invokeInitMethod(bean, beanDefinition);
    }

    private void invokeInitMethod(Object bean, BeanDefinition beanDefinition) {
        // bean标签配置了init-method属性
        String initMethod = beanDefinition.getInitMethod();
        if (initMethod == null || initMethod.equals("")) {
            return;
        }
        invokeMethod(bean, initMethod);
        // TODO bean标签实现了InitializingBean接口
    }

    private void invokeMethod(Object bean, String initMethod) {
        try {
            Class<?> clazz = bean.getClass();
            Method method = clazz.getDeclaredMethod(initMethod);
            method.invoke(bean);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void loadAndRegisterBeanDefinitions(String location) {
        //加载流对象
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(location);
        //通过sax解析
        Document document = DocumentUtils.createDocument(resourceAsStream);
        //解析beans文件
        parseXMLBeans(document.getRootElement());
    }

    //解析beans文件
    private void parseXMLBeans(Element rootElement) {
        List<Element> elements = rootElement.elements();
        for (Element beanElement : elements) {
            //获取标签的名称
            String name = beanElement.getName();
            if (name.equals("bean")){
                //解析<bean>
                parseXMLBean(beanElement);
            }else {
                //解析自定义标签
                parseXMLCustom(beanElement);
            }
        }
    }

    //解析自定义标签
    private void parseXMLCustom(Element beanElement) {

    }

    //解析<bean>
    private void parseXMLBean(Element beanElement) {
        if (beanElement == null) {
            return;
        }
        String id = beanElement.attributeValue("id");
        String clazz = beanElement.attributeValue("class");
        String initMethod = beanElement.attributeValue("init-method");
        String scope = beanElement.attributeValue("scope");
        if (scope==null) scope="singleton";
        //将数据封装到
        BeanDefinition beanDefinition=new BeanDefinition(clazz, id);
        beanDefinition.setInitMethod(initMethod);
        beanDefinition.setScope(scope);
        //解析bean的子标签
        List<Element> propertyElements = beanElement.elements();
        for (Element propertyElement : propertyElements) {
            parseXMLProperties(beanDefinition,propertyElement);
        }
        //注册beanDefinition信息
        this.beanDefinitionMap.put(id, beanDefinition);
    }

    //解析properties文件
    private void parseXMLProperties(BeanDefinition beanDefinition, Element propertyElement) {
        if (propertyElement == null) {
            return;
        }

        //获取name属性
        String name = propertyElement.attributeValue("name");
        String value = propertyElement.attributeValue("value");
        String ref = propertyElement.attributeValue("ref");

        // 如果value和ref都有值,则返回
        if (value != null && !value.equals("") && ref != null && !ref.equals("")) {
            return;
        }

        PropertyValue propertyValue=null;
        if (value!=null && !value.equals("")){
            // 因为spring配置文件中的value是String类型,而对象中的属性值是各种各样的,所以需要存储类型
            TypedStringValue typeStringValue = new TypedStringValue(value);
            Class<?> targetType = getTypeByFieldName(beanDefinition.getClassName(),name);
            typeStringValue.setTargetType(targetType);
            propertyValue = new PropertyValue(name, typeStringValue);
            beanDefinition.addPropertyValue(propertyValue);
        }else if (ref!=null && !ref.equals("")){
            RuntimeBeanReference reference=new RuntimeBeanReference(ref);
            propertyValue=new PropertyValue(name, reference);
            beanDefinition.addPropertyValue(propertyValue);
        }else {
            return;
        }
    }

    private Class<?> getTypeByFieldName(String beanClassName, String name) {
        try {
            Class<?> clazz = Class.forName(beanClassName);
            Field field = clazz.getDeclaredField(name);
            return field.getType();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}

 

最后

以上就是糊涂柠檬为你收集整理的手写ioc代码的全部内容,希望文章能够帮你解决手写ioc代码所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(34)

评论列表共有 0 条评论

立即
投稿
返回
顶部