我们在Controller中定义了Service成员变量,然后在Controller的Action方法中调用Service成员变量的方法,那么如果实现Service的成员变量? 之前定义了@Inject注解,就用它来实现Service是例话,那么谁来实例化呢。

不是开发者通过new的方式来实例化,而是通过框架自身来实例化,像这类实例化过程称为IOC(控制反转),控制不是由开发者来决定,而是反转给框架了。一般也将控制反转称为DI(依赖注入),可以理解为将某个类需要依赖的成员注入到这个类中,那么我们该如何实现了?

最简单的方式是,先通过BeanHelper获取所有的BeanMap(是一个Map<Class<?>,Object>结构,记录了类与对象的映射关系),然后遍历这个映射关系,分别取出Bean类与Bean实例,进而通过反射获取类中所有成员变量。继续遍历这些成员变量,在循环中判断这些成员变量是否带有Inject注解,若带有该注解,则从BeanMap根据Bean类取出Bean实例。最后通过ReflectionUtil的setField的方法来修改当前成员变量的值。

把上面的逻辑写成一个IocHelper的类,让它来完成这件事,代码如下:

 package org.smart4j.framework.helper;

 import org.smart4j.framework.annotation.Inject;
import org.smart4j.framework.org.smart4j.framework.util.ArrayUtil;
import org.smart4j.framework.org.smart4j.framework.util.CollectionUtil;
import org.smart4j.framework.org.smart4j.framework.util.ReflectionUtil; import java.lang.reflect.Field;
import java.util.Map; /**
* Created by jack on 2017/5/23.
* 依赖注入助手类
*/
public class IocHelper {
static {
//获取所有的Bean类与Bean实例之间的关系(简称Bean Map)
Map<Class<?>, Object> beanMap = BeanHelper.getBeanMap();
if (CollectionUtil.isNotEmpty(beanMap)) {
//遍历beanMap
for (Map.Entry<Class<?>, Object> beanEntry : beanMap.entrySet()) {
//从beanMap中获取bean类与bean实例
Class<?> beanClass = beanEntry.getKey();
Object beanInstance = beanEntry.getValue();
//获取Bean类定义的所有成员变量(简称Bean Field)
Field [] beanFields = beanClass.getDeclaredFields();
if (ArrayUtil.isNotEmpty(beanFields)){
//遍历beanField
for (Field beanField : beanFields) {
//判断当前的Bean Field是否带有Inject注解
if (beanField.isAnnotationPresent(Inject.class)){
//在Bean Map中获取Bean Field对应的实例
Class<?> beanFieldClass = beanField.getType();
Object beanFieldInstance = beanMap.get(beanFieldClass);
if (beanFieldInstance != null){
//通过放射初始化beanField值
ReflectionUtil.setField(beanInstance,beanField,beanFieldInstance);
}
}
}
} }
}
}
}

手写web框架之实现依赖注入功能的更多相关文章

  1. 30个类手写Spring核心原理之依赖注入功能(3)

    本文节选自<Spring 5核心原理> 在之前的源码分析中我们已经了解到,依赖注入(DI)的入口是getBean()方法,前面的IoC手写部分基本流程已通.先在GPApplicationC ...

  2. 从零写Java Web框架——实现Ioc依赖注入

    大概思路 通过读取配置文件,获取框架要加载的包路径:base-package,类似于 Spring 配置文件中的: <context:component-scan base-package=&q ...

  3. 2、手写Unity容器--第一层依赖注入

    这个场景跟<手写Unity容器--极致简陋版Unity容器>不同,这里构造AndroidPhone的时候,AndroidPhone依赖于1个IPad 1.IPhone接口 namespac ...

  4. 手写web框架之加载Controller,初始化框架

    1,加载Controller     我们需要创建 一个ControllerHelper类,让它来处理下面的逻辑:      通过ClassHelper我们可以获取所有定义了Controller注解的 ...

  5. 手写web框架之实现Bean容器

    实现Bean容器    使用ClassHelper可以获取所加载的类,但无法通过类来实例化对象,因此我们需要提供一个反射工具类,让它封装java反射相关的API,对外提供更好用的工具方法.将该类命名为 ...

  6. 手写web框架之加载配置项目

    一  定义框架配置项 在项目的src/main/resources目录下创建一个名为smart.propertiesd的文件,文件的内容如下: smart.framework.jdbc.driver= ...

  7. 手写web框架之开发一个类加载器

    ackage io.renren.common; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUti ...

  8. 手写Spring框架,加深对Spring工作机制的理解!

    在我们的日常工作中,经常会用到Spring.Spring Boot.Spring Cloud.Struts.Mybatis.Hibernate等开源框架,有了这些框架的诞生,平时的开发工作量也是变得越 ...

  9. 手写MVC框架(一)-再出发

    背景 前段时间把之前写的DAO框架(手写DAO框架(一)-从“1”开始)整理了一下,重构了一版.整理过程中看以前写的代码,只是为了了解实现,只是为了实现,代码写的有点粗糙.既然已经整理了DAO框架,索 ...

随机推荐

  1. ConcurrentDictionary源码概读

    ConcurrentDictionary的数据结构主要由Tables和Node组成,其中Tables包括桶(Node,节点)数组.局部锁(Local lock).每个锁保护的元素数量(PerLock) ...

  2. HashMap源码分析一

           HashMap在java编程中,算使用频率top10中的类了.这里是关于HashMap的源码的分析.一个类的源码分析,要看他的来龙去脉,他的历史迭代.一来从以前的版本开始分析,由易到难: ...

  3. solr 中文分词相关(转载)

    smartcn和ik的对比,来自http://www.cnblogs.com/hadoopdev/p/3465556.html 一.引言: 年的时候,就曾经有项目涉及到相关的应用(Lunce构建全文搜 ...

  4. P5657 格雷码

    思路 考场上的递归思路 每次向下递归的时候判断是左半边还是右半边即可 注意向右半边递归之后下一层序列要反转过来即可 代码 #include <cstdio> #include <al ...

  5. 在Chrome浏览器中点击链接,打开IE浏览器,跳转到指定页面并传递参数

    需求: 在Chrome浏览器中点击链接,打开IE浏览器,跳转到指定页面并传递参数 过程: 一些应用软件可以通过点击URL链接启动并执行操作(例如迅雷),这是如何做到的呢? 主要是通过修改注册表,注册U ...

  6. 用node.js读写文件

    node.js没有二进制数据类型,却提供了类似字节数组的“流“数据类型,着一种数据类型在文件系统模块中频频出现 node.js打开文件 fs = require('fs'); console.log( ...

  7. linux系统编程--信号

    信号的概念 man 7 siganl  查看man手册 信号在我们的生活中随处可见, 如:古代战争中摔杯为号:现代战争中的信号弹:体育比赛中使用的信号枪......他们都有共性:1. 简单 2. 不能 ...

  8. sudo/su

    linux用户分为根用户/ 普通用户 系统用户 根用户和普通用户是可以实际登录到系统中的,普通用户是没办法使用useradd添加新用户的,只有根用户有权限 当然,也可以使用su su 是切换用户的意思 ...

  9. hdu 3555 Bomb(数位dp入门)

    Bomb Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) Total Subm ...

  10. HGOI 20191108 题解

    Problem A 新婚快乐 一条路,被$n$个红绿灯划分成$n+1$段,从前到后一次给出每一段的长度$l_i$,每走$1$的长度需要$1$分钟. 一开始所有红绿灯都是绿色的,$g$分钟后所有红绿灯变 ...