从零开始写javaweb框架笔记15-搭建轻量级JAVAWEB框架-实现依赖注入功能

来源:互联网 发布:豆豆美妆馆扒皮 知乎 编辑:程序博客网 时间:2024/05/22 15:26
我们在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的类,让它来完成这件事,代码如下:

    

[java] view plain copy print?
  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. }  


     只需在IocHelper的静态代码库中实现相关逻辑,就能完成IOC容器的初始化工作。这么这个代码块在上面时候进行加载了?

    其实IocHelper类加载的时候就会加载这个代码块,后面需要找一个统一的地方来加载IocHelper。

   上面的代码涉及了CollectionUtil(对集合的封装工具类),ArrayUtil(对数组的封装工具类)工具类

   CollecionUtil的代码如下:

[java] view plain copy print?
  1. package org.smart4j.framework.org.smart4j.framework.util;  
  2.   
  3. import org.apache.commons.collections4.CollectionUtils;  
  4. import org.apache.commons.collections4.MapUtils;  
  5.   
  6. import java.util.Collection;  
  7. import java.util.Map;  
  8.   
  9. /** 
  10.  * Created by jack on 2017/5/23. 
  11.  * 集合工具类 
  12.  */  
  13. public class CollectionUtil {  
  14.     /** 
  15.      * 判断Collection是否为空 
  16.      */  
  17.     public static boolean isEmpty(Collection<?> collection){  
  18.         return CollectionUtils.isEmpty(collection);  
  19.     }  
  20.     /** 
  21.      *判断Collection是否非空 
  22.      */  
  23.     public static boolean isNotEmpty(Collection<?> collection){  
  24.         return !isEmpty(collection);  
  25.     }  
  26.     /** 
  27.      * 判断Map是否为空 
  28.      */  
  29.     public static boolean isEmpty(Map<?,?> map){  
  30.         return MapUtils.isEmpty(map);  
  31.     }  
  32.     /** 
  33.      * 判断Map是否非空 
  34.      */  
  35.     public static boolean isNotEmpty(Map<?,?> map){  
  36.         return !isEmpty(map);  
  37.     }  
  38. }  


ArrayUtil的代码如下:

     

[java] view plain copy print?
  1. package org.smart4j.framework.org.smart4j.framework.util;  
  2.   
  3. import org.apache.commons.lang3.ArrayUtils;  
  4.   
  5. /** 
  6.  * Created by jack on 2017/5/23. 
  7.  * 数组工具类 
  8.  */  
  9. public class ArrayUtil {  
  10.     /** 
  11.      * 判断数组是否非空 
  12.      */  
  13.     public static boolean isNotEmpty(Object[] array) {  
  14.         return !ArrayUtils.isEmpty(array);  
  15.     }  
  16.   
  17.     /** 
  18.      * 判断数组是否为空 
  19.      */  
  20.     public static boolean isEmpty(Object[] array) {  
  21.         return ArrayUtils.isEmpty(array);  
  22.     }  
  23. }  

     可见一个简单的IOC框架十几行代码就搞定了,似乎比想象的简单。需要注意的是,此时在Ioc框架中管理的Bean都是单例的,由于Ioc框架底层还是从BeanHelper获取Bean Map的,而Bean Map中的对象都是事先创建好并放入这个bean容器的,所有的对象都是单例的。

    下面在给出一个StringUtil,字符串集合工具类的代码:

   

[java] view plain copy print?
  1. package org.smart4j.framework.org.smart4j.framework.util;  
  2.   
  3. import org.apache.commons.lang3.StringUtils;  
  4.   
  5. /** 
  6.  * Created by jack on 2017/5/23. 
  7.  * 字符串工具类 
  8.  */  
  9. public class StringUtil {  
  10.     /* 
  11.     * 判断字符串是否为空 
  12.     * */  
  13.     public static boolean isEmpty(String str){  
  14.         if(str != null){  
  15.             str=str.trim();  
  16.         }  
  17.         return StringUtils.isEmpty(str);  
  18.     }  
  19.     /* 
  20.     * 判断字符串是否非空 
  21.     * */  
  22.     public static boolean isNotEmpty(String str){  
  23.         return !isEmpty(str);  
  24.     }  
  25. }  

     此时框架代码地址:框架代码地址


阅读全文
0 0
原创粉丝点击