从零开始写javaweb框架笔记15-搭建轻量级JAVAWEB框架-实现依赖注入功能
来源:互联网 发布:豆豆美妆馆扒皮 知乎 编辑:程序博客网 时间:2024/05/22 15:26
之前定义了@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);
- }
- }
- }
- }
- }
- }
- }
- }
只需在IocHelper的静态代码库中实现相关逻辑,就能完成IOC容器的初始化工作。这么这个代码块在上面时候进行加载了?
其实IocHelper类加载的时候就会加载这个代码块,后面需要找一个统一的地方来加载IocHelper。
上面的代码涉及了CollectionUtil(对集合的封装工具类),ArrayUtil(对数组的封装工具类)工具类
CollecionUtil的代码如下:
- package org.smart4j.framework.org.smart4j.framework.util;
- import org.apache.commons.collections4.CollectionUtils;
- import org.apache.commons.collections4.MapUtils;
- import java.util.Collection;
- import java.util.Map;
- /**
- * Created by jack on 2017/5/23.
- * 集合工具类
- */
- public class CollectionUtil {
- /**
- * 判断Collection是否为空
- */
- public static boolean isEmpty(Collection<?> collection){
- return CollectionUtils.isEmpty(collection);
- }
- /**
- *判断Collection是否非空
- */
- public static boolean isNotEmpty(Collection<?> collection){
- return !isEmpty(collection);
- }
- /**
- * 判断Map是否为空
- */
- public static boolean isEmpty(Map<?,?> map){
- return MapUtils.isEmpty(map);
- }
- /**
- * 判断Map是否非空
- */
- public static boolean isNotEmpty(Map<?,?> map){
- return !isEmpty(map);
- }
- }
ArrayUtil的代码如下:
- package org.smart4j.framework.org.smart4j.framework.util;
- import org.apache.commons.lang3.ArrayUtils;
- /**
- * Created by jack on 2017/5/23.
- * 数组工具类
- */
- public class ArrayUtil {
- /**
- * 判断数组是否非空
- */
- public static boolean isNotEmpty(Object[] array) {
- return !ArrayUtils.isEmpty(array);
- }
- /**
- * 判断数组是否为空
- */
- public static boolean isEmpty(Object[] array) {
- return ArrayUtils.isEmpty(array);
- }
- }
可见一个简单的IOC框架十几行代码就搞定了,似乎比想象的简单。需要注意的是,此时在Ioc框架中管理的Bean都是单例的,由于Ioc框架底层还是从BeanHelper获取Bean Map的,而Bean Map中的对象都是事先创建好并放入这个bean容器的,所有的对象都是单例的。
下面在给出一个StringUtil,字符串集合工具类的代码:
- package org.smart4j.framework.org.smart4j.framework.util;
- import org.apache.commons.lang3.StringUtils;
- /**
- * Created by jack on 2017/5/23.
- * 字符串工具类
- */
- public class StringUtil {
- /*
- * 判断字符串是否为空
- * */
- public static boolean isEmpty(String str){
- if(str != null){
- str=str.trim();
- }
- return StringUtils.isEmpty(str);
- }
- /*
- * 判断字符串是否非空
- * */
- public static boolean isNotEmpty(String str){
- return !isEmpty(str);
- }
- }
此时框架代码地址:框架代码地址
- 从零开始写javaweb框架笔记15-搭建轻量级JAVAWEB框架-实现依赖注入功能
- 从零开始写javaweb框架笔记15-搭建轻量级JAVAWEB框架-实现依赖注入功能
- 从零开始写javaweb框架笔记14-搭建轻量级JAVAWEB框架-实现Bean容器
- 从零开始写javaweb框架笔记14-搭建轻量级JAVAWEB框架-实现Bean容器
- 从零开始写javaweb框架笔记16-搭建轻量级JAVAWEB框架-加载Controller,初始化框架
- 从零开始写javaweb框架笔记16-搭建轻量级JAVAWEB框架-加载Controller,初始化框架
- 《从零开始写Javaweb框架》知识点--依赖注入的实现
- 从零开始写javaweb框架笔记11-搭建轻量级JAVAWEB框架-搭建开发环境
- 从零开始写javaweb框架笔记10-搭建轻量级JAVAWEB框架-确定目标
- 从零开始写javaweb框架笔记13-搭建轻量级JAVAWEB框架-开发一个类加载器
- 从零开始写javaweb框架笔记17-搭建轻量级JAVAWEB框架-请求转发
- 从零开始写javaweb框架笔记13-搭建轻量级JAVAWEB框架-开发一个类加载器
- 从零开始写javaweb框架笔记12-搭建轻量级JAVAWEB框架-定义框架配置项,加载配置项
- [笔记]架构探险-从零开始写JavaWeb框架-1. 之搭建轻量级mvc框架
- 从零开始写javaweb框架笔记2-搭建web项目框架
- 从零开始写javaweb框架笔记23-使框架具备AOP特性-实现事务控制特性
- 从零开始写javaweb框架笔记7-动手开发web应用
- 架构探险 从零开始写javaweb框架
- 友盟社会化分享 QQ空间不显示分享的图片 (已解决)
- Linux下根据进程的名字杀死进程
- Leetcode——Target Sum
- 十分钟搞定pandas(Python数据预处理库)
- 安装svn插件集成myeclipse2014的两种方式
- 从零开始写javaweb框架笔记15-搭建轻量级JAVAWEB框架-实现依赖注入功能
- 单片机Microcontrollers
- Win7系统安装软件提示"不是有效的win32应用程序"的解决方法
- 在运行MFC程序的Release版本时,断点断在"INT_PTR nResponse = dlg.DoModal();"这句话上的处理
- 微擎we7模块和模板安装方法
- 第一个MyBatis程序
- PCB emi设计要点
- freemaker模板中long值默认用,号分隔问题
- VM虚拟机下安装Centos7.0图文教程