首页 > 其他分享 >Google Guice 入门教程01 - 依赖注入

Google Guice 入门教程01 - 依赖注入

时间:2023-07-04 20:31:33浏览次数:52  
标签:HelloWorldImpl 01 Guice 入门教程 hw HelloWorld public inj class


1. 依赖注入

1.1 类依赖注入

所谓的绑定就是将一个接口绑定到具体的类中,这样客户端不用关心具体的实现,而只需要获取相应的接口完成其服务即可。

HelloWorld.java

 

1     public interface HelloWorld {
2 
3         String sayHello();
4     }
5


然后是具体的实现,HelloWorldImpl.java

 


1     public class HelloWorldImpl implements HelloWorld {
2 
3         @Override
4         public String sayHello() {
5             return "Hello, world!";
6         }
7     }
8


写一个测试例子看看,HelleWorldTest.java

 

1     public class HelleWorldTest {
 2 
 3         @Test
 4         public void testSayHello() {
 5           Injector inj=  Guice.createInjector(new Module() {
 6                 @Override
 7                 public void configure(Binder binder) {
 8                     binder.bind(HelloWorld.class).to(HelloWorldImpl.class);
 9                 }
10             });
11           HelloWorld hw = inj.getInstance(HelloWorld.class);
12           Assert.assertEquals(hw.sayHello(), "Hello, world!");
13         }
14     }
15



这个例子非常简单,通俗的将就是将一个HelloWorldImpl的实例与HelloWorld关联起来,当想Guice获取一个HelloWorld实例的时候,Guice就返回一个HelloWorldImpl的实例,然后我们就可以调用HelloWorld服务的方法了。

问题(1)HelloWorld是单例的么?测试下。

 


1 HelloWorld hw = inj.getInstance(HelloWorld.class); 
2 Assert.assertEquals(hw.sayHello(), "Hello, world!");
3 HelloWorld hw2 = inj.getInstance(HelloWorld.class);
4 System.out.println(hw.hashCode()+"->"+hw2.hashCode());
5 Assert.assertEquals(hw.hashCode(), hw2.hashCode());


解答(1)测试结果告诉我们,HelloWorld不是单例的,每次都会返回一个新的实例。

问题(2)HelloWorld的实例是HelloWorldImpl么?可以强制转型么?

HelloWorld hw = inj.getInstance(HelloWorld.class);
System.out.println(hw.getClass().getName());

 

解答(2),结果输出cn.imxylz.study.guice.helloworld.HelloWorldImpl,看来确实只是返回了一个正常的实例,并没有做过多的转换和代理。

问题(3),如果绑定多个实现到同一个接口上会出现什么情况?

 


1 public class HelloWorldImplAgain implements HelloWorld {
2     @Override
3     public String sayHello() {
4         return "Hello world again.";
5     }
6 }

 



binder.bind(HelloWorld.class).to(HelloWorldImpl.class);
binder.bind(HelloWorld.class).to(HelloWorldImplAgain.class);



解答(3),很不幸,Guice目前看起来不允许多个实例绑定到同一个接口上了。

com.google.inject.CreationException: Guice creation errors:

1) A binding to cn.imxylz.study.guice.helloworld.HelloWorld was already configured at cn.imxylz.study.guice.helloworld.HelleWorldTest$1.configure(HelleWorldTest.java:28). 
  at cn.imxylz.study.guice.helloworld.HelleWorldTest$1.configure(HelleWorldTest.java:29)

问题(4),可以绑定一个实现类到实现类么?

1 Injector inj=  Guice.createInjector(new Module() {
2       @Override
3       public void configure(Binder binder) {
4           binder.bind(HelloWorldImpl.class).to(HelloWorldImpl.class);
5       }
6   });
7 HelloWorld hw = inj.getInstance(HelloWorldImpl.class);
8 System.out.println(hw.sayHello());

 

非常不幸,不可以自己绑定到自己。

1) Binding points to itself. 
  at cn.imxylz.study.guice.helloworld.HelleWorldTest$1.configure(HelleWorldTest.java:28)

我们来看看bind的语法。

<T> AnnotatedBindingBuilder<T> bind(Class<T> type);
 
 
 
 
 
 
ScopedBindingBuilder to(Class<? extends T> implementation);


