自制简陋的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 oneCache = new ConcurrentHashMap<>();
public final static Map 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 oneCache = new ConcurrentHashMap<>();
    public final static Map 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());
    }
}

你可能感兴趣的:(自制简陋的ioc容器并解决循环依赖)