当前位置: 首页 > 后端技术 > Java

【曹公杂谈】MavenIOC容器下半篇:GoogleGuice

时间:2023-04-02 01:20:48 Java

前言底层容器是Guice。Guice也被广泛使用,活跃在以下wheels(仅部分):GoogleinternalscalatestTestNGCaffeineCacheSpringSecurityConfigulasticsearchjenkins其中很多wheel都是Guice直接使用的,因为没有历史包袱;但是Maven不一样,maven之前使用了自己的IOCwheel,有自己独特的定义组件的方式(比如Spring是通过@Component注解来定义的);但是Guice作为一个独立的IOC框架,肯定不能识别Maven中的组件。所以,中间一定要有兼容性。Maven组件仍然以与PlexusIOC容器相同的方式定义,但他们开发了一个中间层来解析这些组件并将它们存储在Guice容器中。这里说的是解析组件后,存放到Guice容器中。这不是特别准确。更准确的说是放在一个基于Guice封装的容器中。这个容器叫做:sisu,由eclipse这个开源项目维护(https://www.eclipse.org/sisu/)。可能你一头雾水,就一个破IOC,技术性如何,还是有层次感的。.让我们暂时忽略它。本期先说说Guice,然后大家就明白为什么要封装Sisu了。总结一下,依赖路径为:底层是googleGuice--》sisu(eclipse)--》sisu-plexus兼容层--《plexus--》maven。好,开始写。什么是吉斯?根据wiki的介绍,Guice是一个依赖注入框架,由Google开源。主要特点是:支持以java注解的形式配置组件和依赖。最早的版本应该是2007年的,我也找到了当年的报道https://developers.googleblog...,还是2007年,2004年发布了支持注解的JDK1.5。同时,Spring的早期版本主要是基于xml的配置,Guice当时支持全注解配置,在当时看来是非常前沿的。接下来,让我们仔细看看Guice的用法。在开始讲核心概念之前,先说说我对IOC框架的理解。很多时候可以简单的说IOC容器就是一张地图,一个放东西的地方,就像中药房,每一格都会放一种药材,每一格上都有一个标签来说明里面。这是什么药。既然是放东西的地方,核心就是两部分,怎么放,什么时候放,以后可能要考虑怎么找。例如,如果你打算只支持基于item类型的搜索,那么你就要考虑:如果这个类型的item有多个怎么办?如何区分这多个项目?如果你打算解决这个问题,那么你可能会想:那我放的时候,我会给这些item起个名字,以免区分多个相同类型的item。甚至,你可能会考虑item的权限隔离,比如给item加一个depositor字段,以后拿到的时候只能:拿自己的,不能拿别人的。反正最后要看需求。一般来说,像我们的spring,按类型来说差不多。当一个类型有多个实现时,根据名称来区分就可以了。至于Guice,我这里重点讲解一下:如何保存。至于抓取,可能分为两种,依赖注入和直接从容器中抓取。但是依赖注入的底层实现也是:如果我发现我依赖的东西不可用,我就去容器里拿。因此,我们只需要关注如何直接从容器中获取东西即可;这里不特别关注依赖注入的问题。在Guice中,概述了保存事物的各种方法。在Guice的文档中,这个词叫做Binding,中文意思是绑定。https://github.com/google/gui...绑定是什么意思,就是我最终可能需要从容器中获取一个ClassA类型的对象。既然要得到,就得先存起来。当我保存的时候,我需要创建一个绑定:ClassA-->获取Class类型对象的方式。其实很简单。下面就按照我的代码示例,一起来看看吧。以下所有代码都在这里:https://gitee.com/ckl111/mave...1.linkedbinding-绑定接口到实现类首先来一个接口和实现:publicinterfaceHelloInterface{voidhello();}publicclassHelloInterfaceImpl实现HelloInterface{@Overridepublicvoidhello(){System.out.println("helloworld");再来看看,怎么放到容器里,从容器里拿出来的简单方法:大家看我的代码截图,放东西的时候,就是指定这个接口和对应的实现班级。取东西的时候,按照界面去取就可以了。2.BindingAnnotations当一个类型有多个实现类时,绑定方法接口和多个实现类:世界”);}}classHelloInterfaceImpl2实现HelloInterface{@Overridepublicvoidhello(){System.out.println("helloworld");}}如果还是按照之前的方法,框架就晕了,有多个实现类,给你哪个?请再次说明,好吗?Guice有一个名为Named的注释,可以在各个地方添加。注解本身支持设置名称。这里的意思就是你的接口有多个实现,那么就这样吧:接口+注解是唯一的key,这样就ok了。所以,现在就变成了这样:接口+注解1--》实现类1;接口+注解2--》实现类2。那怎么获取呢?简单,怎么保存,怎么退出,保存的时候用接口+注解,退出的时候也一样。既然可以使用官方的Named注解,也可以使用自己的注解。3、如果InstanceBindings接口直接绑定同类型的单例对象,需要绑定多个实例,处理方法同上。4.绑定到工厂方法:授人以鱼不如授人以渔。前面的方法很简单。这次不同了。我只会告诉你如何获得这个东西。5.不需要接口。在直接绑定一个实现类之前,都是基于一个接口类来获取接口对应的实现。这次不一样,直接是一个实现类。publicclassUtilService{}就像上面的情况,必须直接调用这个类的构造函数。6.接口绑定一个构造函数:ToConstructorBindings哎,越来越无语了,Guice的花样真多。7.内置的可以不用绑定的主要有:Logger,Injector本身(相当于帮你注入容器本身)8.我们可以不用绑定直接用spring吗,现在不用了做这个捆绑和捆绑。让我们看看Guice的支持是如何不受约束的。可以这样:@ImplementedBy(TestInterfaceImpl.class)interfaceTestInterface{}这相当于,你要自己指定,谁是你的实现类,或者你的provider是谁。但是官方不推荐使用这种隐式绑定。我不知道为什么,但还有一个选项可以专门禁用隐式绑定。9.一次性获取一个接口的多个实现类的场景,就是一次性获取多个实现类,给你放到一个集合中。这个场景我没有写任何代码,大家可以自己看文档,很简单。10.注入的方法关于如何手动从容器中提取我已经讲了很多了。当然,如果你想自动注入,它也支持:构造函数注入,字段注入等方法。下面是构造函数注入:其他支持的特性其他的,比如循环依赖,aop一般都支持,但是这个容器用在Android端,会出现问题,因为aop好像不支持,所以特意提供为Android端一个去掉aop的版本。循环依赖之类的,具体实现没看过多少。另外,guice默认会生成多个实例(类比spring的prototype,不是singleton),但是它也支持singleton,我在前面的代码例子中都有。从最大槽可以看出Guice是非常轻量级的,也就是说它的功能没有Spring那么完备,所以我们还是需要显式配置每个接口以及如何获取它的对象(方法也是多种多样的,哈哈哈,如如前所示)。当然,配置好之后,当我们拿到一个对象的时候,就会帮我们完成自动注入。但是,它不支持类路径扫描。比如你给一个包名,它会自动扫描这个包下的组件。反正官方不支持。据说有第三方插件,我还没试过。综上所述,在各种轮子里,Guice确实足以管理自己代码之间的相互依赖,但是在业务代码中使用它还是有点累。因为,主要原因是:各种依赖都需要自己配置,但是只在一个地方配置。不像spring,约定通过接口找对象的时候,默认是找实现类,然后反射生成对象。在这方面,确实是:约定优于配置,就像为什么Maven打败了ant一样,也是这个道理。还有一个问题就是不支持spring的component-scan。基于这两个问题,必须有一个方法。因此,Maven也足够聪明。不是直接基于Guice,而是选择基于Guice包的Sisu,Sisu可以解决我们的问题,支持类路径扫描。某种类型的。让我们看看sisu是如何介绍自己的:它只是比Guice看起来不错而Spring已经拥有的功能多了一些。以后一定会再介绍sisu的。再见,上面。本文由博客多发平台OpenWrite发布!