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

大概思路

  1. 通过读取配置文件,获取框架要加载的包路径:base-package,类似于 Spring 配置文件中的:

    <context:component-scan base-package="*"/>
  2. 将 base-package 路径下的所有类都加载,并保存在一个 Set<Class<?>> classSet 中;
  3. 初始化 Bean 容器,遍历 classSet,通过反射获得 Class 的实例,并保存 Class 与 Class实例的映射关系,即 Map<Class<?>, Object> instanceMap;
  4. 初始化 Ioc,遍历 Bean 容器,找出有 @Controller 注解的 Class,遍历其成员变量,如果其成员变量有 @Inject 注解,则从 instanceMap 中获取对应的 Service 类,通过反射设置该 Bean 实例的成员变量;

思维导图

简单模拟 Ioc

模拟 Controller 类:

package org.zhengbin.ioc.test;

/**
 * Created by zhengbinMac on 2017/4/10.
 */
// 假设这是一个 Controller 类
public class TestController {

    // 假设这是一个待注入的 Service
    private String wordService;

    // 假设这是一个 Action 方法,方法中有调用 Service 来实现具体的业务逻辑
    public void toOut() {
        System.out.println("Hello1 " + wordService);
    }

    public void toOut(String str) {
        System.out.println("Hello2 " + str);
    }
}

模拟 Ioc 注入管理:

package org.zhengbin.ioc.test;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by zhengbinMac on 2017/4/10.
 */
public class TempIoc {
    // Bean 容器,保存 Bean 类与 Bean 实例之间的映射关系
    private static Map<Class<?>, Object> BEAN_MAP = new HashMap<Class<?>, Object>();

