从零写一个具有IOCAOPMVC功能的框架学习笔记05-实现容器的依赖注入

3次阅读

共计 3469 个字符,预计需要花费 9 分钟才能阅读完成。

1. 实现思路及须要实现的内容

实现思路

  1. 定义相干的注解标签
  2. 实现创立被注解标记的成员变量实例,并将其注入到被 @Autowired 标记的成员变量中

须要实现的内容

  1. 编写 ClassUtil#setField 办法为对应的实例设置属性值
  2. 编写 @Autowired 注解
  3. 编写 DependencyInjector 实现属性的依赖注入

2. 第一局部:编写 @Autowired 注解和 ClassUtil#setField 办法

2.1 本局部须要实现的代码如下:

package org.myframework.injection.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author wuyiccc
 * @date 2020/6/13 23:20
 * 岂曰无衣,与子同袍~
 */

/**
 * Autowired 目前只反对成员变量级别的注入
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {String value() default "";
}

    /**
     * 设置类的属性值
     * @param field 成员变量
     * @param target 类实例
     * @param value 成员变量的值
     * @param accessible 是否容许设置公有属性
     */
    public static void setField(Field field, Object target, Object value, boolean accessible) {field.setAccessible(accessible);
        try {field.set(target, value);
        } catch (IllegalAccessException e) {log.error("setField error", e);
            throw new RuntimeException(e);
        }
    }

2.2 相干代码解读

3. 第二局部:实现 DependencyInjector

3.1 须要实现的代码如下:

package com.wuyiccc.helloframework.injection;

import com.wuyiccc.helloframework.core.BeanContainer;
import com.wuyiccc.helloframework.injection.annotation.Autowired;
import com.wuyiccc.helloframework.util.ClassUtil;
import com.wuyiccc.helloframework.util.ValidationUtil;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.Set;

/**
 * @author wuyiccc
 * @date 2020/7/13 14:57
 * 岂曰无衣,与子同袍~
 */
@Slf4j
public class DependencyInjector {

    /**
     * Bean 容器
     */
    private BeanContainer beanContainer;


    public DependencyInjector() {beanContainer = BeanContainer.getInstance();
    }

    /**
     * 执行 IOC
     */
    public void doIoc() {if (ValidationUtil.isEmpty(beanContainer.getClasses())) {log.warn("empty classes in BeanContainer");
            return;
        }

        // 遍历容器中的所有 class 的对象
        for (Class<?> clazz : beanContainer.getClasses()) {Field[] fields = clazz.getDeclaredFields();

            if (ValidationUtil.isEmpty(fields)) {continue;}

            for (Field field : fields) {
                // 找出被 Autowired 标记的成员变量
                if (field.isAnnotationPresent(Autowired.class)) {Autowired autowired = field.getAnnotation(Autowired.class);
                    String autowiredValue = autowired.value(); // value 值
                    // 获取该 field 的类型
                    Class<?> fieldClass = field.getType();
                    // 获取该类型在容器中对应的实例
                    Object fieldValue = getFieldInstance(fieldClass, autowiredValue);
                    if (fieldValue == null) {throw new RuntimeException("unable to inject relevant type, target fieldClass is:" + fieldClass.getName() + "autowiredValue is :" + autowiredValue);
                    } else {
                        // 通过反射将对应的成员变量实例注入到成员变量所在类的实例里
                        Object targetBean = beanContainer.getBean(clazz);
                        ClassUtil.setField(field, targetBean, fieldValue, true);
                    }
                }

            }

        }


    }

    /**
     * 依据 Class 在 beanContainer 里获取实例或者实现类
     *
     * @param fieldClass     实例中属性的类型
     * @param autowiredValue 要注入的值的名称
     * @return
     */
    private Object getFieldInstance(Class<?> fieldClass, String autowiredValue) {
        // 看是否获取同等级的实例
        Object fieldValue = beanContainer.getBean(fieldClass);
        if (fieldValue != null) {return fieldValue;} else {Class<?> implementedClass = geImplementedClass(fieldClass, autowiredValue);
            if (implementedClass != null) {return beanContainer.getBean(implementedClass);
            } else {return null;}
        }
    }

    /**
     * 获取接口 i 的实现类
     *
     * @param fieldClass 实例中要注入的属性的类型
     * @return
     */
    private Class<?> geImplementedClass(Class<?> fieldClass, String autowiredValue) {Set<Class<?>> classSet = beanContainer.getClassesBySuper(fieldClass);
        if (!ValidationUtil.isEmpty(classSet)) {if (ValidationUtil.isEmpty(autowiredValue)) {if (classSet.size() == 1) {return classSet.iterator().next();} else {throw new RuntimeException("multiple implemented classes for" + fieldClass.getName() + "please set @Autowired's value to pick one");
                }
            } else {for (Class<?> clazz : classSet) {if (autowiredValue.equals(clazz.getSimpleName())) {return clazz;}
                }
            }
        }

        return null;
    }
}

3.2 相干代码解说如下:

GitHub 地址:https://github.com/wuyiccc/he…

正文完
 0