200行Java代码实现依赖注入框架

Java依赖注入实践:JSR 330与Spring框架的结合使用 JSR 330定义了一组注解,包括@Inject和@Qualifier,这些注解可以被用于实现依赖注入。Spring框架从4.0版本开始支持JSR 330规范,允许开发者使用或(Spring 6+)注解来简化配置和提高代码的可读性。 阅读详情


依赖注入框架并不神秘,其实它是非常简单的东西。不要去看spring的依赖注入源码,因为你只要一去看就意味着你再也写不敢下手自己撸了,它的功能因为过于强大,所以设计也过于复杂,普通程序员一眼看去只能望洋兴叹。

我也并没有去细致阅读spring源码。即便如此也只用了半天的时间便自己撸了一个基本满足标准依赖注入规范「JSR-330」的小框架iockids。这个小框架只有一个主类Injector,大约200行代码,它具备以下功能。

  1. 单例/非单例注入
  2. 构造器注入
  3. 字段注入
  4. 循环依赖注入
  5. Qualifier注入

我们看一个稍微复杂一点的使用示例

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;

import iockids.Injector;

@Singleton
class Root {

    @Inject
    @Named("a")
    Node a;

    @Inject
    @Named("b")
    Node b;

    @Override
    public String toString() {
        return String.format("root(%s, %s)", a.name(), b.name());
    }

}

interface Node {

    String name();

}

@Singleton
@Named("a")
class NodeA implements Node {

    @Inject
    Leaf leaf;

    @Inject
    @Named("b")
    Node b;

    @Override
    public String name() {
        if (b == null)
            return String.format("nodeA(%s)", leaf);
        else
            return String.format("nodeAWithB(%s)", leaf);
    }

}

@Singleton
@Named("b")
class NodeB implements Node {

    Leaf leaf;

    @Inject
    @Named("a")
    Node a;

    @Inject
    public NodeB(Leaf leaf) {
        this.leaf = leaf;
    }

    @Override
    public String name() {
        if (a == null)
            return String.format("nodeB(%s)", leaf);
        else
            return String.format("nodeBWithA(%s)", leaf);
    }

}

class Leaf {

    @Inject
    Root root;

    int index;

    static int sequence;

    public Leaf() {
        index = sequence++;
    }

    public String toString() {
        if (root == null)
            return "leaf" + index;
        else
            return "leafwithroot" + index;
    }

}

public class Demo {

    public static void main(String[] args) {
        var injector = new Injector();
        injector.registerQualifiedClass(Node.class, NodeA.class);
        injector.registerQualifiedClass(Node.class, NodeB.class);
        var root = injector.getInstance(Root.class);
        System.out.println(root);
    }

}

上面这份代码用到了iockids提供的所有功能。

  1. Root/NodeA/NodeB类是单例类
  2. Leaf类是非单例类
  3. 它们都使用了字段注入
  4. NodeB使用了构造器注入
  5. NodeA和NodeB还使用了Qualifier名称注入
  6. Leaf类中有Root类型的字段,这便是循环依赖
  7. NodeA中有NodeB字段,NodeB中有NodeA字段,这也是循环依赖

为了便于理解上述代码,我画了依赖图


上面的代码输出如下

root(nodeAWithB(leafwithroot0), nodeBWithA(leafwithroot1))

从这个输出中,我们也可以大致想象出依赖结构。

iockids提供了丰富的注入错误异常报告,防止用户注入配置出错。

比如我们将上面的NodeA和NodeB的名称都配置成一样的a,就会曝出下面的错误堆栈

iockids.InjectException: duplicated qualifier javax.inject.Named with the same class iockids.demo.Node
    at iockids.Injector.registerQualifiedClass(Injector.java:87)
    at iockids.Injector.registerQualifiedClass(Injector.java:70)
    at iockids.demo.Demo.main(Demo.java:106)

如果我们将NodeB的构造器随意加一个参数

@Inject
    public NodeB(Leaf leaf, int k) {
        this.leaf = leaf;
    }

运行时就会抛出下面的错误

