我们在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. Ubuntu系统---以virtualenv方式安装Tensorflow-CPU

    Ubuntu系统---以virtualenv方式安装Tensorflow-CPU 一.安装环境 环境:Ubuntu18.04+CPU+python2.7 本文介绍:如何在ubuntu上以virtual ...

  2. 一图一知-TS之函数function

  3. SQL 递归查询,意淫CTE递归的执行步骤

    今天用到了sql的递归查询.递归查询是CTE语句with xx as(....)实现的. 假如表Category数据如下. 我们想查找机枪这个子分类极其层次关系(通过子节点,查询所有层级节点).以下是 ...

  4. HTML5——5 HTML5 SVG

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. CSCD核心,北大中文核心

    从两篇文章看两个杂志 title 子空间聚类的重建模型及其快速算法 稀疏正则非凸优化问题之全局收敛分析 author 夏雨晴(浙江大学数学科学学院),张振跃 储敏(武汉大学数学与统计学院) journ ...

  6. 浅析servlet

    目录 Servlet简介 Servlet定义 Servlet的特点 Servlet底层原理 Servlet GenericServlet HttpServlet Servlet的生命周期 Servle ...

  7. kickstart批量装机脚本

    #!/bin/bash #安装必备的软件 yum -y install dhcp tftp-server tftp xinetd syslinux vsftpd yum -y install *kic ...

  8. ACM-ICPC 2015 沈阳赛区现场赛 F. Frogs && HDU 5514(容斥)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5514 题意:有m个石子围成一圈, 有n只青蛙从跳石子, 都从0号石子开始, 每只能越过xi个石子.问所 ...

  9. Vmware虚拟机 centos7设置固定IP地址

    参考文章:https://www.cnblogs.com/lfhappy/p/10798400.html      https://blog.csdn.net/u014466635/article/d ...

  10. 012_linuxC++之_类的继承定义

    (一)访问控制和继承 公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基 ...