也就是说只能绑定一个类的子类到其本身。改造下,改用子类替代。

 


1     public class HelloWorldSubImpl extends HelloWorldImpl {
2 
3         @Override
4         public String sayHello() {
5             return "@HelloWorldSubImpl";
6         }
7     }
8

 



1 Injector inj=  Guice.createInjector(new Module() {
2             @Override
3             public void configure(Binder binder) {
4                 binder.bind(HelloWorldImpl.class).to(HelloWorldSubImpl.class);
5             }
6         });
7       HelloWorldImpl hw = inj.getInstance(HelloWorldImpl.class);
8       System.out.println(hw.sayHello());


太好了,支持子类绑定,这样即使我们将一个实现类发布出去了(尽管不推荐这么做),我们在后期仍然有办法替换实现类。

使用bind有一个好处,由于JAVA 5以上的泛型在编译器就确定了,所以可以帮我们检测出绑定错误的问题,而这个在配置文件中是无法检测出来的。

这样看起来Module像是一个Map,根据一个Key获取其Value,非常简单的逻辑。

问题(5),可以绑定到我们自己构造出来的实例么?

解答(5)当然可以!看下面的例子。

 


1 Injector inj=  Guice.createInjector(new Module() {
2             @Override
3             public void configure(Binder binder) {
4                 binder.bind(HelloWorld.class).toInstance(new HelloWorldImpl());
5             }
6         });
7       HelloWorld hw = inj.getInstance(HelloWorld.class);
8       System.out.println(hw.sayHello());

问题(6),我不想自己提供逻辑来构造一个对象可以么?

解答(6),可以Guice提供了一个方式(Provider<T>),允许自己提供构造对象的方式。

 


1 Injector inj=  Guice.createInjector(new Module() {
 2       @Override
 3       public void configure(Binder binder) {
 4           binder.bind(HelloWorld.class).toProvider(new Provider<HelloWorld>() {
 5               @Override
 6               public HelloWorld get() {
 7                   return new HelloWorldImpl();
 8               }
 9           });
10       }
11   });
12 HelloWorld hw = inj.getInstance(HelloWorld.class);
13 System.out.println(hw.sayHello());

问题(7),实现类可以不经过绑定就获取么?比如我想获取HelloWorldImpl的实例而不通过Module绑定么?

解答(7),可以,实际上Guice能够自动寻找实现类。

 

Injector inj=  Guice.createInjector();
HelloWorld hw = inj.getInstance(HelloWorldImpl.class);
System.out.println(hw.sayHello());


问题(8),可以使用注解方式完成注入么?不想手动关联实现类。

解答(8),好,Guice提供了注解的方式完成关联。我们需要在接口上指明此接口被哪个实现类关联了。

1     @ImplementedBy(HelloWorldImpl.class)
2     public interface HelloWorld {
3 
4         String sayHello();
5     }
6



Injector inj=  Guice.createInjector();
HelloWorld hw = inj.getInstance(HelloWorld.class);
System.out.println(hw.sayHello());



事实上对于一个已经被注解的接口我们仍然可以使用Module来关联,这样获取的实例将是Module关联的实例,而不是@ImplementedBy注解关联的实例。这样仍然遵循一个原则,手动优于自动。

问题(9)再回头看问题(1)怎么绑定一个单例?

 1     Injector inj = Guice.createInjector(new Module() {
 2 
 3         @Override
 4         public void configure(Binder binder) {
 5             binder.bind(HelloWorld.class).to(HelloWorldImplAgain.class).in(Scopes.SINGLETON);
 6         }
 7     });
 8     HelloWorld hw = inj.getInstance(HelloWorld.class);
 9     HelloWorld hw2 = inj.getInstance(HelloWorld.class);
10     System.out.println(hw.hashCode() + "->" + hw2.hashCode());
11

可以看到现在获取的实例已经是单例的,不再每次请求生成一个新的实例。事实上Guice提供两种Scope,com.google.inject.Scopes.SINGLETON和com.google.inject.Scopes.NO_SCOPE,所谓没有scope即是每次生成一个新的实例。

