手写SpringIOC

Secular and rational guide you forward, progress is always full of pain.
talk is cheap, show me the code,make a better result.

目录

在这里插入图片描述

概述

Spring在后端基本完成了大一统,前面已经讲述了DB,JDBC,连接池组件,缓存,ORM组件,以及SpringMVC框架。如下我们将重点带来Spring系列框架组件的简要实现。
首先我们先考虑Spring,其中最重要的就是IOC和AOP。

需求:

需求整理如下:
1.由Spring来负责控制对象的生命周期和对象之间的关系。
2.将对象的控制权交给IOC容器,
3.所有的依赖关系被统一集中的管理起来了,清晰明了
4.每个类只需要关注直接的业务逻辑

设计思路

为了方面也为了规范,我们使用UML工具啦。

实现思路分析

1.扫描包下的类

取得某个接口下所有实现这个接口的类。以文件的形式来获取包下的所有Class

2.如果类存在注入bean所需的注解 将bean放入bean容器

根据beanid获取对应的bean,初始化依赖的属性

3.查看beanA中的属性 如果属性需要注入 就在bean容器中找到对应的beanB 并且注入到beanA的属性中

查找包路径下面所有添加注解的类 @IocService

拓展Demo实现

相关代码如下:


 public static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive,
	         List<Class<?>> classes) {
	      // 获取此包的目录 建立一个File
	      File dir = new File(packagePath);
	      // 如果不存在或者 也不是目录就直接返回
	      if (!dir.exists() || !dir.isDirectory()) {
	         return;
	      }
	      // 如果存在 就获取包下的所有文件 包括目录
	      File[] dirfiles = dir.listFiles(new FileFilter() {
	         // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
	         public boolean accept(File file) {
	            return (recursive && file.isDirectory()) || (file.getName().endsWith(".class"));
	         }
	      });
	      // 循环所有文件
	      for (File file : dirfiles) {
	         // 如果是目录 则继续扫描
	         if (file.isDirectory()) {
	            findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive,
	                  classes);
	         } else {
	            // 如果是java类文件 去掉后面的.class 只留下类名
	            String className = file.getName().substring(0, file.getName().length() - 6);
	            try {
	               // 添加到集合中去
	               classes.add(Class.forName(packageName + '.' + className));
	            } catch (ClassNotFoundException e) {
	               e.printStackTrace();
	            }
	         }
	      }
	   }
	}

2.将bean放入bean容器


  public ConcurrentHashMap<String,Object>initBean(List<Class>classes) throws IllegalAccessException,InstantiationException{
        ConcurrentHashMap<String,Object> map = new ConcurrentHashMap<String, Object>();
        String beanId="";
        for(Class clazz :classes){
            Object object = clazz.newInstance();
            IocService annotation =(IocService)clazz.getDeclaredAnnotation(IocService.class);
            if (annotation!=null){
                //如果定义了name属性 以实现的name属性为主否则以默认的规则为主
                String value = annotation.name();
                if (value!=null && !value.equals("")){
                    beanId = value;
                }
                else {
                    beanId = toLowerCaseFirstOne(clazz.getSimpleName());
                }
            }

           //存储值
            map.put(beanId,object);
        }
        return map;
    }

3.属性注入

 /**
     * 初始化依赖的属性
     * @param object
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     */
    private void initAttribute(Object object)throws Exception{
        //获取object的所有类型
        Class<? extends Object> classinfo = object.getClass();
        //获取所有的属性字段
        Field[] fields = classinfo.getDeclaredFields();
        //遍历所有字段
        for(Field field : fields){
            //查找字段上有依赖的注解
            boolean falg = field.isAnnotationPresent(IocResource.class);
            if (falg){
                IocResource iocResource = field.getAnnotation(IocResource.class);
                if (iocResource!=null){
                    //获取属性的beanid
                    String beanId = field.getName();
                    //获取对应的object
                    Object attrObject = getBean(beanId);
                    if (attrObject!=null){
                        //访问私有字段
                        field.setAccessible(true);
                        //赋值
                        field.set(object,attrObject);
                        continue;
                    }
                }
            }
        }
    }

实验效果:

在这里插入图片描述

分析:

1.在这里插入图片描述
1.首先会加载实现类路劲
2.接着会获取bean
3.初始化bean
4.初始化依赖
在这里插入图片描述

小结:

主要讲述了SpringIOC原理和简单实现,里面有许多不足,请大家指正~

参考资料和推荐阅读

  1. 手把手教你手写Spring框架(附源码).
  2. 手写代码实现spring的ioc功能.
  3. 纯手写轻量级springioc aop.

欢迎阅读,各位老铁,如果对你有帮助,点个赞加个关注呗!~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迅捷的软件产品制作专家

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值