1. 本节须要实现的内容
- 新建 @Aspect 注解
- 减少 ClassUtil#newInstance 办法来通过 Class 对象新建一个真正的实例对象
- 减少 ValidationUtil 类作为参数校验类
- 编写 BeanContainer 类以及其外部办法: 实现容器的创立以及增删查改操作
2. 第一局部工作
2.1 该局部须要实现的内容:
- 新建 @Aspect 注解
- 减少 ClassUtil#newInstance 办法
- 编写 @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 该局部须要实现的内容
- 实现 BeanContainer 类的编写
- 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…