对于自动注入就非常简单了,只需要在实现类加一个Singleton注解即可。

1     @Singleton
2     public class HelloWorldImpl implements HelloWorld {

4         @Override
5         public String sayHello() {
6             return "Hello, world!";
7         }
8     }
9

from internet

标签:HelloWorldImpl,01,Guice,入门教程,hw,HelloWorld,public,inj,class
From: https://blog.51cto.com/u_2650279/6625162

相关文章

  • 01-逻辑分析仪使用
    目录一.环境搭建二.软件配置一.环境搭建安装软件和硬件连接,板子的GND连接逻辑分析仪的GND,待测点连接逻辑分析仪上面的通道.二.软件配置相关选项含义......
  • 2019年中国公有云厂商发展状况白皮书
     前 言     云发展白皮书做了三年的中国公有云厂商收入利润综合排名,到了这次想要继续推出来,在文章快要完成三分之二的时候,突然有了更强烈的想法,就是立足中国公有云厂商收入利润综合排名,直接升级为:2019年中国公有云厂商发展状况白皮书。一方面,让大家可以更全面了解公有云及......
  • 2019年中国公有云厂商收入利润排名
    继续延续了往年的统计方法,即:云计算是一个筐,什么都可往里装。 从公有云到私有云,从私有云到公有云,抑或还采取混合云,企业上云变得十分普遍。行业数字化转型,在很大程度上推动了公有云厂商进入了一个发展的新阶段。从而,也促使2019年中国公有云厂商获得了更好的发展结果。 据阿明(Aming)......
  • Nftables栈溢出漏洞(CVE-2022-1015)复现
    背景介绍NftablesNftables是一个基于内核的包过滤框架,用于Linux操作系统中的网络安全和防火墙功能。nftables的设计目标是提供一种更简单、更灵活和更高效的方式来管理网络数据包的流量。钩子点(HookPoint)钩子点的作用是拦截数据包,然后对数据包进行修改,比较,丢弃和放行等操作......
  • ORA-01122 ORA-01200故障处理---惜分飞
    联系:手机/微信(+8617813235971)QQ(107644445)标题:ORA-01122ORA-01200故障处理作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]由于某种原因客户的数据库启动报ORA-01122ORA-01200错误让客户把system01.dbf文件发给我进行分析,发......
  • Day01-7 类型转换
    由于java是强类型语言,所以要进行有些运算的时候,需要用到类型转换低---------------------------------------------------------------------->高byte,short,char—>int—>long—>float—>double运算中,不同类型的数据先转化为同一类型,然后进行运算//强制转换(类......
  • 2012年中国县级市面积排行(截止到2012年7月31日) (zz.IS2120@BG57IV3)
    2012年中国县级市面积排行(截止到2012年7月31日)//z2013-02-1813:12:[email protected][T146,L2083,R63,V2084]说明:1、以下数据由宜居城市研究室统计整理,统计时间截止到2012年7月31日,与县级市同级的县、旗等不计算入内;2、以下面积均指陆地面积,不包括海域面积,入榜县......
  • 101.final和override关键字
    在C++中,final是一个关键字,用于修饰类的成员变量和成员函数。1.final修饰成员变量:当一个类中的成员变量被声明为final时,它就变成了常量,即它的值不能再被修改。final修饰的成员变量必须在类定义中进行初始化,且只能初始化一次。假设我们有一个名为Person的类,其中包含一个成员变量na......
  • Day01-6 数据类型
    数据类型强类型语言要求变量的使用要符合规定,所有变量都必须先定义后才能使用java数据类型的两大类基本数据类型数值类型整数类型byte占1个字节范围:-128-127shout占2个字节范围:-32768-32767int占4个字节范围:-2147483648-2147483647long占8个字节范围:-9223372036......
  • 第016课 Nand Flash操作原理及裸机程序分析
    第001节_NAND_FLASH操作原理NANDFLASH原理图NANDFLASH是一个存储芯片那么:这样的操作很合理”读地址A的数据,把数据B写到地址A”问1.原理图上NANDFLASH和S3C2440之间只有数据线,怎么传输地址?答1.在DATA0~DATA7上既传输数据,又传输地址当ALE为高电平时传输的是地址,那么在数据......