(一)手写Spring项目之IOC

项目地址:https://github.com/iamzhubaoliang/MySpring

1. 什么是IOC

IOC Inversion of Control 即控制反转,它可以降低代码之间的耦合性,最长见的就是Spring的依赖注入,它是怎么反转的?因为它的对象并不是我们new出来的而是被动的由容器进行注入的,spring相当于中间连接将原对象与属性进行了分离,由spring来控制对象的生命周期。

2. 实现方式

我们依旧是使用三级缓存
回顾一下Spring的三级缓存过程,顺便回顾一下循环依赖是怎么解决的

  1. 首先Spring会执行GetBean,GetBean为空壳方法,调用doGetBean
  2. 然后执行getSingleton(Beanname,true)方法从一级缓存中查找,然后判断是不是正在创建,此时A一定不存在所以为空,然后进入它的重载方法getsingleTon(Beannaem,singletonFactory)方法,singletonFactory为一个lambda表达式,其为函数式接口的实现。
  3. 然后进入singleton方法中,执行lanbda表达式getObject(在接口ObjectFactory中),这个getObject方法中是我们传进来的实现createBean,里面只有doCreateBean方法,执行DoCreatBean,然·后执行CrateBeanInstance方法,这个时候就会创建A的实例化对象,但这个是原始的对象,没有进行属性填充的,所以在doCreateBean中同时进行属性的填充。
  4. 在向A中填充B之前有一个向三级缓存中添加一个键值对的过程,添加了beanName和getEarlyBeanRefrence(beanname,bean)(将A传入了这个lamda表达式中),然后向A里填充B,发现B没有
  5. 执行this.Factory.getBean()查找B,B找不到,然后再执行A的那一套,将B的name和getEarlyRefrence lambda表达式扔到三级缓存,最终到了填充B的A属性的时候,getBean,doGetBean后,执行getsingleton发现缓存中有A,所以从三级缓存中删除键值对,放到二级缓存,此时进行填充,填充成功后执行addsingleton B放入一级缓存删掉三级缓存B键值对
  6. 上面这些过程都是在创建A时候的调用,所以层层返回填充A,执行addsingleton ,执行删掉二级缓存中A,放入一级缓存,
  7. 因为创建是一个循环,所以程序会继续执行,getBean,拿B这一次从一级缓存中直接拿到了B,到此结束
  8. 其中那个getEarlyBeanRefrence表达式是用来解决aop的,当从三级缓存拿对象的时候,如果不是则直接返回原始对象,如果有动态代理则返回一个代理对象,这样就实现了aop

我们来分析一下三级缓存的作用,一级缓存singletonobjects是存放已经注入的对象,earlysingletonObjects是存放半成品也就是没有进行属性注入的Bean,此时的Bean虽然是半成品却可以被其他对象所引用,第三级缓存是用来创建代理对象的,我们放入三级缓存的并不是我们原始用反射创建的Bean,而是一个动态的工厂,当我们从工厂中取对象的时候如果发现有通知(增强)那么取的就是代理对象,如果不是直接返回原始对象

3. 手动实现的方式

IOC最重要的就是属性的注入了
手写的思路

  1. 创建Autowired,创建CompoentScan,Compoentd等注解
  2. 创建三级缓存
  3. 实现Bean的生命周期:Bean的生命周期如下
    1)实例化Bean
    2)如果Bean实现了BeanNameAware接口就执行setBeanName方法
    3)如果Bean实现了ApplicationContextAware接口就执行setApplicationContext方法
    4)如果Bean实现了BeanPostProcessor接口就执行postProcessBeforeInitialization
    5)如果Bean 实现了InitializingBean接口,执行afterPropertiesSet()方法
    6)如果bean使用init-method声明了初始化方法,则执行初始化方法
    7)如果Bean实现了BeanPostProcessor接口就执行postProcessAfterInitialization
    8)如果bean实现了DisposableBean接口,则执行destory()方法
    上述只是简单的生命周期,中间还有其他的复杂过程参考https://zhuanlan.zhihu.com/p/344140024
  4. 我们使用spring的时候一般是getBean,而具体创建的时候就是CreateBean,创建完成后属性注入,成品放入一级缓存
    image

代码

