简单的ioc容器实现

简单的ioc容器实现

我的源码:https://github.com/lldwb/lldwb_ioc.git

介绍

提示:实现简单的ioc容器是为了学习并加深ioc的概念

IoC容器 = IOC + 容器(Bean容器/容器工厂)
容器工厂就使用反射获取类的容器工厂(终极版)
只需要在这个容器工厂的基础下扩展ioc的功能就可以了

ioc容器生命周期(单例)

  1. 创建:读取并创建和存储需要管理的依赖
  2. 依赖注入:全部完成创建后进行依赖注入

ioc容器生命周期(原型)

  1. 创建:读取并存储需要管理的依赖(class格式)
  2. 使用:读取 ioc 容器中的 class 进行创建,创建后进行依赖注入,依赖注入时会检索保证所使用的所有依赖(包括依赖的依赖)都可以正常使用

思路介绍

请先根据思路完成一遍,再看我的或者其他人的源码

  1. 完成容器工厂
  2. 添加 ioc(依赖注入)的功能,注意:单例是在全部完成创建后进行依赖注入,而原型在自己创建后进行依赖注入

源码介绍

注入处理器调用者

用于找到注入处理器的实现类,并遍历所有实现类进行调用

@Slf4j
public class InjectHandlerInvoker {
    private static List<InjectHandler> list=new ArrayList<>();

