手写一个简单的IOC容器

原文 http://localhost:4000/2020/02/25/SSM/spring/%E6%89%8B%E5%86%99%E4%B8%80%E4%B8%AA%E5%88%9D%E7%BA%A7%E7%9A%84IOC%E5%AE%B9%E5%99%A8/#more

说明

首先我们都知道,Spring框架中两个最重要的组件就是IOC和AOP。IOC 即 inversion of control 控制反转。Aop即 Aspect Oriented Programming 面向切面编程。那么我们这里就来手写一个简单的IOC容器。这里主要使用 xml配置的方式来实现IOC容器。

前置知识

手撸一个IOC容器需要先掌握好 XML文件解析Java反射知识。

行了,下面我们就开始了。

项目搭建

创建项目

使用普通的maven搭建一个项目。

导入依赖

<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.3.RELEASE</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.10</version></dependency><dependency><groupId>org.dom4j</groupId><artifactId>dom4j</artifactId><version>2.1.1</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.62</version></dependency>
</dependencies>

实体类

package com.ooyhao.pojo;
import lombok.Data;
import java.io.Serializable;@Data
public class User implements Serializable {private byte age;private Byte ageB;private short height;private Short heightS;private int id;private Integer idI;private long weight;private Long weightL;private char sex;private Character sexC;private float salary;private Float salaryF;private double buy;private Double buyD;private boolean successB;private Boolean success;private String name;
}

spring配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="user" class="com.ooyhao.pojo.User"><property name="age" value="2"/><property name="ageB" value="20"/><property name="height" value="170"/><property name="heightS" value="1700"/><property name="id" value="1"/><property name="idI" value="10"/><property name="weight" value="60"/><property name="weightL" value="600"/><property name="sex" value="m"/><property name="sexC" value="f"/><property name="salary" value="7500.5"/><property name="salaryF" value="9000.5"/><property name="buy" value="10.05"/><property name="buyD" value="100.5"/><property name="success" value="false"/><property name="successB" value="true"/><property name="name" value="欧阳"/></bean>
</beans>

自定义ApplicationContext

/*** 简单手写一个IOC容器*/
public class MyApplicationContext implements ApplicationContext {private static Map<String,Object> beansContainer = new HashMap<>();public MyApplicationContext(String path){//构造器中处理//处理ClassPath下的文件。ClassPathResource resource = new ClassPathResource(path);//利用DOM4J解析XML文件SAXReader reader = new SAXReader();try {//读取xml文件,获取到文档Document document = reader.read(resource.getInputStream());//根目录beansElement beansElement = document.getRootElement();//迭代beans获取多个beanIterator<Element> beansIter = beansElement.elementIterator();while(beansIter.hasNext()){//单个beanElement beanElement = beansIter.next();//idString id = beanElement.attributeValue("id");//完整的类名String className = beanElement.attributeValue("class");//通过className反射出一个对象Class<?> aClass = Class.forName(className);//获取无参数的构造器Constructor<?> constructor = aClass.getConstructor();//利用无参数的构造器创建实例Object o = constructor.newInstance();//迭代bean获取propertyIterator<Element> beanIter = beanElement.elementIterator();while (beanIter.hasNext()){Element property = beanIter.next();//属性名String fieldName = property.attributeValue("name");//属性值String fieldValue = property.attributeValue("value");//根据属性名获取属性对象Field field = aClass.getDeclaredField(fieldName);//属性的类型Class<?> fieldType = field.getType();//拼接set方法名String setMethodName = "set" + fieldName.substring(0,1).toUpperCase()+ fieldName.substring(1);//获取方法对象Method method = aClass.getMethod(setMethodName, fieldType);Object val = fieldValue;switch (fieldType.getName()){case "int":case "java.lang.Integer":val = Integer.valueOf(fieldValue);break;case "boolean":case "java.lang.Boolean":val = Boolean.valueOf(fieldValue);break;case "char":case "java.lang.Character":val = fieldValue.charAt(0);break;case "long":case "java.lang.Long":val = Long.valueOf(fieldValue);break;case "double":case "java.lang.Double":val = Double.valueOf(fieldValue);break;case "float":case "java.lang.Float":val = Float.valueOf(fieldValue);break;case "byte":case "java.lang.Byte":val = Byte.valueOf(fieldValue);break;case "short":case "java.lang.Short":val = Short.valueOf(fieldValue);break;}method.invoke(o,val);}beansContainer.put(id,o);}} catch (DocumentException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (NoSuchFieldException e) {e.printStackTrace();}}public Object getBean(String s) throws BeansException {Object o = beansContainer.get(s);return o;}public <T> T getBean(Class<T> aClass) throws BeansException {Collection<Object> values = beansContainer.values();Iterator<Object> iterator = values.iterator();while (iterator.hasNext()){Object next = iterator.next();if (next.getClass().equals(aClass)) {return (T) next;}}return null;}//部分未实现功能此处省略
}

上述部分就是实现简单的IOC重点内容。主要是基于 XML解析和发射知识。

项目测试

项目测试代码

ApplicationContext context = new MyApplicationContext("spring.xml");
User o = context.getBean(User.class);
System.out.println(JSONObject.toJSONString(o));

测试结果

{"age": 2,"ageB": 20,"buy": 10.05,"buyD": 100.5,"height": 170,"heightS": 1700,"id": 1,"idI": 10,"name": "欧阳","salary": 7500.5,"salaryF": 9000.5,"sex": "m","sexC": "f","success": false,"successB": true,"weight": 60,"weightL": 600
}

注意:这里只是实现了一个简单的IOC容器,并且只是实现了 java的简单类型和 包装类型,以及String类型的注入。

手写一个简单的IOC容器相关推荐