1.扫描:

  1. 首先要根据ComponentScan获取扫描路径,接着递归扫描目录,将所有带有Component注解的类用一个BeanDefintion(用来描述Bean)包装的类包装然后放入beanDefintionHashMap,这个map用来存储扫描过程中的Bean的描述
  2. 判断此类是否实现了BeanPostProcessor接口,如果实现了就要实例化这个class放入BeanPostProcessorList,这个list用来存放所有的后置处理器
  3. 如果是Controller同时将描述的Controller属性置true
  4. 然后获取Scope属性将Scope的值放入BeanDefintion
  5. 最后放入map中
    这样就将所有的Bean完成了扫描
 public static void LoadAllBean() {
        for (Class<?> clazz : classesHashSet) {
            if (!(clazz.isAnnotationPresent(Component.class)||clazz.isAnnotationPresent(Controller.class)))
                continue;
            BeanDefintion newBeanDefine = new BeanDefintion();
            newBeanDefine.setClazz(clazz);
            String BeanName=clazz.getName();
            BeanName=getBeanName(BeanName);
            if(clazz.isAnnotationPresent(Component.class)&&!clazz.getAnnotation(Component.class).value().equals(""))
                BeanName=clazz.getAnnotation(Component.class).value();
            if(clazz.isAnnotationPresent(Controller.class)&&!clazz.getAnnotation(Controller.class).value().equals("")) {
                BeanName = clazz.getAnnotation(Controller.class).value();

            }
            if(clazz.isAnnotationPresent(Controller.class))
                newBeanDefine.setIsController(true);
            newBeanDefine.setBeanName(BeanName);
            //加载后置处理器
            if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
                try {
                    BeanPostProcessorList.add((BeanPostProcessor) clazz.getDeclaredConstructor().newInstance());

                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }
            }


            //scope
            if (clazz.isAnnotationPresent(Scope.class)) {
                String scope = clazz.getDeclaredAnnotation(Scope.class).value();
                newBeanDefine.setScope(scope);
            } else {
                //默认为单例模式
                newBeanDefine.setScope(ScopeEnum.SingleTon.toString());
            }
            //添加切面
            if (clazz.isAnnotationPresent(Aspect.class)) {
                for (Method method : clazz.getMethods()) {
                    String annotationPath = "";

                    if (method.isAnnotationPresent(PointCut.class)) {
                        String delegateString = method.getAnnotation(PointCut.class).value();
                        annotationPath=delegateString;
                        if (delegateString.charAt(delegateString.length() - 1) == ')') {

                            //说明是在某个方法上面的切面
                            annotationPath =annotationPath.replace("()","");
                            //切掉方法保留到类
                            String[] seg=cutName(annotationPath);
                            AddToAspects(clazz,seg[0],true,seg[1]);
                        }else
                        {//切面是某个包或者类
                            String annotationPathClone=new String(annotationPath);
                            URL resource=Container.classLoader.getResource(annotationPathClone.replace(".","/"));
                            if(resource==null)
                                resource=Container.classLoader.getResource(annotationPathClone.replace(".","/")+".class");
                            File file=new File(resource.getFile());
//                            System.out.println(file);
                            if(file.isDirectory()) {
                                ArrayList<File> fileArray=new ArrayList<>();
                                DFSgetCureentDir(file,fileArray);
                                for(File f:fileArray)
                                {
                                   String key= f.getAbsolutePath().replace("\\",".");
                                   key=key.substring(key.indexOf(annotationPath),key.indexOf(f.getName())+f.getName().length()-6);
                                   AddToAspects(clazz,key,false,"");
                                }

                            }else
                            {
                                String key= file.getAbsolutePath().replace("\\",".");
                                key=key.substring(key.indexOf(annotationPath),key.indexOf(file.getName())+file.getName().length()-6);
                                AddToAspects(clazz,key,false,"");
                            }
                        }

                    }


                }
            }
                beanDefintionHashMap.put(newBeanDefine.getBeanName(), newBeanDefine);

        }
    

    }

AddToAspects是用来添加通知的先不用管,这个后期做AOP的时候讲解

2.创建

