zoukankan      html  css  js  c++  java
  • 手写web框架之实现依赖注入功能

      我们在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的类,让它来完成这件事,代码如下:

     1 package org.smart4j.framework.helper;
     2  
     3  
     4 import org.smart4j.framework.annotation.Inject;
     5 import org.smart4j.framework.org.smart4j.framework.util.ArrayUtil;
     6 import org.smart4j.framework.org.smart4j.framework.util.CollectionUtil;
     7 import org.smart4j.framework.org.smart4j.framework.util.ReflectionUtil;
     8  
     9 import java.lang.reflect.Field;
    10 import java.util.Map;
    11  
    12 /**
    13  * Created by jack on 2017/5/23.
    14  * 依赖注入助手类
    15  */
    16 public class IocHelper {
    17     static {
    18         //获取所有的Bean类与Bean实例之间的关系(简称Bean Map)
    19         Map<Class<?>, Object> beanMap = BeanHelper.getBeanMap();
    20         if (CollectionUtil.isNotEmpty(beanMap)) {
    21             //遍历beanMap
    22             for (Map.Entry<Class<?>, Object> beanEntry : beanMap.entrySet()) {
    23                 //从beanMap中获取bean类与bean实例
    24                 Class<?> beanClass = beanEntry.getKey();
    25                 Object beanInstance = beanEntry.getValue();
    26                 //获取Bean类定义的所有成员变量(简称Bean Field)
    27                 Field [] beanFields = beanClass.getDeclaredFields();
    28                 if (ArrayUtil.isNotEmpty(beanFields)){
    29                     //遍历beanField
    30                     for (Field beanField : beanFields) {
    31                         //判断当前的Bean Field是否带有Inject注解
    32                         if (beanField.isAnnotationPresent(Inject.class)){
    33                             //在Bean Map中获取Bean Field对应的实例
    34                             Class<?> beanFieldClass = beanField.getType();
    35                             Object beanFieldInstance = beanMap.get(beanFieldClass);
    36                             if (beanFieldInstance != null){
    37                                 //通过放射初始化beanField值
    38                                 ReflectionUtil.setField(beanInstance,beanField,beanFieldInstance);
    39                             }
    40                         }
    41                     }
    42                 }
    43  
    44  
    45             }
    46         }
    47     }
    48 }
  • 相关阅读:
    std thread
    windows更新包发布地址
    How to set up logging level for Spark application in IntelliJ IDEA?
    spark 错误 How to set heap size in spark within the Eclipse environment?
    hadoop 常用命令
    windows 安装hadoop 3.2.1
    windows JAVA_HOME 路径有空格,执行软连接
    day01MyBatisPlus条件构造器(04)
    day01MyBatisPlus的CRUD 接口(03)
    day01MyBatisPlus入门(02)
  • 原文地址:https://www.cnblogs.com/duan2/p/11749177.html
Copyright © 2011-2022 走看看