从零写Java Web框架——实现Ioc依赖注入
大概思路
- 通过读取配置文件,获取框架要加载的包路径:base-package,类似于 Spring 配置文件中的:
- <context:component-scan base-package="*"/>
- 将 base-package 路径下的所有类都加载,并保存在一个 Set<Class<?>> classSet 中;
- 初始化 Bean 容器,遍历 classSet,通过反射获得 Class 的实例,并保存 Class 与 Class实例的映射关系,即 Map<Class<?>, Object> instanceMap;
- 初始化 Ioc,遍历 Bean 容器,找出有 @Controller 注解的 Class,遍历其成员变量,如果其成员变量有 @Inject 注解,则从 instanceMap 中获取对应的 Service 类,通过反射设置该 Bean 实例的成员变量;
思维导图
对比 Spring 框架
Spring 的设计理念:
Spring 的三个核心组件就是 Context、Core 和 Bean 组件。
- Context 组件:就是一个 Bean 关系的集合,这个关系集合又叫做 Ioc 容器;
- Core 组件:是集发现、建立和维护每个 Bean 之间关系所需的一系列工具类;
- Bean 组件:包装 Bean 实例的 Object,Bean 由 BeanFactory 创建;
三者关系,如下图所示:
与 Spring 框架三大组件的对比:
Context 组件,对应,Ioc 容器(IocHelper 提供依赖注入功能);
Core 组件,对应,类加载器、反射工具类,建立和维护 Bean 之间关系的工具类;
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);
- }
- // 有入参的 Action 方法
- 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 你好
从零写Java Web框架——实现Ioc依赖注入的更多相关文章
- 从零写Java Web框架——请求的处理DispatcherServlet
大概思路 继承 HttpServlet,实现 DispatcherServlet,拦截所有请求: DispatchServlet 重写 init()方法,负责初始化框架: 重写 service()方法 ...
- 读《架构探险——从零开始写Java Web框架》
内容提要 <架构探险--从零开始写Java Web框架>首先从一个简单的 Web 应用开始,让读者学会如何使用 IDEA.Maven.Git 等开发工具搭建 Java Web 应用:接着通 ...
- 【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框架>- S ...
- 手写web框架之实现依赖注入功能
我们在Controller中定义了Service成员变量,然后在Controller的Action方法中调用Service成员变量的方法,那么如果实现Service的成员变量? 之前定义了@Injec ...
- Java Web系列:Spring依赖注入基础
一.Spring简介 1.Spring简化Java开发 Spring Framework是一个应用框架,框架一般是半成品,我们在框架的基础上可以不用每个项目自己实现架构.基础设施和常用功能性组件,而是 ...
- 《架构探险——从零开始写Java Web框架》这书不错,能看懂的入门书
这书适合我. 哈哈,结合 以前的知识点,勉强能看懂. 讲得细,还可以参照着弄出来. 希望能坚持 完成啦... 原来,JSTL就类似于DJANGO中的模板. 而servlet类中的res,req,玩了D ...
- 架构探险——从零开始写Java Web框架》第二章照作
沉下来慢慢看实现了. 越来越觉得可以和DJANGO作对比. package org.smart4j.chapter2.model; /** * Created by sahara on 2016/3/ ...
- Smart Framework:轻量级 Java Web 框架
Smart Framework:轻量级 Java Web 框架 收藏 黄勇 工作闲暇之余,我开发了一款轻量级 Java Web 框架 —— Smart Framework. 开发该框架是为了: 加 ...
- JAVA web 框架集合
“框架”犹如滔滔江水连绵不绝, 知道有它就好,先掌握自己工作和主流的框架: 在研究好用和新框架. 主流框架教程分享在Java帮帮-免费资源网 其他教程需要时间制作,会陆续分享!!! 152款框架,你还 ...
随机推荐
- 基于matplotlib的数据可视化 - 饼状图pie
绘制饼状图的基本语法 创建数组 x 的饼图,每个楔形的面积由 x / sum(x) 决定: 若 sum(x) < 1,则 x 数组不会被标准化,x 值即为楔形区域面积占比.注意,该种情况会出现 ...
- thinkphp __hash__
thinkphp会自动在模板文件的表单后加一个__hash__来验证提交,保证一定程序上的安全: 但是有时用不着,可以用: C('TOKEN_ON',false); 关闭这项
- Docker 学习笔记 ---Docker组件
Docker组件 1. 客户端:dockerclient 2. 服务端:dockerserver 3. Docker镜像 4. Registry 5. Docker 容器 Docker客户端 ...
- GC那些事儿--Android内存优化第一弹
引言 接App优化之内存优化(序), 作为App优化系列中内存优化的一个小部分. 由于内存相关知识比较生涩, 内存优化中使用到的相关工具, 也有很多专有名词. 对Java内存管理, GC, Andro ...
- ios标准开发者账号 ios企业开发者账号的区别总结
ios标准开发者账号 ios企业开发者账号的区别总结 ios标准开发者项目 1.ios标准开发者项目账号可以发布到app store 2.ios标准开发者项目分为两种:①个人开发者②公司/机构开发 ...
- RGB 常用颜色对照表
http://blog.csdn.net/xiaoting451292510/article/details/8226325
- java.lang.RuntimeException: Date pattern must be set for column update_time in the schema of component
使用Talend open studio ,从mysql数据源中读取数据,将数据导出到excel文档,另外一个mysql数据库,和一个普通文件,遇到标题的错误,模型如下图所示: tMap将30.7中 ...
- MySql(十):MySQL性能调优——MySQL Server性能优化
本章主要通过针对MySQL Server( mysqld)相关实现机制的分析,得到一些相应的优化建议.主要涉及MySQL的安装以及相关参数设置的优化,但不包括mysqld之外的比如存储引擎相关的参数优 ...
- grub配置指南
GRUB(统一引导装入器)是基本的Linux引导装入器.其有四个作用,如下:1.选择操作系统(如果计算机上安装了多个操作系统).2.表示相应引导文件所在的分区.3.找到内核.4.运行初始内存盘,设置内 ...
- Atitit 图像处理类库 halcon11 安装与环境搭建attilax总结
Atitit 图像处理类库 halcon11 安装与环境搭建attilax总结 正常安装软件,安装前请先退出其它一切正在运行的程序. 先安装halcon-10.0-windows.exe.安装完成后 ...