用过Spring框架的人一定都知道Spring的依赖注入控制反转;通俗的讲就是负责实例化对象 和 管理对象间的依赖 实现解耦。

我们来对比两段代码:

UserController{UserService userService = new UserService();userService.insert(user);
}UserController{@AutowwiredUserService userService;userService.insert(user);
}

乍一看好像没什么区别,好像都是一样的。在controller里面创建了一个service对象然后调用它里面的方法。但是换个角度想想, 如果还有2个,3个,甚至n个类需要用到这个service呢,那它岂不是要被创建n次,这样就会极大的浪费资源,分分钟就内存溢出了。

企业开发案例:

我们只需要在xml配置文件里面指定配置参数,然后在类上加上spring注解它就能帮我们管理对象了,那它又是怎么实现的呢? 答案是: xml解析 + 反射 + 工厂模式。

手写IOC容器,演示它的加载过程:

1. 模仿spring,我们也定义一个注解

@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface MyService {}@Target({ TYPE, FIELD, METHOD })
@Retention(RUNTIME)
public @interface MyAutowired {}

2. 像使用spring注解一样,使用我们刚才的注解

@MyService
public class OrderService {public void add() {System.out.println("Order....add()");}
}@MyService
public class UserService {@MyAutowiredprivate OrderService orderService;public void add() {orderService.add();System.out.println("User....add()");}
}

3. 演示容器加载核心代码

/*** SpringIOC容器实现过程*/
public class MyClassPathXmlApplicationContext {// 1. 指定扫描包的范围private String packageName ;// Spring的bean容器 (容器启动时初始化所有bean,默认单例)  key:beanName(默认类名小写)  value:bean对象private ConcurrentHashMap<String, Object> beans;public MyClassPathXmlApplicationContext(String packageName) throws Exception {// 类加载时初始化这些参数this.packageName = packageName;this.beans = new ConcurrentHashMap<String, Object>();initBeans();// 初始化所有类initEntryField();// 初始化所有类的属性
    }/*** 初始化bean(IOC控制反转)*/public void initBeans() throws Exception {// 2. 通过java反射扫描指定包下面所有类的class地址List<Class<?>> classes = ClassUtil.getClasses(packageName);ConcurrentHashMap<String, Object> classExistAnnotation = this.findClassExistAnnotation(classes);if(classExistAnnotation == null || classExistAnnotation.isEmpty()) throw new Exception("cannot find bean");}/*** 判断类上面是否存在bean的注解*/private ConcurrentHashMap<String, Object> findClassExistAnnotation(List<Class<?>> classes) throws InstantiationException, IllegalAccessException {for(Class<?> classInfo : classes) {// 3. 获取指定路径中有ioc注解的类MyService annotation = classInfo.getAnnotation(MyService.class);if(annotation!=null) {String className = classInfo.getSimpleName();// 获取类名称// 4. 将类名首字母小写,获取bean名称。String beanaName = StringUtil.toLowerCaseFirstOne(className);// 5. 反射初始化对象Object object = classInfo.newInstance();// 6. 将bean对象存入spring容器中
                beans.put(beanaName, object);}}return beans;// 对象初始化完成
    }    /*** 初始化属性*/private void initEntryField() throws Exception {// 7. 遍历spring容器中所有的bean对象for (Entry<String, Object> entry : beans.entrySet()) {Object bean = entry.getValue();this.attriAssign(bean);}}/*** 依赖注入实现原理(DI依赖注入)*/public void attriAssign(Object object) throws Exception {Class<? extends Object> classInfo = object.getClass();// 8. 使用反射机制,获取当前类的所有属性值Field[] fields = classInfo.getDeclaredFields();for(Field field : fields) {// 9. 获取有@MyAutowired注解的属性MyAutowired myAutowired = field.getAnnotation(MyAutowired.class);if(myAutowired != null) {// 10. 获取属性名称String beanName = field.getName();// 11. 默认使用属性名称,查找bean容器对象Object bean = this.getBean(beanName);if(bean != null) {field.setAccessible(true);// 允许访问私有属性// 12. 将得到的bean对象赋值给当前对象的属性上。(bean名称=属性名称)
                    field.set(object, bean);}}}}/*** 通过bean名称去spring容器里面获取bean对象*/public Object getBean(String beanName) throws Exception {if(StringUtils.isEmpty(beanName)) throw new Exception("beans.factory.BeanCreationException");Object object = beans.get(beanName);return object;}/*** 测试*/public static void main(String[] args) throws Exception {MyClassPathXmlApplicationContext applicationContext = new MyClassPathXmlApplicationContext("com.wulei.service");UserService userService = (UserService)applicationContext.getBean("userService");userService.add();}
}

依赖注入:比如userController里面的userService属性加上bean注解,在类被加载时通过反射获取service的对象,并且赋值给该属性,这就叫做依赖注入。
控制反转:controller引用service的实例,不需要通过new来创建,将创建对象的责任转移给spring容器,这就叫反转; ioc容器实现对象的创建,以及外部资源的获取(其他类的属性和方法),这就叫控制

