乐趣区

从零写一个具有IOCAOPMVC功能的框架学习笔记04容器的创建以及容器成员的增删查改

1. 本节须要实现的内容

  1. 新建 @Aspect 注解
  2. 减少 ClassUtil#newInstance 办法来通过 Class 对象新建一个真正的实例对象
  3. 减少 ValidationUtil 类作为参数校验类
  4. 编写 BeanContainer 类以及其外部办法: 实现容器的创立以及增删查改操作

2. 第一局部工作

2.1 该局部须要实现的内容:

  1. 新建 @Aspect 注解
  2. 减少 ClassUtil#newInstance 办法
  3. 编写 @ValidationUtils 校验类

2.2 新建 @Aspect 注解

阐明:因为咱们后续的 AOP 性能实现时,须要扫描被 @Aspect 注解标记的类,并放入容器中,所以咱们这里就提前新建 @Apspect 注解

2.2 减少 ClassUtil#newInstance 办法

2.2.1 ClassUtil#newInstance 须要实现的代码如下:
    /**
     * 实例化 class
     *
     * @param clazz
     * @param accessible 是否能够通过反射来拜访该 class 的 private 润饰的构造函数
     * @param <T>
     * @return
     */
    public static <T> T newInstance(Class<T> clazz, boolean accessible) {
        try {Constructor constructor = clazz.getDeclaredConstructor();
            constructor.setAccessible(accessible); // 避免获取到的是 private 类型的构造函数
            return (T) constructor.newInstance();} catch (Exception e) {log.error("newInstance error", e);
            throw new RuntimeException(e);
        }
    }
2.2.5 ClassUtil#newInstance 办法解读

2.3 编写 ValidationUtil 类

2.3.1 须要实现的代码如下
package com.wuyiccc.helloframework.util;

import java.util.Collection;
import java.util.Map;

/**
 * @author wuyiccc
 * @date 2020/7/13 10:41
 * 岂曰无衣,与子同袍~
 */
public class ValidationUtil {

    /**
     * String 是否为 null 或者 ""
     *
     * @param obj
     * @return
     */
    public static boolean isEmpty(String obj) {return obj == null || "".equals(obj);
    }


    /**
     * java 的数组是否为 null 或者 size=0
     *
     * @param obj
     * @return
     */
    public static boolean isEmpty(Object[] obj) {return obj == null || obj.length == 0;}


    /**
     * 判断 Collection 是否为 null 或者 size=0
     *
     * @param obj
     * @return 是否为空
     */
    public static boolean isEmpty(Collection<?> obj) {return obj == null || obj.isEmpty();
    }

    /**
     * Map 是否为 null 或 size 为 0
     * @param obj
     * @return
     */
    public static boolean isEmpty(Map<?, ?> obj) {return obj == null || obj.isEmpty();
    }
}

2.3.2 ValidationUtil 代码解读:

3. 第二局部工作

3.1 该局部须要实现的内容

  1. 实现 BeanContainer 类的编写
  2. BeanContainer 类所具备的次要性能:加载指定包门路下的 bean,通过注解筛选出 Bean 的 Class 对象汇合,通过接口或者父类获取实现类或者子类的 Class 汇合

3.2 该局部须要实现的代码如下

package com.wuyiccc.helloframework.core;

import com.wuyiccc.helloframework.aop.annotation.Aspect;
import com.wuyiccc.helloframework.core.annotation.Component;
import com.wuyiccc.helloframework.core.annotation.Controller;
import com.wuyiccc.helloframework.core.annotation.Repository;
import com.wuyiccc.helloframework.core.annotation.Service;
import com.wuyiccc.helloframework.util.ClassUtil;
import com.wuyiccc.helloframework.util.ValidationUtil;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.lang.annotation.Annotation;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author wuyiccc
 * @date 2020/7/13 10:19
 * 岂曰无衣,与子同袍~
 */

