美文网首页spring 整合使用
自制简陋的ioc容器并解决循环依赖

自制简陋的ioc容器并解决循环依赖

作者: 笔记本一号 | 来源:发表于2021-10-27 03:28 被阅读0次

    献上一段自己写的极其简陋版的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());
        }
    }
    

    相关文章

      网友评论

        本文标题:自制简陋的ioc容器并解决循环依赖

        本文链接:https://www.haomeiwen.com/subject/dgsualtx.html