    public static void main(String[] args) {
        try {
            // 加载类实例
            Class<?> cla = getClazz("org.zhengbin.ioc.test.TestController");
            // 存入 BeanMap 中(即放入 Bean 容器中)
            Object instance = newInstance(cla);
            BEAN_MAP.put(cla, instance);

            // 需要时(在初始化整个 Web 框架时),从 BEAN_MAP 中获取类与类实例(即 Bean 类与 Bean 实例)
            Object bean = BEAN_MAP.get(cla);

            // 获取反射类的所有变量,getFields()是获取公开的变量
            Field[] fields = cla.getDeclaredFields();
            for (Field field : fields) {
                // 设置反射类 "实例" 的成员变量值
                setField(bean, field, "你好");
            }

            // 获取 Bean 实例的所有方法
            Method[] methods = cla.getDeclaredMethods();
            for (Method method : methods) {
                // 模拟 Action 方法是否需要带入参数
                Class<?>[] classes = method.getParameterTypes();
                if (classes.length == 0) {
                    // 调用方法
                    invokeMethod(bean, method);
                } else {
                    invokeMethod(bean, method, "你好");
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 加载类
     * @param packageName 类的全路径地址(包名.类名)
     * @return            Bean 类
     */
    private static Class<?> getClazz(String packageName) {
        Class<?> cls;
        try {
            cls = Class.forName(packageName);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return cls;
    }

    /**
     * 创建实例
     * @param cls Bean 类
     * @return    Bean 类的实例
     */
    private static Object newInstance(Class<?> cls) {
        Object instance;
        try {
            instance = cls.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return instance;
    }

    /**
     * 设置成员变量值
     * @param obj   Bean 实例
     * @param field 成员变量
     * @param value 成员变量的赋值
     */
    private static void setField(Object obj, Field field, Object value) {
        try {
            // 值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。
            // 值为 false 则指示反射的对象应该实施 Java 语言访问检查。
            field.setAccessible(true);
            field.set(obj, value);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 调用方法
     * @param obj    Bean 实例
     * @param method 方法(Controller 中的 Action 方法)
     * @param args   方法的入参
     * @return       方法返回值
     */
    private static Object invokeMethod(Object obj, Method method, Object... args) {
        Object result;
        try {
            method.setAccessible(true);
            result = method.invoke(obj, args);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return result;

    }
}

输出结果:

Hello1 你好
Hello2 你好
时间: 2024-10-09 02:06:45

从零写Java Web框架——实现Ioc依赖注入的相关文章

从零写Java Web框架——请求的处理

大概思路 继承 HttpServlet,实现 DispatcherServlet,拦截所有请求: DispatchServlet 重写 init()方法,负责初始化框架: 重写 service()方法,获取 HttpServletRequest.HttpServletResponse: 通过 HttpServletRequest.HttpServletResponse,获取请求路径.请求参数,进行请求的处理,并做转发或重定向: 思维导图

【EatBook】-NO.3.EatBook.3.JavaArchitecture.2.001-《架构探险:从零开始写Java Web框架》-

1.0.0 Summary Tittle:[EatBook]-NO.3.EatBook.3.JavaArchitecture.2.001-<架构探险:从零开始写Java Web框架>- Style:JavaArchitecture Series:Architecture Publishing House:电子工业 Author: 黄勇 Page Number:349 Since:2017-04-06 End:ing... Total Hours:ing... Degree Of Diffcul

(转)Java Web系列:Spring依赖注入基础

一.Spring简介 1.Spring简化Java开发 Spring Framework是一个应用框架,框架一般是半成品,我们在框架的基础上可以不用每个项目自己实现架构.基础设施和常用功能性组件,而是可以专注业务逻辑.因此学习Spring Framework在架构和模式方面的结构和原理,对我们在架构和模块级别的理解帮助极大.Spring Framework(参考1)的宗旨是简化Java开发,主要的手段如下: (1)在架构上解耦:通过DI(依赖注入)管理类型依赖,通过AOP分离关注点,减少重复代码

Java Web系列:Spring依赖注入基础

一.Spring简介 1.Spring简化Java开发 Spring Framework是一个应用框架,框架一般是半成品,我们在框架的基础上可以不用每个项目自己实现架构.基础设施和常用功能性组件,而是可以专注业务逻辑.因此学习Spring Framework在架构和模式方面的结构和原理,对我们在架构和模块级别的理解帮助极大.Spring Framework(参考1)的宗旨是简化Java开发,主要的手段如下: (1)在架构上解耦:通过DI(依赖注入)管理类型依赖,通过AOP分离关注点,减少重复代码

JAVA web 框架集合

“框架”犹如滔滔江水连绵不绝, 知道有它就好,先掌握自己工作和主流的框架: 在研究好用和新框架. 主流框架教程分享在Java帮帮-免费资源网 其他教程需要时间制作,会陆续分享!!! 152款框架,你还知道其他的吗? 留言你用过的web框架 Java开源web框架汇总 1 Struts2 Struts2是一个web应用框架.它不是一个Struts的新的发布版本,而是一个全新的框架.Struts2 是第二代基于Model-View-Controller (MVC)模型的web应用框架. Struts

java web 框架之struts2

简介:struts2是一个典型的mvc架构.利用它可是方便的实现某些功能. struts2 的工作流程图以及动态的action: 浏览器请求经过web容器,进入到struts2过滤器,然后搜索匹配,如果有与之对应的action对象,就会调用action对象的execut()方法,并根据处理的结果返回相应的值.通过创建多个action对象可以实现动态的action.也就是为了解决业务请求的多样性. 园长第一次接触框架,对于struts2框架的配置并不是很熟悉,对于初学者来说,很有必要讲讲strut

Java Web框架-----------------------struts2(官网教程版HelloWorld)

Java Web框架------------------struts2(官网教程版HelloWorld) 我们都知道Struts是Java Web 常用的三大框架之一,另外还有Spring.Hibernate.学习Struts很有必 要!那么怎么学习呢?我的建议是: 1.对于英语能力还可以的人,学技术我们要从官网文档学起,再结合中文别人所写的论文.博客,视频 等.这样可以达到事半功倍的效果. 2.对于阅读英语稍微吃力的人,我们可以下载有道词典,再来本计算机专业英语书,不懂就查,但是, 我们决不能

IoC 依赖注入、以及在Spring中的实现

资源来自网络: 去年火得不行的Spring框架,一般的书籍都会从IoC和AOP开始介绍起,这个IoC概念,个人感觉资料里都写得让人看得有些痛苦,所谓IoC,就是控制反转(Inversion of Control)的缩写,这个大家都知道,但是个人觉得理解这个概念,最好应该从依赖(dependence)开始讲起,以下观点由此展开: UML中依赖关系如A依赖于B,就是A中有对方的引用;也就是说依赖就是引用:A依赖于B,就是A使用B来做事情. 所谓依赖,举个例子说明,一个类Person,另一个类Car,

IoC 依赖注入容器 Unity

原文:IoC 依赖注入容器 Unity IoC 是什么? 在软件工程领域,“控制反转(Inversion of Control,缩写为IoC)”是一种编程技术,表述在面向对象编程中,可描述为在编译时静态分析器并不知道具体被耦合的对象,而该对象是在运行时被对象装配器绑定的. 在传统编程中,决定业务流程的对象是被静态分配的.而在 IoC 中,业务流程取决于对象装配器实例化提供的对象,这使利用抽象来定义对象间的交互成为可能.对象装配器为了能绑定一个对象,要求该对象必须具备兼容的抽象定义.例如类 Cla