    static {
        for (Class<?> clazz:ScanUtils.scan(InjectHandler.class,"top.lldwb.ioc.inject.impl")){
            try {
                Object object = clazz.newInstance();
                if (InjectHandler.class.isInstance(object)){
                    list.add((InjectHandler) object);
                }
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static Object handle(Object object, ContainerFactory factory) {
        for (InjectHandler injectHandler : list) {
            injectHandler.handle(object, factory);
        }
        return object;
    }
}

注入处理器接口

注入处理器接口,如果需要扩展注入处理器的功能请实现该接口

public interface InjectHandler {
    Object handle(Object object, ContainerFactory factory);
}

字段注入处理器实现类

@Slf4j
public class MethodInjectHandler implements InjectHandler {
    @Override
    public Object handle(Object object, ContainerFactory factory) {
        log.debug("遍历公开方法,查看是否需要依赖注入");
        try {
            // 获取 object 及其指定到父类 Object 的 BeanInfo
            // 方法信息
            for (Method method : object.getClass().getMethods()) {
                if (method.isAnnotationPresent(Inject.class)) {
                    log.debug("method:" + method.getName());
                    List<Object> objectList = new ArrayList<>();
                    log.debug("获取方法的每个参数");
                    for (Parameter parameter : method.getParameters()) {
                        log.debug("遍历参数");
                        if (factory.isMultipleClass(parameter.getClass())) {
                            log.debug("一个实现类时执行");
                            log.debug("参数类型:" + parameter.getType().getName());
                            objectList.add(factory.getBean(parameter.getType()));
                        } else {
                            log.debug("多个实现类时执行");
                            Inject inject = method.getAnnotation(Inject.class);
                            log.debug("注解指定的实现类:" + inject.value());
                            objectList.add(factory.getBean(inject.value()));
                        }
                    }
                    method.invoke(object, objectList.stream().toArray());
                }
            }
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        return object;
    }
}

方法注入处理器实现类

@Slf4j
public class FieldInjectHandler implements InjectHandler {
    @Override
    public Object handle(Object object, ContainerFactory factory) {log.debug("遍历所有字段,查看是否需要依赖注入(不推荐)");
        for (Field field : object.getClass().getDeclaredFields()) {
            if (field.isAnnotationPresent(Inject.class)) {
                log.debug("field:" + field.getName());
                Inject inject = field.getAnnotation(Inject.class);
                Object value;
                if (inject.value() != "") {
                    value = factory.getBean(inject.value());
                } else {
                    value = factory.getBean(field.getType());
                }
                try {
                    field.setAccessible(true);
                    field.set(object, value);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return object;
    }
}

工厂

@Slf4j
public class ContainerFactory {

    /**
     * 单例容器
     */
    private Map<String, Object> container = new HashMap<>();
    /**
     * 原型容器
     */
    private Map<String, Class<?>> archetype = new HashMap<>();

    /**
     * 初始化容器
     * 参数表示要管理的包路径
     */
    public ContainerFactory(String... packages) {
        List<Class<?>> classList = ScanUtils.scan(packages);
        resolveClass(classList);
    }

    /**
     * 容器工厂方法
     */
    public Object getBean(String name) {
        if (container.containsKey(name)) {
            return container.get(name);
        } else {
            Object object = newInstance(archetype.get(name));
            if (object == null) {
                throw new RuntimeException();
            }
            return inject(object);
        }
    }

    /**
     * 容器工厂方法
     */
    public <T> T getBean(String name, Class<T> tClass) {
        // 判断单例容器中是否有
        if (container.containsKey(name)) {
            return (T) container.get(name);
        } else {
            T t = (T) newInstance(archetype.get(name));
            if (t == null) {
                throw new RuntimeException();
            }
            inject(t);
            return t;
        }
    }

    /**
     * 容器工厂方法
     */
    public <T> T getBean(Class<T> tClass) {
        // 判断单例容器中是否有
        T t = null;
        for (Object objects : container.values()) {
            // 判断是否可以进行类型转换
            if (tClass.isInstance(objects)) {
                if (t != null) {
                    throw new RuntimeException();
                }
                t = (T) objects;
            }
        }
        for (Class<?> clazz : archetype.values()) {
            // 判断是否可以进行类型转换
            try {
                Object objects = clazz.newInstance();
                if (tClass.isInstance(objects)) {
                    if (t != null) {
                        throw new RuntimeException();
                    }
                    t = (T) objects;
                    inject(t);
                }
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            }
        }
        if (t == null) {
            throw new RuntimeException();
        }

        return t;
    }

    /**
     * 解析class集合,找到带有@Bean注解的类
     * 同时对单例容器进行依赖注入
     *
     * @param classList
     */
    private void resolveClass(List<Class<?>> classList) {
        classList.forEach(clazz -> {
            if (clazz.isAnnotationPresent(Bean.class)) {
                Bean bean = clazz.getAnnotation(Bean.class);
                // 获取 Bean 的作为 k
                String k = bean.value();
                // 判断是否需要唯一
                if (bean.sole()) {
                    // 唯一,添加到单例容器
                    container.put(k, newInstance(clazz));
                } else {
                    // 不唯一,添加到原型容器
                    archetype.put(k, clazz);
                }
            }
        });

        // 对单例容器进行依赖注入
        for (Object object : container.values()) {
            inject(object);
        }
    }

    /**
     * 判断接口是否多个实现类
     *
     * @param tClass
     * @return 有多个返回 false
     */
    public Boolean isMultipleClass(Class<?> tClass) {
        // 判断单例容器中是否有
        Boolean is = false;
        for (Object objects : container.values()) {
            // 判断是否可以进行类型转换
            if (tClass.isInstance(objects)) {
                if (is) {
                    return false;
                } else {
                    is = true;
                }
            }
        }
        for (Class<?> clazz : archetype.values()) {
            // 判断是否可以进行类型转换
            try {
                Object objects = clazz.newInstance();
                if (tClass.isInstance(objects)) {
                    if (is) {
                        return false;
                    } else {
                        is = true;
                    }
                }
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            }
        }
        return is;
    }

    /**
     * 创建实例
     *
     * @param clazz 类
     * @return
     */
    private Object newInstance(Class<?> clazz) {
        try {
            return clazz.getConstructor().newInstance();
        } catch (Exception e) {
            throw new RuntimeException("实例创建失败:", e);
        }
    }

    /**
     * 进行依赖注入
     *
     * @param object
     * @return
     */
    private Object inject(Object object) {
        log.debug(object.getClass().getName() + "进行依赖注入");
        InjectHandlerInvoker.handle(object,this);
        return object;
    }
}