1、Hello World!
1、定义Service Service.java public interface Service{ public void sayHello(); } 2、定义实现类 ServiceImpl.java public class ServiceImpl implements Service{ @Override public String sayHello() { return "Hello World!"; } } 3、客户端 Client.java public class Client { //@Inject 也可以再这里注入 public Service service; /*这里是在构造函数中注入了 优点是可以再构造函数中完成一些初始化工作 缺点是类的实例化与参数绑定,限制了实例化类的方式 */ @Inject public Client(Service service){ this.service = service; } public void print(){ System.out.println(service.say()); } } 4、测试类 public class Test extends TestCase{ public void testGuice(){ Injector inj = Guice.createInjector(new Module(){ @Override public void configure(Binder binder){ binder.bind(Service.class).to(ServiceImpl.class); } }); Client client = inj.getInstance(Client.class); client.print(); } }
2、单例问题
在测试类中直接拿Service对象比较
Service service = inj.getInstance(Service.class); Service service2 =inj.getInstance(Service.class); Assert.assertEquals(service.hashCode(),service2.hashCode()); //不等,每次都会返回一个新的实例 修改代码Module中的方法 ... binder.bind(Service.class).to(Serviceimpl.class).in(Scopes.SINGLETON); ... //再次测试 Service service = inj.getInstance(Service.class); Service service2 =inj.getInstance(Service.class); Assert.assertEquals(service.hashCode(),service2.hashCode()); //相等,返回是同一个实例 //--------------------我是分割线 ----------------------------- //也可以通过在实现类上添加@Singleton标注来完成, @Singleton public class ServiceImpl implements Service{ ... }
3、返回的是正常的实例,未做转换和代理。
Service service = inj.getInstance(Service.class); System.out.println(service.getClass().getName()); //输出Service,是正常的实例,未做转换和代理。
4、无法绑定多个实现到一个借口
再建一个实现类 public class ServiceImplAgain implements Service{ ... } 然后修改Module类 ... binder.bind(Service.class).to(ServiceImpl.class); binder.bind(Service.class).to(ServiceImplAgain.class); .. //系统报错
5、不可以自己绑定自己,但可以绑定子类到自己,也可以绑定到自己构造出来的实例上。
... binder.bind(ServiceImpl.class).to(ServiceImpl.class); ... //报错 ,不可以自己绑定自己 Binding porins to itserlf //--------------------我是分割线--------------------------- public class ServiceSubImpl extends ServiceImpl{ ... } ... binder.bind(ServiceImpl.class).to(ServiceSubImpl.class); ... /*运行正常,支持子类绑定,这样即使我们将一个实现类发布出去(尽管不推荐这么做),我们再后期仍然有拌饭替换实现类。*/ //--------------------我是分割线--------------------------- ... binder.bind(Service.class).to(new ServiceImpl()); ... //绑定到实例上
5、可以Guice提供一个方式(Provider<T>),允许自己提供构造对象的方式。
//方法一 ... binder.bind(Service.class).toProvider(new Provider<Service>() { @Override public Service get() { return new ServiceImpl(); } }); ... //方法二,或者直接编写类 public class ServiceProvider implements Provider<Service>{ @Override public Service get(){ return new ServiceImpl(); } } //正常调用 ... binder.bind(Service.class).toProvider(ServiceProvider.class) ... //方法三,也可以再借口上预定义 @ProvideBy(ServiceProvider.class) public interface Service{ ... } ... Service service = Guice.createInjector().getInstance(Client.class) ... //方法四,当然也可以注入Provider,通过Guice获取后,调用get()获取Service的实例 public class ProviderServiceDemo { @Inject private Provider<Service> provider; public static void main(String[] args) { ProviderServiceDemo psd = Guice.createInjector(new Module() { @Override public void configure(Binder binder) { binder.bind(Service.class).toProvider(WwwServiceProvider.class); }}).getInstance(ProviderServiceDemo.class); psd.provider.get().execute();//我们每次get出来都是新对象 } }
6、可以直接获取实例而不通过Modue绑定。
Injector inj= Guice.createInjector(); Service service = inj.getInstance(ServiceImpl.class); System.out.println(service.sayHello());
7、使用注解实现注入,等于是默认实现类。
@ImplementedBy(ServiceImpl.class) public interface Service{ String sayHello(); } Injector inj = Guice.createInjector(); Service service = inj.getInstance(Service.class); System.out.println(service.sayHello()); //使用Module关联 优先于 @ImplementedBy
8、静态属性注入
@Inject public Service service; //运行正常 @Inject public static Service service; //如果是刚才的客户端代码,使用时报空指针异常。 //要这么写 public class Demo{ @Inject private static Service service; public static void main(String[] args){ Guice.createInjector(new Module(){ @Override public void configure(Binder binder){ binder.requestStaticInjection(Demo.class); }//这里请求了静态注入服务。 }); Demo.service.sayHello(): } }
9、构造函数注入可以自动注入多个参数
... @Inject public Client(Service service,Service2 service2){ this.service = service; this.service2 = service2; } ...
10、使用setter注入
... @Inject public void setService(Service service){ this.service = service; } ...
11、注入实例变量的属性
public class Demo{ @Inject private Service service; public static void main(String[] args){ final Demo demo = new Demo(); Guice.createInjector(new Module(){ @Override public void configure(Binder binder){ binder.requestInjection(demo);//想实例变量注入属性 } }); demo.service.sayHello(); } } //更简便的方法 ... Guice.createInjector().injectMember(demo);//一句搞定 ...
12、绑定多个服务
public interface Service{ void execute(); } public class HomeService implements Service{ @Override public void execute(){ System.out.println("home"); } } public class WwwService implements Service{ @Override public void execute(){ System.out.println("www"); } } //这里需要定义2个注解 @Retention(RetentionPolicy.RUNTIME) @Target({FIELD,PARAMETER}) @BindingAnnotation public @interface Home { } @Retention(RetentionPolicy.RUNTIME) @Target({FIELD,PARAMETER}) @BindingAnnotation public @interface Www { } public class Demo { @Inject @Www private Service wwwService; @Inject @Home private Service homeService; public static void main(String[] args) { Demo demo = Guice.createInjector(new Module() { @Override public void configure(Binder binder) { binder.bind(Service.class).annotatedWith(Www.class).to(WwwService.class); binder.bind(Service.class).annotatedWith(Home.class).to(HomeService.class); } }).getInstance(Demo.class); demo.homeService.execute(); demo.wwwService.execute(); } }
静态注入 多个服务
public class StaticMultiInterfaceServiceDemo { @Inject @Www private static Service wwwService; @Inject @Home private static Service homeService; public static void main(String[] args) { Guice.createInjector(new Module() { @Override public void configure(Binder binder) { binder.bind(Service.class).annotatedWith(Www.class).to(WwwService.class); binder.bind(Service.class).annotatedWith(Home.class).to(HomeService.class); binder.requestStaticInjection(StaticMultiInterfaceServiceDemo.class); } }); StaticMultiInterfaceServiceDemo.homeService.execute(); StaticMultiInterfaceServiceDemo.wwwService.execute(); } }
太懒,不想写注解怎么办,用Names模板
public class NoAnnotationMultiInterfaceServiceDemo { @Inject @Named("Www") private static Service wwwService; @Inject @Named("Home") private static Service homeService; public static void main(String[] args) { Guice.createInjector(new Module() { @Override public void configure(Binder binder) { binder.bind(Service.class).annotatedWith(Names.named("Www")).to(WwwService.class); binder.bind(Service.class).annotatedWith(Names.named("Home")).to(HomeService.class); binder.requestStaticInjection(NoAnnotationMultiInterfaceServiceDemo.class); } }); NoAnnotationMultiInterfaceServiceDemo.homeService.execute(); NoAnnotationMultiInterfaceServiceDemo.wwwService.execute(); } }
13、绑定常量
public class ConstantInjectDemo { @Inject @Named("v") private int v; public static void main(String[] args) { ConstantInjectDemo cid = Guice.createInjector(new Module() { @Override public void configure(Binder binder) { binder.bindConstant().annotatedWith(Names.named("v")).to(12); //以下方法同样适用(其他基本类型全部适用) //binder.bind(int.class).annotatedWith(Names.named("v")).toInstance(12); } }).getInstance(ConstantInjectDemo.class); System.out.println(cid.v); } }
14、绑定Properties
@Inject @Named("web") private String web; public static void main(String[] args) { ConstantInjectDemo cid = Guice.createInjector(new Module() { @Override public void configure(Binder binder) { Properties properties= new Properties(); properties.setProperty("web", "www.imxylz.cn"); Names.bindProperties(binder, properties); } }).getInstance(ConstantInjectDemo.class); System.out.println(cid.web); }