  1. jquery手写轮播图_用jQuery如何手写一个简单的轮播图?(附代码)

    用jQuery如何手写一个简单的轮播图?下面本篇文章通过代码示例来给大家介绍一下.有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助. 用 jQuery 手写轮播图 先上个效果截图: 主要 ...

  2. 怎么手写一个简单的List集合

    List集合 手写一个简单的List集合为自己调用并不是特别难,只需要定义一个集合接口去提供所有方法的定义如下代码 : package com.myself.util; /*** * @author ...

  3. 手写一个简单的分页器

    封装分页器 1. 前言 分页器基本上是任何网站必须要有的一个组件,为什么需要分页器,当后台传入了大量的数据,那么在前端拿到数据,如果直接展示很有可能或造成卡顿,同时消耗过多的内存,给用户带来的浏览效果 ...

  4. 手写实现简单版IOC

    概述 IOC (Inversion of Control) 控制反转,大家应该都比较熟悉了.应该也都有用过,这里就不具体介绍了.自己平时也有用到过IOC,但是对它的具体实现原理只有一个模糊的概念,所以 ...

  5. 手写一个简单rpc框架(一)

    扑街前言:前面说了netty的基本运用.Java的NIO等一系列的知识,这些知识已经可以做一个简单的rpc框架,本篇和下篇我们一起了解一个怎么完成一个rpc框架,当然个只是为了更好的了解rpc框架的基 ...

  6. 手写一个简单的HashMap,搞定挑剔面试官

    作者:编程十二 链接:https://www.jianshu.com/p/1be0e957baf2 前言 今天去面试啊,聊得差不多的时候面试官突然问我会手写HashMap吗?这我哪能怂啊,好死不死的面 ...

  7. 手写一个简单的线程池MyThreadPool

    说明 手写的一个简单的线程池,旨在帮助了解线程池的工作原理. 核心内容 核心工作线程 任务阻塞队列 定义一个内部类去实现核心工作线程 /*** 内部类:工作的核心线程*/private final c ...

  8. 深入了解Vue 2响应式原理,并手写一个简单的Vue

    1. Vue 2的响应式原理 Vue.js 一个核心思想是数据驱动.所谓数据驱动是指视图是由数据驱动生成的,对视图的修改,不会直接操作 DOM,而是通过修改数据.vue.js里面只需要改变数据,Vue ...

  9. 小白前端之路:手写一个简单的vue-router这几年,好像过的好快,怀念我的大学生活。 - 连某人 大三实习生,之前写过简单MVVM框架、简单的vuex、但是看了vue-router的源码(看了

    这几年,好像过的好快,怀念我的大学生活. 连某人 大三实习生,之前写过简单MVVM框架.简单的vuex.但是看了vue-router的源码(看了大概)之后就没有写,趁着周末不用工作(大三趁着不开学出来 ...

最新文章

  1. 2013 vc 字体 静态文本框_vc 中mfc 的 静态文本框 的名字 的字体怎么设置
  2. java 判断 中文字符_java中判断字符串中是否有中文字符
  3. php珠心算源码,深度解析珠心算的“开智”功能
  4. 杭电acm 2024 C语言合法标识符
  5. xcode4的workspace里各lib工程与app工程联编之runscript简介
  6. kettle job如何利用java的反射机制获取执行的sql语句
  7. gg修改器修改数值没有用怎么办_风灵月影是谁?风灵月影修改器大全
  8. 白话java_白话Java
  9. MySQL5及更高版本的jar包下载(jdbc)及常见问题解决
  10. cnn模型(cnn神经网络模型)
  11. 方舟非主机服务器无限距离,方舟生存进化怎么调主机距离
  12. RPL源路由的IPv6路由头[RFC6554译文]
  13. 关于cocoapods遇到xxxx file not found和No such module 'XXX'的问题
  14. 使用maven编译打包用javac还是eclipse的jdt的问题
  15. 私域流量运营之社交裂变
  16. python汇率的转换程序_如何实现python汇率转换代码
  17. 详解super()函数
  18. xmapp 在Mac下配置
  19. 混沌研习社-《创业反思-成为更加优秀的自己》 百度云下载
  20. 蹭WiFi掉黑客陷进怎么破

热门文章

  1. android webview第三方框架,Android 中使用第三方 WebView,腾讯X5浏览器
  2. CC00016.kylin——|HadoopOLAP_Kylin.V16|——|Kylin.v16|Cube优化|检查Cuboid数量|
  3. SQL server 嵌套查询
  4. 常见浏览器以及对应驱动的下载与使用
  5. c语言程序设计学籍信息,C语言程序设计报告——学生学籍管理(报告).doc
  6. Oracle学习之建表
  7. 基于Android幼儿识字软件,布布识字软件(幼儿识字)
  8. 从Oracle迁移到PostgreSQL的十大理由
  9. 我与兼阅万,有个美丽的邂逅
  10. 爱奇艺微服务标准技术架构实践