iockids.InjectException: no accessible constructor for injection class int
    at iockids.Injector.createNew(Injector.java:120)
    at iockids.Injector.createNew(Injector.java:94)
    at iockids.Injector.createFromParameter(Injector.java:167)
    at iockids.Injector.createFromConstructor(Injector.java:145)
    at iockids.Injector.createNew(Injector.java:123)
    at iockids.Injector.createFromQualified(Injector.java:216)
    at iockids.Injector.createFromField(Injector.java:173)
    at iockids.Injector.injectMembers(Injector.java:233)
    at iockids.Injector.createNew(Injector.java:136)
    at iockids.Injector.createFromQualified(Injector.java:216)
    at iockids.Injector.createFromField(Injector.java:173)
    at iockids.Injector.injectMembers(Injector.java:233)
    at iockids.Injector.createNew(Injector.java:136)
    at iockids.Injector.createNew(Injector.java:94)
    at iockids.Injector.getInstance(Injector.java:245)
    at iockids.demo.Demo.main(Demo.java:107)

项目开源地址:github.com/pyloque/iock

关注公众号「码洞」,和大佬们一起来讨论iockids的设计与实现

RNA-Seq数据分析实战:从FastQC到STAR比对的完整流程(附避坑指南) 本文提供了RNA-Seq数据分析从FastQC质控到STAR比对的完整实战流程与避坑指南。详细解读了FastQC/MultiQC报告的关键指标,并重点阐述了STAR比对工具的核心参数设置、索引构建及性能优化策略,旨在帮助用户获得准确可靠的比对结果,为下游基因表达分析奠定坚实基础。 阅读详情

相关推荐

ORACLE 12C RAC 启动报错,错误代码 ORA-27300,ORA-27301,ORA-27302

非一体机,12.2 无任何补丁,2套X86服务器,1节点集群异常(数据库正常,还有会话),2节点正常工作,负载不高,硬件、空间均未检查到异常,多路径存在掉线的情况,但通过Mulitpath -ll 看又是正常的,2根私有网络,其中一根不同,sysctl中配置的稀疏模式。5、再次加成crs alert ohas等集群日志,以及根据现象和错误再次到后台sr中查找可用信息,发现有一个类似问题,12.2 RAC 无任何补丁,报同样错误,解决方案为重启两套服务器。查询MOS文档以及后台文档,排除上面指出的问题。

weixin_42344665的博客 1465

【JAVA-IOC(控制反转)】

5.1 IOC本质是个容器,本质上是对象工厂,通过读取配置文件,再通过它用反射来完成5.2 Spring提供的IOC容器的俩种实现方式(俩个接口):IOC容器基本实现方式,Spring内部使用接口,一般不提供开发人员使用。特点:加载配置文件,不会去创建对象。在获取或使用对象时才创建对象。:可以理解成BeanFactory子接口,比BeanFactory更加强大。面向开发人员。特点:加载配置文件,就会去创建对象。一般使用第二种。定义一个接口创建一个实现了接口的类@Override。

ZERO_HOPE的博客 2385

【论文精读】Formal Mathematical Reasoning: A New Frontier in AI

注:本文根据师兄汇报内容总结。

m0_60634555的博客 1189

【Java 初级】Spring核心之控制反转(IOC)

Spring Bean是Spring框架中的一个核心概念,它是一个由Spring容器管理的对象。在Spring中,Bean是指任何一个由Spring容器所管理的对象,可以是Java类的实例、数据源、事务管理器等等。 Spring Bean的创建、初始化、销毁等生命周期都由Spring容器控制,这样可以将应用程序的对象解耦合,提高模块化和可重用性。Spring Bean可以通过注解、XML配置文件等方式进行声明和配置,Spring容器会根据配置信息创建对应的Bean对象并将其注入到需要使用的地方。

激流丶的博客 1498

SAP SM30数据维护实战:条件筛选与动态校验的实现技巧

本文详细介绍了SAP SM30数据维护的实战技巧,重点讲解如何通过条件筛选实现精准数据查取,以及利用表维护生成器事件实现动态数据检查与校验。文章提供了从基础视图创建到高级事件编程的完整流程,包括调用函数VIEW_MAINTENANCE_CALL传递筛选条件,以及在NEW_DATA和CHANGE_SAVE事件中编写业务规则校验逻辑,帮助开发者提升SM30的管控能力与数据质量。

q9w8e7r6t5的博客 522

知识图谱本体建模工具Protege使用教程

1.下载 先去官网下载:protégé 直接下最新版,点击会有注册页面,只填必填项的name和project description即可。 下载后解压即可使用。 2、安装可视化工具Graphviz 去官网:Download | Graphviz下载。下一个最新版的zip就行。 我解压在了Protege文件夹下,然后在 Preference下指定目录。 指定一下你解压完的Graphviz下的dot.exe,确定。 PS:如果这样报错就尝试在环境变量的系统变量的...

子麒的博客 2万+

注解和依赖注入框架