创建过程就是对象在三级缓存中移动,在真实的Spring中利用一个getEarlyBeanRefrence(beanname,bean)的lambda表达式来获取代理或者原始对象这里使用的是一个动态工厂来获取,其实原理是一样的,lambda表达式就是一个函数调用,它是一个函数式接口,有关函数式接口的资料自行查阅
这一部分是IOC的核心部分,会有点多,但基本原理开始已经阐述了,其实很简单,代码虽然多单实现的路基很简单

  1. 上面创建了Bean的描述,这里就要按照描述来创建Bean了,ProductBean()用来遍历beanDefintionHashMap并调用CreateBean函数
  2. CreateBean的逻辑就是开始讲述的IOC三级缓存了。
    其他相关描述见注释
  public static void ProductBean()
    {


            for (String beanName : beanDefintionHashMap.keySet()) {
                BeanDefintion beanDefintion = beanDefintionHashMap.get(beanName);

//                如果是单例就Create,因为如果不是Singleton单例每次拿的时候是先创建并不是从缓存中拿取
                if (beanDefintion.getScope().equals(ScopeEnum.SingleTon.toString())) {

                    CreateBean(beanDefintion,true);
                }
            }

    }
    private static Object CreateBean(BeanDefintion beanDefintion,Boolean sinleton) {
        //判断是不是在二级缓存中存在
        try {
            //如果在一级直接返回
            if(Container.singletonObjects.containsKey(beanDefintion.getBeanName())&&sinleton)
                return Container.singletonObjects.get(beanDefintion);
            else if(Container.earlySingletonObjects.containsKey(beanDefintion.getBeanName()))
            {
                //这里返回引用,是半成品,为了填充依赖于它的对象
                return Container.earlySingletonObjects.get(beanDefintion.getBeanName());

            }else {
                if(beanDefintion.getClazz().isInterface())
                   return null;
                //调用后置处理器
                //调用后置处理器方法

                Object instance = beanDefintion.getClazz().getDeclaredConstructor().newInstance();

                DynamicBeanFactory dynamicBeanFactory = new DynamicBeanFactory();
                dynamicBeanFactory.setInstance(instance);
                dynamicBeanFactory.setBeanDefintion(beanDefintion);
                //查看是否存在切面并放入工厂中,在工厂中准备代理
                if(BeforeDelegatedSet.containsKey(beanDefintion.getClazz().getName()))
                {
                    dynamicBeanFactory.setDelegated(true);
                    dynamicBeanFactory.setBeforemethodCache(BeforeDelegatedSet.get(beanDefintion.getClazz().getName()));
                }
                if(AfterDelegatedSet.containsKey(beanDefintion.getClazz().getName()))
                {
                    dynamicBeanFactory.setDelegated(true);
                    dynamicBeanFactory.setAftermethodCache(AfterDelegatedSet.get(beanDefintion.getClazz().getName()));
                }

                //扔到三级缓存
                Container.singletonFactory.put(beanDefintion.getBeanName(), dynamicBeanFactory);
                populate(beanDefintion.getBeanName());
                //扔到二级
                Container.earlySingletonObjects.put(beanDefintion.getBeanName(),Container.singletonFactory.get(beanDefintion.getBeanName()).getTarget());
                Container.singletonFactory.remove(beanDefintion.getBeanName());
                //扔到一级
                Container.singletonObjects.put(beanDefintion.getBeanName(),Container.earlySingletonObjects.get(beanDefintion.getBeanName()));
                //后置处理器
                Container.earlySingletonObjects.remove(beanDefintion.getBeanName());
                //加入Controllermap引用
                if(beanDefintion.isController())
                    Container.controllerMap.put(beanDefintion.getBeanName(),Container.singletonObjects.get(beanDefintion.getBeanName()));

				//如果实现了BeanNameAware接口就调用SetBeanName设置BeanName
                if(instance instanceof BeanNameAware)
                {
                    ((BeanNameAware)instance).SetBeanName(beanDefintion.getBeanName());
                }
                for(BeanPostProcessor processor:BeanPostProcessorList)
                {

                    Container.singletonObjects.put(beanDefintion.getBeanName(),processor.postProcessBeforeInitialization(instance,beanDefintion.getBeanName()));

                }
			//如果实现了InitializingBean接口就调用afterPropertiesSet
                if(instance instanceof InitializingBean)
                {
                   ((InitializingBean) instance).afterPropertiesSet();
                }
                for(BeanPostProcessor processor:BeanPostProcessorList)
                {
                    Container.singletonObjects.put(beanDefintion.getBeanName(),processor.postProcessAfterInitialization(instance,beanDefintion.getBeanName()));

                }


            }




        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }


        if(!sinleton)
        {
            Object obj=Container.singletonObjects.get(beanDefintion.getBeanName());
            //因为创建完成后最后都放入一级缓存,如果不是单例就要删除
            Container.singletonObjects.remove(beanDefintion.getBeanName());
            return obj;
        }
        return null;
    }

    /**
     * 获取属性,填充属性
     */
    private static void populate(String BeanName)
    {
        try {
                Class<?> bean=Container.singletonFactory.get(BeanName).getBeanDefintion().getClazz();
			//获取所有的变量,看看有没有Autowired注解,调用getBean取所注入的Bean
                for (Field delclaredField : bean.getDeclaredFields())
                {
                    if(!delclaredField.isAnnotationPresent(Autowired.class))
                        continue;
                    String[] name=delclaredField.getType().toString().split("\\.");
                    String benName=name[name.length-1];
                    String a=delclaredField.getAnnotation(Autowired.class).value();
                    if(!delclaredField.getAnnotation(Autowired.class).value().equals(""))
                        benName=delclaredField.getAnnotation(Autowired.class).value();
                    Object fBean = getBean(benName);
                    delclaredField.setAccessible(true);
                    delclaredField.set(Container.singletonFactory.get(BeanName).getInstance(), fBean);
                }

        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }



    public static Object getBean(String BeanName)
    {//没有判断是不是单例,后期改进
        if(beanDefintionHashMap.get(BeanName).getScope().equals(ScopeEnum.SingleTon))
        {
			//有直接从一级缓存中拿到成品
            if (Container.singletonObjects.containsKey(BeanName))
                return Container.singletonObjects.get(BeanName);
            else {
                return CreateBean(beanDefintionHashMap.get(BeanName),true);
            }
        }else
        {	没有就调用CreateBean创建
            return CreateBean(beanDefintionHashMap.get(BeanName),false);
        }
    }
posted @ 2021-09-13 23:04  LiangLiangAA  阅读(126)  评论(0编辑  收藏  举报
theme: { name: 'geek', avatar: '', headerBackground: '' // ... },