自己模拟的Spring Ioc注解版,加深对Spring底层的了解。这里只支持使用@Autowired注解通过类型进行自动装配。
用来给容器中添加组件
package com.hrious.core.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 将组件添加到容器中
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
String value() default "";
}
package com.hrious.core.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 通过类型进行自动注入
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}
import com.hrious.core.anno.Autowired;
import com.hrious.core.anno.Component;
import java.io.File;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* 这里只支持使用@Component向容器中添加组件,和使用@Autowired自动装配
*/
public class AnnotaionConfigIocContainer {
// 系统文件分隔符
private static final String SEPARATOR = File.separator;
// 保存扫描出来的类的Class对象
private Map<String, Class> classMap = new HashMap<>();
// 保存首先实例化对象
private Map<String, Object> temporaryMap = new HashMap<>();
// 保存依赖添加完成后的对象
private Map<String, Object> objectMap = new HashMap<>();
// 提供唯一的构造方法
public AnnotaionConfigIocContainer(String scanPackage) {
// 扫描
this.scan(scanPackage);
// 填充相关依赖
injectDepends();
}
public <T> T getBean(Class<T> clazz) {
T bean = null;
int count = 0;
for (Map.Entry<String, Class> entry : classMap.entrySet()) {
Class value = entry.getValue();
if (clazz.isAssignableFrom(value)) {
bean = (T) objectMap.get(entry.getKey());
count++;
}
}
if (null == bean) {
throw new RuntimeException("没有类型为:" + clazz.getName() + "的bean");
}
if (count == 1) {
return bean;
} else {
// 通过类型获取的bean可能会有多个
throw new RuntimeException("需要一个" + clazz.getName() + "类型的bean,找到了" + count + "个");
}
}
public Object getBean(String beanName) {
Object bean = objectMap.get(beanName);
if (null == bean) {
throw new RuntimeException("没有名字为:" + beanName + "的bean");
}
return bean;
}
// 注入相关依赖
private void injectDepends() {
// 查找每个类中的依赖
for (Map.Entry<String, Class> entry : classMap.entrySet()) {
Class clazz = entry.getValue();
String beanName = entry.getKey();
// 获取所有属性
Field[] fields = clazz.getDeclaredFields();
// 从容器中获取需要注入属性的对象
Object bean = temporaryMap.get(beanName);
for (Field field : fields) {
// 判断是否存在@Autowired
if (field.isAnnotationPresent(Autowired.class)) {
// 需要判断依赖个数
Class needType = field.getType();
Object needBean = null;
int count = 0;
// 寻找依赖
for (Map.Entry<String, Class> entry2 : classMap.entrySet()) {
Class tempType = entry2.getValue();
// 比较是否为同一个类型
if (tempType == needType) {
count++;
needBean = temporaryMap.get(entry2.getKey());
} else {
// 满足注入条件
if (needType.isAssignableFrom(tempType)) {
count++;
needBean = temporaryMap.get(entry2.getKey());
}
}
}
if (count == 1) {
field.setAccessible(true);
try {
field.set(bean, needBean);
} catch (IllegalAccessException e) {
}
} else {
throw new RuntimeException(clazz.getName() + "需要一个的bean" + needType.getName() + "类型,找到了" + count + "个");
}
}
}
// 将标注有@Component注解的类添加到objectMap中
objectMap.put(beanName, bean);
}
}
// 扫描
private void scan(String basePackage) {
// 当前项目的classpath
String basePath = AnnotaionConfigIocContainer.class.getResource("/").getPath();
// 扫描的包路径
String scanPachagePath = new String(basePackage);
scanPachagePath = basePath + scanPachagePath.replaceAll("\\.", "\\" + SEPARATOR);
File file = new File(scanPachagePath);
String[] scanFiles = file.list();
for (String scanFile : scanFiles) {
if (scanFile.contains(".class")) {
String className = scanFile.replace(".class", "");
if (!this.getClass().getSimpleName().equals(className)) {
String qualifyClassName = basePackage + "." + className;
try {
Class<?> clazz = Class.forName(qualifyClassName);
// 判断是否有@Component注解
if (clazz.isAnnotationPresent(Component.class)) {
// 判断是否自定义名称
Component component = clazz.getAnnotation(Component.class);
String value = component.value();
String beanName = null;
if ("".equals(value)) {
// 没有指定名称
// 需要转换名称
beanName = tranformBeanName(className);
} else {
// 指定了name
beanName = value;
}
// 容器中beanName唯一
// 判断beanName是否存在
if (classMap.containsKey(beanName)) {
throw new RuntimeException("名称为:" + beanName + "的bean已经存在");
} else {
temporaryMap.put(beanName, clazz.newInstance());
classMap.put(beanName, clazz);
}
}
} catch (ClassNotFoundException e) {
} catch (IllegalAccessException | InstantiationException e) {
// 构造方法私有化或者是抽象类和接口
throw new RuntimeException("无法创建" + qualifyClassName + "对象");
}
}
} else {
scan(basePackage + "." + scanFile);
}
}
}
// 转换beanName满足首字母小写的驼峰原则
private String tranformBeanName(String beanName) {
if (beanName.length() == 1) {
return beanName.toLowerCase();
} else {
return beanName.substring(0, 1).toLowerCase() + beanName.substring(1);
}
}
}