Hero注解只有成员变量,没有方法。int age();上面的代码定义了两个成员变量,这两个成员变量以方法的形式来定义。@Hero(name = "萧峰", age = 31)也可以在定义注解的成员变量时,使用 default 关键字为其指定默认值,String name() default "段誉";@Hero可以用 @Retention 来设定注解的保留策略,这 3 个策略的生命周期长度为 SOURCE < CLASS < RUNTIME。

xingyu19911016的博客 724

最新Anaconda3的安装配置及使用教程(详细过程)

最新Anaconda3安装使用Anaconda下载方式一:官网下载方式二:清华镜像下载(推荐)Anaconda安装 Anaconda是一个开源的Python发行版本,其包含了conda、Python等180多个科学包及其依赖项 Anaconda + Jupyter 基本上已经是大部分机器学习/数据分析等开发者标配的开发环境, 不多介绍,直接进去正题: Anaconda下载 方式一:官网下载 下载地址传送门: 官网首页:https://www.anaconda.com/ 官网下载页:https://www

HowieXue 薛永浩的博客 34万+

java代码动态注入与class文件热加载实现

一、java代码动态注入 在本文中,我们将研究如何将Java代码动态加载到正在运行的jvm中。 该代码可能是全新的,或者我们可能想更改程序中某些现有代码的功能。 (在开始之前,您可能想知道为什么到底有人会这样做。显而易见的示例是规则引擎之类的东西。规则引擎希望为用户提供添加或更改规则的能力,而不必重新启动规则。您可以通过将DSL脚本作为规则注入规则库来执行此操作,这种方法的真正问题在于,必须对DSL脚本进行解释,使其运行起来极其缓慢。然后可以像程序中的任何其他代码一样编译和运行该程序,效率将提高几个数量级。

qq_21223653的博客 6442

使用Python爬虫抓取旅游景点评价数据并进行热度可视化

景点热度通常由景点的评分、评论数以及游客的热情度来决定。高热度的景点通常意味着更高的游客评分和更多的游客评论。热度不仅反映了景点的受欢迎程度,还可以揭示某些景点的潜力和存在的问题。评分:游客对景点的综合评分,通常是0到5分。评论数:景点的评论数量,反映了游客对景点的关注程度。热度变化:在一定时间内,景点的评价和评论数量变化,能够反映景点的热度波动。通过使用Python爬虫技术抓取旅游景点的评价和评论数据,我们能够深入分析景点的热度,并通过数据可视化工具将这些信息展示给用户。

2201_76125261的博客 1282

UNet改进(24):注意力机制-从基础原理到高级融合策略

本文系统探讨了如何通过引入各类注意力机制增强UNet在医学图像分割中的性能。文章分为基础篇、进阶篇和高级篇三个层级:基础篇介绍了时序注意力、可变形注意力、分层注意力等8种基础机制;进阶篇提出了5种混合注意力设计;高级篇则探讨了全局+局部+多尺度等复杂组合机制。实验表明,这些注意力模块在心脏MRI、肺部感染等任务中能提升2-15%的分割精度。文章还提供了硬件适配建议和完整实现代码,为研究者提供了全面的技术参考。未来方向包括NAS优化、量子注意力等前沿探索,为UNet在医疗影像等领域的应用革新提供了理论指导。

2501_91516851的博客 765

Java语言控制反转是什么?有什么好处?

Java语言控制反转是什么?有什么好处?

Fover_Night的博客 981

SAP-ABAP:SAP创建CDS视图(SQL语句创建)实例详解

通过Eclipse和ADT创建CDS视图是SAP开发中的一项重要技能。CDS视图不仅简化了数据建模,还提供了高性能和灵活性。掌握CDS视图的开发和使用,可以帮助你更好地支持SAP S/4HANA和Fiori应用的开发。

baidu_35680696的博客 1825

java200行代码程序大吗_200行Java代码如何实现依赖注入框架详解

200行Java代码如何实现依赖注入框架详解发布时间:2020-10-02 20:39:24来源:脚本之家阅读:79作者:老钱依赖注入介绍先回顾下依赖注入的概念:我们常提起的依赖注入(Dependency Injection)和控制反转(Inversion of Control)是同一个概念。具体含义是:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协...

weixin_39690963的博客 178

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

java框架注入_200行Java代码如何实现依赖注入框架详解

依赖注入介绍先回顾下依赖注入的概念:我们常提起的依赖注入(Dependency Injection)和控制反转(Inversion of Control)是同一个概念。具体含义是:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在 传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在Spring里,创建被调用者的工作不再由调用者来完成,因...

weixin_39946266的博客 120

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

java 代码注入_200行Java代码实现依赖注入框架

依赖注入框架并不神秘,其实它是非常简单的东西。不要去看spring的依赖注入源码,因为你只要一去看就意味着你再也写不敢下手自己撸了,它的功能因为过于强大,所以设计也过于复杂,普通程序员一眼看去只能望洋兴叹。我也并没有去细致阅读spring源码。即便如此也只用了半天的时间便自己撸了一个基本满足标准依赖注入规范「JSR-330」的小框架iockids。这个小框架只有一个主类Injector,大约200...

weixin_35734209的博客 309

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

java 脚本注入_200行Java代码如何实现依赖注入框架详解

依赖注入介绍先回顾下依赖注入的概念:我们常提起的依赖注入(Dependency Injection)和控制反转(Inversion of Control)是同一个概念。具体含义是:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在 传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在Spring里,创建被调用者的工作不再由调用者来完成,因...

weixin_28823431的博客 246

Java 依赖注入框架全景指南

无论选择哪种框架,依赖注入的核心价值在于通过解耦依赖提升代码质量可维护性:依赖关系集中管理,修改依赖只需调整配置,无需修改业务代码。可扩展性:通过替换实现类(如从 MySQL 切换到 PostgreSQL),轻松扩展功能,符合 "开闭原则"。可测试性:通过注入 Mock 对象,实现组件的隔离测试,保障代码质量。在 Java 开发中,合理使用依赖注入框架,可有效解决传统依赖管理的痛点,为项目的长期演进奠定坚实基础。根据项目规模、性能需求和团队技术栈选择合适的框架,才能最大化依赖注入的价值。

m0_57836225的博客 755

依赖注入底层反射原理_Typescript之 200行实现依赖注入

依赖注入概述使用过Angular的读者一定对依赖注入不陌生。从Angular.js到Angular,依赖注入都是绕不开的话题。在其他语言或者框架下,依赖注入也广泛应用,比如JAVA/SCALA使用Guice,C#使用Ninject。什么是依赖注入?简而言之,就是当前某个逻辑模块获取它依赖的服务且不控制服务的生命周期(创建销毁等)。例如服务a依赖服务b,但是a并不需要创建服务b就可以获得服务b的实例...

weixin_28913137的博客 294

typescript get方法_Typescript之 200行实现依赖注入

依赖注入概述使用过Angular的读者一定对依赖注入不陌生。从Angular.js到Angular,依赖注入都是绕不开的话题。在其他语言或者框架下,依赖注入也广泛应用,比如JAVA/SCALA使用Guice,C#使用Ninject。什么是依赖注入?简而言之,就是当前某个逻辑模块获取它依赖的服务且不控制服务的生命周期(创建销毁等)。例如服务a依赖服务b,但是a并不需要创建服务b就可以获得服务b的实例...

weixin_39606177的博客 335

如何用200行代码实现Drools核心逻辑?Java轻量级规则引擎实战

掌握Java实现轻量级规则引擎(Drools 简化版)核心逻辑,200行代码快速构建规则匹配与执行机制。适用于业务解耦、动态策略场景,基于责任链+反射实现高效规则调度,低依赖易扩展,值得收藏。

CompiWander的博客 598

300行代码手写Spring核心--Spring初探

300行代码手写Spring核心--Spring初探 目标:我们通过查看源码的方式一步步尝试完成springIOC容器的初始化 并完成dispatchServlet的功能 1.首先创建一个我们自己的Servlet并继承HttpServlet并重写init方法 public class EVServlet extends HttpServlet { @Override public...

qq_38762479的博客 1165

还不懂spring IOC核心原理?200行代码带你手撸一个

Spring做为Java企业级应用的开源开发框架,早已成为Java后端开发事实上的行业标准,无数的公司选择Spring作为基础的开发框架。使用Spring框架的人一定都听过Spring的I...

架构师小秘圈 289

打造Android依赖注入框架,改变你的代码方式(上)

先来介绍下本次列车本次列车来自地球,时速200km/s,即将开往火星,请要上车的朋友速速上车.. 先介绍一个非常重要的东西:注解 注解(Annotation),我们在写代码的过程中,相信已经见不少了 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(save

Eicky 24万+

用一个类(300行)手写Spring框架

300行代码手写Spring(包含IOC、DI、MVC等核心部分),提炼Spring精华设计思想

不思量 441
上一篇: 核心技术靠化缘是要不来的——自己动手写ORM框架
下一篇: 编程的智慧
码洞
博客等级 码龄10年 41粉丝 137原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值