@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class BeanContainer {


    /**
     * 寄存所有被配置标记的指标对象的 Map
     */
    private final Map<Class<?>, Object> beanMap = new ConcurrentHashMap<>();

    /**
     * 注解列表
     */
    private static final List<Class<? extends Annotation>> BEAN_ANNOTATION = Arrays.asList(Component.class, Controller.class, Service.class, Repository.class, Aspect.class);

    /**
     * 容器是否曾经加载过 bean
     */
    private boolean loaded = false;

    /**
     * 获取 Bean 容器实例
     *
     * @return BeanContainer
     */
    public static BeanContainer getInstance() {return ContainerHolder.HOLDER.instance;}

    private enum ContainerHolder {
        HOLDER;
        private BeanContainer instance;

        ContainerHolder() {instance = new BeanContainer();
        }
    }

    /**
     * Bean 实例数量
     *
     * @return
     */
    public int size() {return beanMap.size();
    }

    public boolean isLoaded() {return loaded;}

    /**
     * 加载指定 packageName 包含其子包下的 bean
     *
     * @param packageName
     */
    public synchronized void loadBeans(String packageName) {if (isLoaded()) {log.warn("BeanContainer has been loaded");
            return;
        }

        Set<Class<?>> classSet = ClassUtil.extractPackageClass(packageName);
        if (ValidationUtil.isEmpty(classSet)) {log.warn("extract nothing from packageName" + packageName);
        }

        for (Class<?> clazz : classSet) {for (Class<? extends Annotation> annotation : BEAN_ANNOTATION) {if (clazz.isAnnotationPresent(annotation)) {beanMap.put(clazz, ClassUtil.newInstance(clazz, true));
                    break;
                }
            }
        }
        loaded = true;
    }


    /**
     * 增加一个 class 对象及其 Bean 实例
     *
     * @param clazz Class 对象
     * @param bean  Bean 实例
     * @return 原有的 Bean 实例,没有则返回 null
     */
    public Object addBean(Class<?> clazz, Object bean) {return beanMap.put(clazz, bean);
    }

    /**
     * 删除一个 IOC 容器治理的对象
     *
     * @param clazz Class 对象
     * @return 删除的 Bean 的实例,没有则返回 null
     */
    public Object removeBean(Class<?> clazz) {return beanMap.remove(clazz);
    }

    /**
     * 依据 Class 对象获取 Bean 实例
     *
     * @param clazz
     * @return
     */
    public Object getBean(Class<?> clazz) {return beanMap.get(clazz);
    }


    /**
     * 获取容器治理的所有 Class 对象汇合
     *
     * @return
     */
    public Set<Class<?>> getClasses() {return beanMap.keySet();
    }

    /**
     * 获取所有的 Bean 汇合
     *
     * @return Bean 汇合
     */
    public Set<Object> getBeans() {return new HashSet<>(beanMap.values());
    }


    /**
     * 依据注解筛选出 Bean 的 Class 对象汇合
     *
     * @param annotation 注解
     * @return Class 汇合
     */
    public Set<Class<?>> getClassesByAnnotation(Class<? extends Annotation> annotation) {Set<Class<?>> keySet = getClasses();

        if (ValidationUtil.isEmpty(keySet)) {log.error("nothing in beanMap");
            return null;
        }

        // 通过注解筛选出符和条件的 Class 对象
        Set<Class<?>> classSet = new HashSet<>();
        for (Class<?> clazz : keySet) {
            // 查看 Class 对象是否有相干的注解标记
            if (clazz.isAnnotationPresent(annotation)) {classSet.add(clazz);
            }
        }
        return classSet.size() > 0 ? classSet : null; // 对立定义,如果 size==0,那么返回 null 而不是空的 classSet}


    /**
     * 通过接口或者父类获取实现类或者子类的 Class 汇合,不包含其自身
     * @param interfaceOrClass 接口 Class 或者父类 Class
     * @return Class 汇合
     */
    public Set<Class<?>> getClassesBySuper(Class<?> interfaceOrClass) {

        // 获取 beanMap 中所有 class 对象
        Set<Class<?>> keySet = getClasses();
        if (ValidationUtil.isEmpty(keySet)) {log.warn("nothing in beanMap");
            return null;
        }

        // 判断 ketSet 里的元素是否是传入的接口的实现类或者是类的子类, 如果是,就增加到汇合中
        Set<Class<?>> classSet = new HashSet<>();
        for (Class<?> clazz : keySet) {if (interfaceOrClass.isAssignableFrom(clazz) && !clazz.equals(interfaceOrClass)) { // 判断 interfaceOrClass 是否是 clazz 父级别的类
                classSet.add(clazz);
            }
        }
        return classSet.size() > 0 ? classSet : null;}




}

3.3 相干代码解说如下

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

退出移动版