共计 3469 个字符,预计需要花费 9 分钟才能阅读完成。
1. 实现思路及须要实现的内容
实现思路
- 定义相干的注解标签
- 实现创立被注解标记的成员变量实例,并将其注入到被 @Autowired 标记的成员变量中
须要实现的内容
- 编写 ClassUtil#setField 办法为对应的实例设置属性值
- 编写 @Autowired 注解
- 编写 DependencyInjector 实现属性的依赖注入
2. 第一局部:编写 @Autowired 注解和 ClassUtil#setField 办法
2.1 本局部须要实现的代码如下:
package org.myframework.injection.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author wuyiccc
* @date 2020/6/13 23:20
* 岂曰无衣,与子同袍~
*/
/**
* Autowired 目前只反对成员变量级别的注入
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {String value() default "";
}
/**
* 设置类的属性值
* @param field 成员变量
* @param target 类实例
* @param value 成员变量的值
* @param accessible 是否容许设置公有属性
*/
public static void setField(Field field, Object target, Object value, boolean accessible) {field.setAccessible(accessible);
try {field.set(target, value);
} catch (IllegalAccessException e) {log.error("setField error", e);
throw new RuntimeException(e);
}
}
2.2 相干代码解读
3. 第二局部:实现 DependencyInjector
3.1 须要实现的代码如下:
package com.wuyiccc.helloframework.injection;
import com.wuyiccc.helloframework.core.BeanContainer;
import com.wuyiccc.helloframework.injection.annotation.Autowired;
import com.wuyiccc.helloframework.util.ClassUtil;
import com.wuyiccc.helloframework.util.ValidationUtil;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.util.Set;
/**
* @author wuyiccc
* @date 2020/7/13 14:57
* 岂曰无衣,与子同袍~
*/
@Slf4j
public class DependencyInjector {
/**
* Bean 容器
*/
private BeanContainer beanContainer;
public DependencyInjector() {beanContainer = BeanContainer.getInstance();
}
/**
* 执行 IOC
*/
public void doIoc() {if (ValidationUtil.isEmpty(beanContainer.getClasses())) {log.warn("empty classes in BeanContainer");
return;
}
// 遍历容器中的所有 class 的对象
for (Class<?> clazz : beanContainer.getClasses()) {Field[] fields = clazz.getDeclaredFields();
if (ValidationUtil.isEmpty(fields)) {continue;}
for (Field field : fields) {
// 找出被 Autowired 标记的成员变量
if (field.isAnnotationPresent(Autowired.class)) {Autowired autowired = field.getAnnotation(Autowired.class);
String autowiredValue = autowired.value(); // value 值
// 获取该 field 的类型
Class<?> fieldClass = field.getType();
// 获取该类型在容器中对应的实例
Object fieldValue = getFieldInstance(fieldClass, autowiredValue);
if (fieldValue == null) {throw new RuntimeException("unable to inject relevant type, target fieldClass is:" + fieldClass.getName() + "autowiredValue is :" + autowiredValue);
} else {
// 通过反射将对应的成员变量实例注入到成员变量所在类的实例里
Object targetBean = beanContainer.getBean(clazz);
ClassUtil.setField(field, targetBean, fieldValue, true);
}
}
}
}
}
/**
* 依据 Class 在 beanContainer 里获取实例或者实现类
*
* @param fieldClass 实例中属性的类型
* @param autowiredValue 要注入的值的名称
* @return
*/
private Object getFieldInstance(Class<?> fieldClass, String autowiredValue) {
// 看是否获取同等级的实例
Object fieldValue = beanContainer.getBean(fieldClass);
if (fieldValue != null) {return fieldValue;} else {Class<?> implementedClass = geImplementedClass(fieldClass, autowiredValue);
if (implementedClass != null) {return beanContainer.getBean(implementedClass);
} else {return null;}
}
}
/**
* 获取接口 i 的实现类
*
* @param fieldClass 实例中要注入的属性的类型
* @return
*/
private Class<?> geImplementedClass(Class<?> fieldClass, String autowiredValue) {Set<Class<?>> classSet = beanContainer.getClassesBySuper(fieldClass);
if (!ValidationUtil.isEmpty(classSet)) {if (ValidationUtil.isEmpty(autowiredValue)) {if (classSet.size() == 1) {return classSet.iterator().next();} else {throw new RuntimeException("multiple implemented classes for" + fieldClass.getName() + "please set @Autowired's value to pick one");
}
} else {for (Class<?> clazz : classSet) {if (autowiredValue.equals(clazz.getSimpleName())) {return clazz;}
}
}
}
return null;
}
}
3.2 相干代码解说如下:
GitHub 地址:https://github.com/wuyiccc/he…
正文完