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...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。