手写高仿真Spring框架-控制反转IOC

7 篇文章 0 订阅

手写高仿真Spring框架

流行词:顶层设计

参考代码:https://gitee.com/li-lixiang/lean-spring-2.0.git

控制反转IOC

初始化流程GPApplicationContext类,按照模板模式,实现IOC初始化。
//1、定位,定位配置文件

reader = new GPBeanDefinitionReader(this.configLoactions);

//2、加载配置文件,扫描相关的类,把它们封装成

BeanDefinition List<GPBeanDefinition> beanDefinitions = reader.loadBeanDefinitions();

//3、注册,把配置信息放到容器里面(伪IOC容器)

doRegisterBeanDefinition(beanDefinitions);

//4、把不是延时加载的类,有提前初始化 doAutowrited();

以下代码主要实现以上1、2步骤。

解析配置,将配置中所有的类加载到容器中

    public GPBeanDefinitionReader(String... locations){
        //通过URL定位找到其所对应的文件,然后转换为文件流
        InputStream is = this.getClass().getClassLoader().getResourceAsStream(locations[0].replace("classpath:",""));
        try {
            config.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(null != is){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        doScanner(config.getProperty(SCAN_PACKAGE));
    }

    private void doScanner(String scanPackage) {
        //转换为文件路径,实际上就是把.替换为/就OK了
        URL url = this.getClass().getResource("/" + scanPackage.replaceAll("\\.","/"));
        File classPath = new File(url.getFile());
        for (File file : classPath.listFiles()) {
            if(file.isDirectory()){
                doScanner(scanPackage + "." + file.getName());
            }else{
                if(!file.getName().endsWith(".class")){ continue;}
                String className = (scanPackage + "." + file.getName().replace(".class",""));
                registyBeanClasses.add(className);
            }
        }
    }

并将容器中所有扫描到的结果类转换成BeanDefinition

    public List<GPBeanDefinition> loadBeanDefinitions(){
        List<GPBeanDefinition> result = new ArrayList<GPBeanDefinition>();
        try {
            for (String className : registyBeanClasses) {
                Class<?> beanClass = Class.forName(className);
                //如果是一个接口,是不能实例化的
                //用它实现类来实例化
                if(beanClass.isInterface()) { continue; }

                //beanName有三种情况:
                //1、默认是类名首字母小写
                //2、自定义名字
                //3、接口注入
                result.add(doCreateBeanDefinition(toLowerFirstCase(beanClass.getSimpleName()),beanClass.getName()));
//                result.add(doCreateBeanDefinition(beanClass.getName(),beanClass.getName()));

                Class<?> [] interfaces = beanClass.getInterfaces();
                for (Class<?> i : interfaces) {
                    //如果是多个实现类,只能覆盖
                    //为什么?因为Spring没那么智能,就是这么傻
                    //这个时候,可以自定义名字
                    result.add(doCreateBeanDefinition(i.getName(),beanClass.getName()));
                }

            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return result;
    }


    //把每一个配信息解析成一个BeanDefinition
    private GPBeanDefinition doCreateBeanDefinition(String factoryBeanName,String beanClassName){
        GPBeanDefinition beanDefinition = new GPBeanDefinition();
        beanDefinition.setBeanClassName(beanClassName);
        beanDefinition.setFactoryBeanName(factoryBeanName);
        return beanDefinition;
    }

    //如果类名本身是小写字母,确实会出问题
    //但是我要说明的是:这个方法是我自己用,private的
    //传值也是自己传,类也都遵循了驼峰命名法
    //默认传入的值,存在首字母小写的情况,也不可能出现非字母的情况

    //为了简化程序逻辑,就不做其他判断了,大家了解就OK
    //其实用写注释的时间都能够把逻辑写完了
    private String toLowerFirstCase(String simpleName) {
        char [] chars = simpleName.toCharArray();
        //之所以加,是因为大小写字母的ASCII码相差32,
        // 而且大写字母的ASCII码要小于小写字母的ASCII码
        //在Java中,对char做算学运算,实际上就是对ASCII码做算学运算
        chars[0] += 32;
        return String.valueOf(chars);
    }

在以上第3步骤中,实现容器初始化

    private void doRegisterBeanDefinition(List<GPBeanDefinition> beanDefinitions) throws Exception {

        for (GPBeanDefinition beanDefinition: beanDefinitions) {
            if(super.beanDefinitionMap.containsKey(beanDefinition.getFactoryBeanName())){
                throw new Exception("The “" + beanDefinition.getFactoryBeanName() + "” is exists!!");
            }
            super.beanDefinitionMap.put(beanDefinition.getFactoryBeanName(),beanDefinition);
        }
        //到这里为止,容器初始化完毕
    }

最后第4步,处理非延时加载的类,非延时加载的进行实例化,延时的不做处理。

    private void doAutowrited() {
        for (Map.Entry<String, GPBeanDefinition> beanDefinitionEntry : super.beanDefinitionMap.entrySet()) {
           String beanName = beanDefinitionEntry.getKey();
           if(!beanDefinitionEntry.getValue().isLazyInit()) {
               try {
                   getBean(beanName);
               } catch (Exception e) {
                   e.printStackTrace();
               }
           }
        }
    }

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值