转载于:https://www.cnblogs.com/wlwl/p/10122236.html

100行代码撸完SpringIOC容器相关推荐

  1. 100行代码撸一个语音对话助手

    前言 之前在CSDN上看到有人用python调用语音api接口实现一个语音对话机器人的功能,于是依葫芦画瓢,按照方法用python撸了一个语音对话助手,并成功在一个linux 智能音箱上应用并实现播报 ...

  2. 一天,我用100行代码撸了一个表白神器!喜欢拿走~

    5月21日,"程序员用代码花式表白"顶上热搜,某广场的大屏,出现了程序员用Java语言,拼成了薇娅头像进行表白,网友不禁发出感叹:这样的程序员还缺女朋友吗? 看到这儿,你以为学习J ...

  3. react hooks使用_我如何使用React Hooks在约100行代码中构建异步表单验证库

    react hooks使用 by Austin Malerba 奥斯汀·马勒巴(Austin Malerba) 我如何使用React Hooks在约100行代码中构建异步表单验证库 (How I bu ...

  4. 用python画苹果的logo_简单几步,100行代码用Python画一个蝙蝠侠的logo

    转自:菜鸟学Python 简单几步,100行代码用Python画一个蝙蝠侠的logo-1.jpg (35.33 KB, 下载次数: 0) 2020-7-30 12:04 上传 蝙蝠侠作为DC漫画的核心 ...

  5. WebServer应用示例:不到100行代码玩转Siri语音控制 | ESP32轻松学(Arduino版)

    ESP32轻松学系列文章目录: ESP32 概述与 Arduino 软件准备 蓝牙翻页笔(PPT 控制器) B 站粉丝计数器 Siri 语音识别控制 LED 灯 Siri 语音识别获取传感器数据 本期 ...

  6. PONG - 100行代码写一个弹球游戏

    大家好,欢迎来到 Crossin的编程教室 ! 今天跟大家讲一讲:如何做游戏 游戏的主题是弹球游戏<PONG>,它是史上第一款街机游戏.因此选它作为我这个游戏开发系列的第一期主题. 游戏引 ...

  7. python画画100行代码_简单几步,100行代码用Python画一个蝙蝠侠的logo

    原标题:简单几步,100行代码用Python画一个蝙蝠侠的logo 转自:菜鸟学Python 蝙蝠侠作为DC漫画的核心人物之一,一直都受到广大粉丝的喜爱,而笔者作为DC的铁杆粉丝,自然也是老爷(粉丝对 ...

  8. 100行代码教你爬取斗图网(Python多线程队列)

    100行代码教你爬取斗图网(Python多线程队列) 前言 根据之前写的两篇文章,想必大家对多线程和队列有了一个初步的了解,今天这篇文章就来实战一下,用多线程 + 队列 爬取斗图网的全网图片. 你还在 ...

  9. C语言100行代码实现推箱子

    1 C语言100行代码实现推箱子 1.1 概述  C语言是很好入门编程的一个语言,它拥有着很好的移植性,基本上所有的平台都支持C语言编程.有些C语言基础的你,是不是也很想做一个项目来检验一下自己的学习 ...

最新文章

  1. 【.NET开发之美】如何提高.NET DataMap中的加载速度
  2. system类的 静态方法可以启动垃圾回收器。_Java—System类入门学习
  3. java外卖系统源码_JAVAWEB校园订餐系统项目源码 一个外卖点餐系统 - 下载 - 搜珍网...
  4. 安卓应用安全指南 4.9 使用`WebView`
  5. c语言中extern关键字_了解C语言中的extern关键字
  6. (转载)Stackoverflow让我们变懒了?
  7. 硬盘可以分为几类,监控专用硬盘和普通硬盘有什么区别?
  8. Java设计模式之工厂模式
  9. linux 网络对时
  10. 电脑系统声音怎么录制 如何录制电脑内部音频
  11. Spring Boot 之---什么是热部署?---怎么使用?
  12. 二、T100库存杂收、杂发、报废管理篇
  13. 快速搭建一个APMT265树莓派无人机
  14. Science | 为什么会吃太多?研究发现肠道细菌可以与大脑直接对话
  15. LeedCode 241. Different Ways to Add Parentheses
  16. JVE非我烟弹降价40%,电子烟价格革命真的来了
  17. Windows bat常用批处理命令学习
  18. python可视化疫情事实报告(pyecharts)——可视化
  19. 数值法求解微分博弈问题(〇)——定义
  20. Zookeeper开源客户端Curator之基本功能讲解

热门文章

  1. C语言---输出三角形字符阵列
  2. mach-o hook
  3. 第1章 编程心理门槛
  4. 《Java核心技术 卷Ⅱ 高级特性(原书第10版)》一3.6.2 使用StAX解析器
  5. 直播App测试重点问题 - 服务器压力
  6. rhel-server-7.2-x86_64无法联网(VMware环境)
  7. 转(HP大中华区总裁孙振耀退休感言)
  8. 网络IO之阻塞、非阻塞、同步、异步总结
  9. Liferay CE 6.1安装教程
  10. 10个最佳jQuery Lightbox效果插件收集