ioc 实现

来源:互联网 发布:linux查看进程端口号 编辑:程序博客网 时间:2024/05/16 01:16

学习黄勇smart-framework的笔记

黄勇的码云地址:https://gitee.com/huangyong/smart-framework

黄勇的oschina博客地址:https://my.oschina.net/huangyong/blog/158380



ioc 主要提供两个功能,一个是初始化bean,另一个是注入bean。

1、所需的注解

/** * 定义需要 IOC 容器管理的 Bean 类 * * @author huangyong * @since 1.0 *///标识注解可以使用在接口和类上@Target(ElementType.TYPE)//标识注解在运行时可以被jvm或通过反射读取和使用(注解最常见的用法)@Retention(RetentionPolicy.RUNTIME)public @interface Bean {}
/** * 指定接口的实现类 * * @author huangyong * @since 1.0 *///标识注解可以使用在接口和类上@Target(ElementType.TYPE)//标识注解在运行时可以被jvm或通过反射读取和使用(注解最常见的用法)@Retention(RetentionPolicy.RUNTIME)public @interface Impl {    Class<?> value();}
/** * 依赖注入 * * @author huangyong * @since 1.0 *///标识注解可以使用在字段上@Target(ElementType.FIELD)//标识注解在运行时可以被jvm或通过反射读取和使用(注解最常见的用法)@Retention(RetentionPolicy.RUNTIME)public @interface Inject {}


2、初始化声明的bean

/** * 初始化相关 Bean 类 * * @author huangyong * @since 1.0 */public class BeanHelper {    /**     * Bean Map(Bean 类 => Bean 实例)     * 声明了一个全局变量HashMap,key为class对象,value为改class的实例,因为HashMap的key不能重复,可以保证统一时刻在这个map中只有一个class实例     */    private static final Map<Class<?>, Object> beanMap = new HashMap<Class<?>, Object>();    /**     * 将被Bean/Service/Action/Aspect注解标识的类放入全局HashMap中     */    static {        try {            // 获取应用包路径下所有的类            List<Class<?>> classList = ClassHelper.getClassList();            for (Class<?> cls : classList) {                // 处理带有 Bean/Service/Action/Aspect 注解的类                if (cls.isAnnotationPresent(Bean.class) ||                        cls.isAnnotationPresent(Service.class) ||                        cls.isAnnotationPresent(Action.class) ||                        cls.isAnnotationPresent(Aspect.class)) {                    // 使用反射 创建 Bean 实例                    Object beanInstance = cls.newInstance();                    // 将 Bean 实例放入 Bean Map 中(键为 Bean 类,值为 Bean 实例)                    beanMap.put(cls, beanInstance);                }            }        } catch (Exception e) {            //自定义Error,需要继承Error类            throw new InitializationError("初始化 BeanHelper 出错!", e);        }    }    /**     * 获取 Bean Map     * 获取所有保存在容器中的类     */    public static Map<Class<?>, Object> getBeanMap() {        return beanMap;    }    /**     * 获取 Bean 实例     * 根据类名获取实例     */    @SuppressWarnings("unchecked")    public static <T> T getBean(Class<T> cls) {        if (!beanMap.containsKey(cls)) {            throw new RuntimeException("无法根据类名获取实例!" + cls);        }        return (T) beanMap.get(cls);    }    /**     * 设置 Bean 实例     * 提供扩展bean的方法,可以用来替换注入     */    public static void setBean(Class<?> cls, Object obj) {        beanMap.put(cls, obj);    }}

3、实现bean注入

/** * 初始化 IOC 容器 * * @author huangyong * @since 1.0 */public class IocHelper {    /**     *      */    static {        try {            // 获取并遍历所有的 Bean 类            Map<Class<?>, Object> beanMap = BeanHelper.getBeanMap();            for (Map.Entry<Class<?>, Object> beanEntry : beanMap.entrySet()) {                // 获取 Bean 类与 Bean 实例                Class<?> beanClass = beanEntry.getKey();                Object beanInstance = beanEntry.getValue();                // 获取 Bean 类中所有的字段(不包括父类中的方法)                Field[] beanFields = beanClass.getDeclaredFields();                if (ArrayUtil.isNotEmpty(beanFields)) {                    // 遍历所有的 Bean 字段                    for (Field beanField : beanFields) {                        // 判断当前 Bean 字段是否带有 Inject 注解                        if (beanField.isAnnotationPresent(Inject.class)) {                            // 获取 Bean 字段对应的接口                            Class<?> interfaceClass = beanField.getType();                            // 获取 Bean 字段对应的实现类                            Class<?> implementClass = findImplementClass(interfaceClass);                            // 若存在实现类,则执行以下代码                            if (implementClass != null) {                                // 从 Bean Map 中获取该实现类对应的实现类实例                                // 放入 HashMap 时是将实现类作为key放入                                Object implementInstance = beanMap.get(implementClass);                                // 设置该 Bean 字段的值                                if (implementInstance != null) {                                    //通过反射初始化                                    beanField.setAccessible(true); // 将字段设置为 public                                    beanField.set(beanInstance, implementInstance); // 设置字段初始值                                } else {                                    // 初始化抛出Error                                    throw new InitializationError("依赖注入失败!类名:" + beanClass.getSimpleName() + ",字段名:" + interfaceClass.getSimpleName());                                }                            }                        }                    }                }            }        } catch (Exception e) {            throw new InitializationError("初始化 IocHelper 出错!", e);        }    }    /**     * 查找实现类     */    public static Class<?> findImplementClass(Class<?> interfaceClass) {        Class<?> implementClass = interfaceClass;        // 判断接口上是否标注了 Impl 注解        if (interfaceClass.isAnnotationPresent(Impl.class)) {            // 获取强制指定的实现类            //定义的规则:在接口上可以声明的@Impl,当要指定具体的实现是哪个类            implementClass = interfaceClass.getAnnotation(Impl.class).value();        } else {            // 获取该接口所有的实现类            List<Class<?>> implementClassList = ClassHelper.getClassListBySuper(interfaceClass);            if (CollectionUtil.isNotEmpty(implementClassList)) {                // 获取第一个实现类                // 在多个实现类中取第一个                implementClass = implementClassList.get(0);            }        }        // 返回实现类对象        return implementClass;    }}


原创粉丝点击