能跑HelloWorld程序之后,就要开始一点点深入去探寻Guice的奥秘了,未知的领域总是充满了诱惑力,新的东西总是能给人带来无限的激情,这就是为什么人们都喜欢去旅游,去探险的原因之一吧;既然开启了Guice的瓶盖,就好好去尝尝Guice的味道。
1、隐式绑定
之前的Helloworld程序是显式的绑定接口的实现,类似这样的形式: bind(TestService.class).to(TestServiceAnotherImpl.class);Guice提供了一种隐式绑定的方式,给接口默认的实现。如:
TestServiceImpl.java
public class TestServiceImpl implements TestService {
@Override
public void info() {
System.out.println("Say,info");
}
}
TestService.java
@ImplementedBy(TestServiceImpl.class)
public interface TestService {
void info();
}
TestServiceModule.java
public class TestServiceModule extends AbstractModule{
@Override
protected void configure() {
bind(TestService.class);
}
}
TestServiceMain.java
public class TestServiceMain {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TestServiceModule());
TestService testService = injector.getInstance(TestService.class);
testService.info();
}
}
输出:Say,info
这个时候Module里面就无需显式的绑定实现类 ,自动的绑定默认实现。
但是如果接口又显式定义了另外一个实现呢,那么哪个优先级高一点?
TestServiceAnotherImpl.java
public class TestServiceAnotherImpl implements TestService {
@Override
public void info() {
System.out.println("Say: another!");
}
}
TestServiceAnotherModule.java
public class TestServiceAnotherModule extends AbstractModule{
@Override
protected void configure() {
bind(TestService.class).to(TestServiceAnotherImpl.class);
}
}
将这个Module载入Injector,跑起来之后,输出结果:Say:another! 说明Module配置总是高于注解配置。
2、对象作用域(Scope)
Guice的默认行为是每次请求对象或者注入的时候都会创建一个新的实例对象。作用域(Scope)能让你自定义对象的生命周期。代码说明一切:
TestSingletonModule.java
public class TestSingletonModule extends AbstractModule {
@Override
protected void configure() {
bind(TestSingleton.class).to(TestSingletonImpl.class);
}
}
TestSingletonMain.java
public class TestSingletonMain {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TestSingletonModule());
TestSingleton testSingleton = injector.getInstance(TestSingleton.class);
System.out.println(testSingleton);
TestSingleton testSingleton2 = injector.getInstance(TestSingleton.class);
System.out.println(testSingleton2);
}
}
输出:
com.lemon.guice.example2.TestSingletonImpl@535b58
com.lemon.guice.example2.TestSingletonImpl@922804
说明是两个不同的对象
当修改一下上述代码,设置成为单例的:
TestSingletonModule.java
public class TestSingletonModule extends AbstractModule {
@Override
protected void configure() {
bind(TestSingleton.class).to(TestSingletonImpl.class).in(Scopes.SINGLETON);
}
}
上述的TestSingletonMain输出为:
com.lemon.guice.example2.TestSingletonImpl@535b58
com.lemon.guice.example2.TestSingletonImpl@535b58
确实是单例的。
说到单例的,大家肯定会想到懒汉式的和恶汉式的单例实现,这个取决于之前所说的Stage的设置。
默认的Stage.DEVELOPMENT是 懒汉式的,Stage.PRODUCTION是饿汉式的,但是在DEVELOPMENT可以使用asEagerSingleton()方法:
bind(TestSingleton.class).to(TestSingletonImpl.class).asEagerSingleton();
显式的使用饿汉式加载方式的。
对于Servlet,作用域还有request和session的区别,这个之后再讲。
3、对象生产者(Provider)
在向Guice申请对象的时候,仅仅是找到构造器然后执行它。但是有些时候你并不想这样:
- 延迟加载
- 需要类的多个对象
- 想提供实例生成的自定义实现。
- 在创建对象的时候需要做其他的一些方式的校验, 在某些情况下需要抛出异常。
- 想使用第三方包,但是不能直接添加@Inject注解。
- 需要复用代码的时候。
首先看看生产者接口:位于Guice jar包内部,继承的是JSR-330 的规范接口
public interface Provider<T> extends javax.inject.Provider<T> {
/**
* Provides an instance of {@code T}. Must never return {@code null}.
*
* @throws OutOfScopeException when an attempt is made to access a scoped object while the scope
* in question is not currently active
* @throws ProvisionException if an instance cannot be provided. Such exceptions include messages
* and throwables to describe why provision failed.
*/
T get();
}
要想使用Provider,首先是实现其接口:
这里沿用 Google Guice这本书的例子:
Gum.java
public class Gum { }
GumProvider.java
public class GumProvider implements Provider<Gum> {
@Override
public Gum get() {
return new Gum();
}
}
GumballMachine.java(对象生产工具,类似工厂)
public class GumballMachine {
@Inject
private Provider<Gum> gumProvider;
public Gum dispense(){
return gumProvider.get();
}
}
配置的Module
GumModule.java
public class GumModule extends AbstractModule {
@Override
protected void configure() {
bind(Gum.class).toProvider(GumProvider.class);
}
}
然后测试:
GumballExample.java
public class GumballExample {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new GumModule());
GumballMachine m = injector.getInstance(GumballMachine.class);
System.out.println(m.dispense());
System.out.println(m.dispense());
}
}
输出:
com.lemon.guice.example3.Gum@5e3974
com.lemon.guice.example3.Gum@df503
这样的话在GumProvider和GumballMachine里面就能玩各种花样,在多线程环境下,这样可能存在线程安全问题,这点要注意。
像ImplementedBy注解一样,可以提供@ProvidedBy注解来省去Module的toProvider的配置
@ProvidedBy(GumProvider.class)
public class Gum {
}
4、@Named注解
这里先抛出一个问题,如果一个接口有多个实现,在不同的条件下使用不同的实现,
如果在Spring中,配置会比较简单,直接在配置文件里面指定实现就Ok,在Guice该肿么解决?
有了@Named注解,就会变得比较方便了。
例子:
Actor.java
public interface Actor {
void iCanDo();
}
LiXiaolong.java
public class LiXiaolong implements Actor {
@Override
public void iCanDo() {
System.out.println("I can do everything!");
}
}
ZhouXingXing.java
public class ZhouXingXing implements Actor {
@Override
public void iCanDo() {
System.out.println("I'm just an actor!");
}
}
ActionMovie.java
public class ActionMovie {
@Inject @Named("lixiaolong")
private Actor lixiaolong;
@Inject @Named("zhouxingchi")
private Actor zhouxingchi;
public void show(){
lixiaolong.iCanDo();
zhouxingchi.iCanDo();
}
}
ActionModule.java
public class ActionModule extends AbstractModule {
@Override
protected void configure() {
bind(Actor.class).annotatedWith(Names.named("lixiaolong")).to(LiXiaolong.class);
bind(Actor.class).annotatedWith(Names.named("zhouxingchi")).to(ZhouXingXing.class);
}
}
ActionExample.java
public class ActionExample {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new ActionModule());
ActionMovie actionMovie = injector.getInstance(ActionMovie.class);
actionMovie.show();
}
}
输出的当然是你想要的东西
相关推荐
python入门-30.寻找列表中只出现一次的数字——寻找单身狗.py
linux优化笔记,配套视频:https://www.bilibili.com/list/474327672?sid=4496133&spm_id_from=333.999.0.0&desc=1
知识付费系统-直播+讲师入驻+课程售卖+商城系统-v2.1.9版本搭建以及资源分享下载,CRMEB知识付费分销与直播营销系统是由西安众邦科技自主开发的一款在线教育平台,该系统不仅拥有独立的知识产权,还采用了先进的ThinkPhp5.0框架和Vue前端技术栈,集成了在线直播教学及课程分销等多种功能,旨在为用户提供全方位的学习体验,默认解压密码youyacaocom
美妆神域-JAVA-基于springBoot美妆神域设计与实现
原生js制作Google粘土logo动画涂鸦代码.zip
golin 扫描工具使用, 检查系统漏洞、web程序漏洞
原生态纯js图片网格鼠标悬停放大显示特效代码下载.zip
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 替换数据可以直接使用,注释清楚,适合新手
去水印web端独立版web
原生js制作左侧浮动可折叠在线客服代码.zip
Chrome 谷歌浏览器下载
全新完整版H5商城系统源码 自己花钱买的,亲测可用,需要自行下载 H5商城系统设置是实现商城基本功能的核心部分,涵盖了从网站配置、短信和支付配置,到商品、工单、订单、分站和提现管理等多个模块的设置。以下是详细的设置指南,帮助您快速上手并高效管理商城系统。 测试环境:Nginx+PHP7.0+MySQL5.6 1. 网站配置 设置商城名称、LOGO、标题、联系方式和SEO关键词等,确保商城专业和易于搜索。 2. 短信配置 配置短信接口和模板,用于发送订单通知、验证码等,提升用户体验。 3. 支付接口配置 配置微信、支付宝等支付接口,填写API密钥和回调地址,确保支付流畅。 4. 商品分类管理 对商品进行分类和排序,设置分类名称和图标,便于用户查找商品。 5. 商品管理 添加和管理商品信息、规格、图片等,确保商品信息准确丰富。 6. 工单管理 查看和回复用户工单,记录售后问题,提升用户服务质量。 7. 订单管理 查看订单详情,更新订单状态,支持批量导出,方便订单跟踪。 8. 分站管理 创建不同区域分站,设置权限,统一管理各区域市场。 9. 提现管理
apk安装包
原生js选项卡插件自定义图片滑动选项卡切换.zip
宗教信息佛教佛寺寺庙庵堂相关数据集提供了全国各个地区省市县各个佛教寺庙的详细信息。这些数据不仅包括寺庙的名称和负责人姓名,还涵盖了所属省份、地级市、区县、具体地址、建立日期以及支派类别等关键信息。该数据集整理了超过3万条样本,为研究中国佛教寺庙的分布、历史和文化提供了丰富的第一手资料。这些信息有助于了解佛教在中国的传播和发展,以及寺庙在社会和文化中的作用。数据的整理和提供,对于宗教学、社会学、历史学和文化研究等领域的学者来说,是一个宝贵的资源。
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 替换数据可以直接使用,注释清楚,适合新手
简单的 Python 版本管理pyenvpyenv 可让您轻松在多个 Python 版本之间切换。它简单、不引人注目,并遵循 UNIX 传统,即使用单一用途的工具来做好一件事。该项目由rbenv和 ruby-build分叉而来,并针对 Python 进行了修改。pyenv 的作用是什么......允许您根据每个用户更改全局 Python 版本。为每个项目的 Python 版本提供支持。允许您使用环境变量覆盖 Python 版本。一次搜索多个 Python 版本的命令。这可能有助于使用tox跨 Python 版本进行测试。与 pythonbrew 和 pythonz 相比,pyenv没有……依赖于Python本身。pyenv由纯shell脚本制作。不存在Python的引导问题。需要加载到你的 shell 中。相反,pyenv 的 shim 方法通过向你的 中添加目录来工作PATH。管理虚拟环境。当然,你可以自己创建虚拟环境 ,或者使用pyenv-virtualenv 来自动化该过程。目录安装获取 PyenvLinux/UNIX自动安装程序基本
Notepad-v2.20工具,是替代Notepad++的首选工具
原生js随机图片拖拽排序代码.zip
更快、更好、更稳定的Redis桌面(GUI)管理客户端,兼容Windows、Mac、Linux,性能出众,轻松加载海量键值