通过反射模拟ioc的bean添加和自动注入原理
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.*;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/***
* 模拟 ioc bean添加到map容器里面去
* 同时也模拟了自动注入的
*/
public class Dom05 {
Map<String, Object> map = new ConcurrentHashMap<>();
@autowrite()
private A a;
public static void main(String[] args) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
final Dom05 dom05 = new Dom05();
dom05.run();
System.out.println(dom05.map);
System.out.println(dom05.a.getName());
}
public void run() throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
//获取反射class
final Class c = this.getClass();
//获取当前calss下的全部方法
final Method[] methods = c.getDeclaredMethods();
//遍历方法
for (Method method : methods) {
//判断方法上面有ben没有
if (method.getAnnotation(bean.class) != null) {
final bean annotation = method.getAnnotation(bean.class);
String name = null;
//判断写添加bean的名称没有 如果写了就用用户的 如果没有写我们就通过反射获取 方法名添加到我们的map里面去
if (!annotation.value().equals("")) {
name = annotation.value();
} else {
//有的话我们把返回的对象添加到我们的map里面去
name = method.getName();
}
//把返回值添加到map里面
map.put(name, method.invoke(c.newInstance()));
}
}
//获取全部的变量
final Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
//检查变上有不有我们的注解bean
final autowrite annotation = field.getAnnotation(autowrite.class);
if (annotation != null) {
//我们先判断是否写bean的名字 如果写了我们直接去map里面去找 如果没有我就循环遍历去找
if (!field.getAnnotation(autowrite.class).value().equals("")) {
field.setAccessible(true);
final String value = field.getAnnotation(autowrite.class).value();
field.set(this, map.get(value));
field.setAccessible(false);
} else {
//有的话我们的循环检查看看有不有相应的对象类型如果有我们就赋值上去
for (Map.Entry<String, Object> entry : map.entrySet()) {
//判断两个对象直接的类型是不是一致的 如果是一致那就证明是需要注入的对象
//System.out.println(entry.getValue().getClass().hashCode() + " " + field.getType().hashCode());
if (entry.getValue().getClass().hashCode() == field.getType().hashCode()) {
field.set(this, entry.getValue());
}
}
}
field.setAccessible(false);
}
}
}
@bean
public A a() {
return new A("张三");
}
}
class A {
private String name;
public A() {
}
public A(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Target(ElementType.METHOD)//内置注解表名用于方法上
@Retention(RetentionPolicy.RUNTIME) //表示在程序运行是也生效
@interface bean {
String value() default ""; //default 设置默认值
}
@Target(ElementType.FIELD)//内置注解表名用于变量上
@Retention(RetentionPolicy.RUNTIME)//表示在程序运行是也生效
@interface autowrite {
String value() default "";//default 设置默认值
}