自制簡陋的ioc容器並解決循環依賴

獻上一段自己寫的極其簡陋版的ioc容器的實現,幫助大家瞭解spring基本原理

步驟:

1、首先自定義註解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyAutowired {
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyComponent {
}

然後創建緩存(我這裏只有兩個個緩存),兩個緩存主要起到單例和解決循環依賴的作用,一級緩存主要存放已經創建好並且已經完全屬性賦值好的bean,二級緩存主要存放實例化但是未屬性賦值的bean,注意:這裏一級緩存和二級緩存相同beanName存放的bean都是指向同一個內存地址,只是bean沒完成創建好時暫時存放在二級緩存中

public final static Map<String, Object> oneCache = new ConcurrentHashMap<>();
public final static Map<String, Object> twoCache = new ConcurrentHashMap<>();

下面是兩個用來測試的bean,並且相互注入

@MyComponent
@Setter
@Getter
public class Cat {
    @MyAutowired
    private Dog dog;
}


@MyComponent
@Setter
@Getter
public class Dog {
    @MyAutowired
    private Cat cat;

    private String name;
    private int age;

    public Dog() {
        this.name="dog";
        this.age=10;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "cat=" + cat +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

下面是我自己實現的getBean,已經解決循環依賴問題,代碼不難,主要是使用一級緩存和二級緩存處理單例和循環依賴問題,然後利用反射實現bean的創建及屬性的賦值

public class MyGetBean {
    public final static Map<String, Object> oneCache = new ConcurrentHashMap<>();
    public final static Map<String, Object> twoCache = new ConcurrentHashMap<>();

    public Object getBean(Class clazz) throws Exception {
        if (clazz.isAnnotationPresent(MyComponent.class)) {
            String simpleName = clazz.getSimpleName();
            StringBuilder beanName = new StringBuilder(simpleName);
            beanName.replace(0, 1, simpleName.substring(0, 1).toLowerCase());
            Object bean = getSingleton(beanName.toString());
            if (bean != null) {
                return bean;
            }
            bean = createBean(clazz, beanName.toString());
            return bean;
        } else {
            throw new RuntimeException("容器沒找到該類型的bean");
        }
    }

    private Object getSingleton(String beanName) {
        Object one = oneCache.get(beanName);
        if (one == null) {
            one = twoCache.get(beanName);
        } else {
            twoCache.remove(beanName);
        }
        return one;
    }

    private synchronized Object createBean(Class clazz, String beanName) throws Exception {
        Object bean = oneCache.get(beanName);
        if (bean == null) {
            bean = clazz.newInstance();
            twoCache.put(beanName, bean);
            for (Field field : clazz.getDeclaredFields()) {
                if (!field.isAccessible()) {
                    field.setAccessible(true);
                }
                if (field.isAnnotationPresent(MyAutowired.class)) {
                    Class<?> type = field.getType();
                    Object inject = getBean(type);
                    field.set(bean, inject);
                }
            }
            oneCache.put(beanName, bean);
        }
        return bean;
    }
}

測試,運行無錯誤

public class Test {
    @org.junit.Test
    public void test() throws Exception {
        MyGetBean myGetBean = new MyGetBean();
        Cat bean = (Cat) myGetBean.getBean(Cat.class);
        System.out.println(bean.getDog().toString());
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章