灯火互联
管理员
管理员
  • 注册日期2011-07-27
  • 发帖数41778
  • QQ
  • 火币41290枚
  • 粉丝1086
  • 关注100
  • 终身成就奖
  • 最爱沙发
  • 忠实会员
  • 灌水天才奖
  • 贴图大师奖
  • 原创先锋奖
  • 特殊贡献奖
  • 宣传大使奖
  • 优秀斑竹奖
  • 社区明星
阅读:2787回复:0

Android RoboGuice使用指南(5):Binding Annotations

楼主#
更多 发布于:2012-09-06 13:56

有些情况需要将同一类型映射到不同的类实现,还是使用绘图的例子.
IShape, Rectangle, MyRectangle, MySquare,有如下继承关系:






我们可能需要将IShape 同时映射到MyRectangle 和MySquare ,这时可以使用Binding Annotation 来实现。 这时使用类型和annotation (标注)可以唯一确定一个Binding。Type 和annotation 对称为Key(键)。
为了同时使用MyRectangle和MySequare,我们定义两个annotation,如下
[java] import com.google.inject.BindingAnnotation;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
  
...
@BindingAnnotation
@Target({ FIELD, PARAMETER, METHOD })
@Retention(RUNTIME)
public @interface Rectangle {
}
...
  
@BindingAnnotation
@Target({ FIELD, PARAMETER, METHOD })
@Retention(RUNTIME)
public @interface Square {
}
import com.google.inject.BindingAnnotation;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;

...
@BindingAnnotation
@Target({ FIELD, PARAMETER, METHOD })
@Retention(RUNTIME)
public @interface Rectangle {
}
...

@BindingAnnotation
@Target({ FIELD, PARAMETER, METHOD })
@Retention(RUNTIME)
public @interface Square {
}
定义了两个标注 @Rectangle, @Square, 至于@BindingAnnotation,@Target,@Retention你并不需要详细了解,有兴趣的可以参见java Annotation tutorial .
简单的说明如下:
@BindingAnnotation 通知这是一个Binding Annotation,如果将多个个标注应用到同一个元素时,Guice会报错。
@Target({FIELD, PARAMETER, METHOD}) 表示这个标注可以应用到类成员变量,函数的参数或时方法。
@Retention(RUNTIME) 表示这个标注在程序运行时可以使用Reflection读取。
创建一个BindingAnnotationsDemo 用来绘制两个图形:
[java] public class BindingAnnotationsDemo extends Graphics2DActivity{
  
@Inject @Rectangle IShape  shape1;
@Inject @Square IShape  shape2;
  
protected void drawImage(){
  
/**
* The semi-opaque blue color in
* the ARGB space (alpha is 0x78)
*/
Color blueColor = new Color(0x780000ff,true);
/**
* The semi-opaque green color in the ARGB space (alpha is 0x78)
*/
Color greenColor = new Color(0x7800ff00,true);
  
graphics2D.clear(Color.WHITE);
graphics2D.Reset();
  
SolidBrush brush=new SolidBrush(blueColor);
  
graphics2D.fill(brush,shape1);
AffineTransform at = new AffineTransform();
at.translate(20, 20);
graphics2D.setAffineTransform(at);
brush=new SolidBrush(greenColor);
graphics2D.fill(brush,shape2);
  
}
  
}
public class BindingAnnotationsDemo extends Graphics2DActivity{

@Inject @Rectangle IShape  shape1;
@Inject @Square IShape  shape2;

protected void drawImage(){

/**
* The semi-opaque blue color in
* the ARGB space (alpha is 0x78)
*/
Color blueColor = new Color(0x780000ff,true);
/**
* The semi-opaque green color in the ARGB space (alpha is 0x78)
*/
Color greenColor = new Color(0x7800ff00,true);

graphics2D.clear(Color.WHITE);
graphics2D.Reset();

SolidBrush brush=new SolidBrush(blueColor);

graphics2D.fill(brush,shape1);
AffineTransform at = new AffineTransform();
at.translate(20, 20);
graphics2D.setAffineTransform(at);
brush=new SolidBrush(greenColor);
graphics2D.fill(brush,shape2);

}

}
使用标注将shape1 绑定到MyRectangle, shape2绑定到MySquare,对应的Module 定义如下:

[java] public class Graphics2DModule extends AbstractAndroidModule{
  
@Override
protected void configure() {
  
bind(IShape.class)
.annotatedWith(Rectangle.class)
.to(MyRectangle.class);
  
bind(IShape.class)
.annotatedWith(Square.class)
.to(MySquare.class);
  
}
}







Inject 可以应用到Field (成员变量),Parameter (参数)或Method(方法),前面的例子都是应用到Field上,如果应用到参数可以有如下形式:
[java] @Inject
public IShape getShape(@Rectangle IShape shape){
...
}
@Inject
public IShape getShape(@Rectangle IShape shape){
...
}
如果你不想自定义Annotation,可以使用Guice自带的@Name标注来解决同一类型绑定到不同实现的问题。
修改上面代码:
[java]  //@Inject @Rectangle IShape  shape1;  
//@Inject @Square IShape  shape2;  
  
@Inject @Named("Rectangle") IShape shape1;
@Inject @Named("Square") IShape shape2;
//@Inject @Rectangle IShape  shape1;
//@Inject @Square IShape  shape2;

@Inject @Named("Rectangle") IShape shape1;
@Inject @Named("Square") IShape shape2;
修改绑定如下:

[java] view plaincopyprint? //bind(IShape.class)  
//.annotatedWith(Rectangle.class)  
//.to(MyRectangle.class);  
  
//bind(IShape.class)  
//.annotatedWith(Square.class)  
//.to(MySquare.class);  
  
bind(IShape.class)
.annotatedWith(Names.named("Rectangle"))
.to(MyRectangle.class);
bind(IShape.class)
.annotatedWith(Names.named("Square"))
.to(MySquare.class);
//bind(IShape.class)
//.annotatedWith(Rectangle.class)
//.to(MyRectangle.class);

//bind(IShape.class)
//.annotatedWith(Square.class)
//.to(MySquare.class);

bind(IShape.class)
.annotatedWith(Names.named("Rectangle"))
.to(MyRectangle.class);
bind(IShape.class)
.annotatedWith(Names.named("Square"))
.to(MySquare.class);

这种方法简单,但编译器无法检测字符串,比如将”Square”错写为”Sqare”,编译器无法查出这个错误,此时到运行时才可能发现 shape2 无法注入,因此建议尽量少用Named.


喜欢0 评分0
游客

返回顶部