简单的ioc容器
这几天重新温习了反射和注解的知识点,本文通过实现一个迷你的Ioc容器,增加对这两个知识点的记忆。
实现效果

BService和CService都是通过Ioc容器注入依赖的
可以看到,BService标记有单例的注解,而CService没有。在重新实例化AService之后,BService的引用是一样的而CService不一样。
实现注解
- @AutoWrite实现依赖注入
- @SingleBean实现单例模式
思路
Ⅰ.判断类是否有单例注解@SingleBean
Ⅱ. 如果是单例,直接从map中查找对象,并返回实例
Ⅲ. 如果不是单例,创建新对象
Ⅳ. 实例化对象时,通过递归,遍历所有的依赖对象
代码
public class IocAnnotations {
static Map<String, Object> map = new ConcurrentHashMap<>();
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface AutoWrite {
String value() default "";
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface SingleBean {
}
static class AService {
@AutoWrite
private BService bService;
@AutoWrite
private CService cService;
public void say() {
bService.say();
System.out.println("BService :" + bService.toString());
}
public void speak() {
cService.speak();
System.out.println("CService :" + cService.toString());
}
}
@SingleBean
static class BService {
public void say() {
System.out.println("BService");
}
}
static class CService {
public void speak() {
System.out.println("CService");
}
}
private static Object container(Class cls) throws IllegalAccessException, InstantiationException {
boolean singleton = cls.isAnnotationPresent(SingleBean.class);
if (!singleton) {
//如果不是单例,直接生成新的实例对象
return createBean(cls);
}
Object obj = map.get(cls.getName());
synchronized (cls) {
if (obj != null) {
//如果map中有对象引用,直接返回
return obj;
}
obj = createBean(cls);
map.put(cls.getName(), obj);
}
return obj;
}
private static Object createBean(Class cls) throws IllegalAccessException, InstantiationException {
//通过默认构造函数实例化对象
Object obj = cls.newInstance();
Field[] field = cls.getDeclaredFields();
//遍历属性
for (Field f : field) {
if (f.isAnnotationPresent(AutoWrite.class)) {
f.setAccessible(true);
Class<?> paramsCls = f.getType();
//通过递归实例化属性对象
f.set(obj, container(paramsCls));
}
}
return obj;
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
AService a = (AService) container(AService.class);
a.say();
a.speak();
System.out.println("============创建新AService=============");
AService aa = (AService) container(AService.class);
aa.say();
aa.speak();
}
}
小结
通过反射和注解的一些基本Api,实现了Ioc中的setter注入功能,只是一个很简单的实例。
但是这个实现并没有解决bean的依赖循环,之后会完善。

浙公网安备 33010602011771号