Saturday, July 26, 2008

about Alias and AliasOverrides of Tapestry5

在tapestry5中一般一个interface只有一个service实现,在IOC里注册绑定此service即可。然后在page中用@Inject声明即可获取对应的service实例。
如果当一个interface有多个service实现,都在IOC中注册时,并没有默认的service实现,在page中@Inject时就会有岐义,不知道要用哪个service实例,因此可以另外再以@service("serviceId")明确声明serviceId。
如果想在@Inject到page时不显式用@service("serviceId")指定特定的serviceId,就需要在IOC注册时声明一个默认实现的service,这个可以在注册service时,不指定serviceId,以此为默认service,和使用Alias声明默认service这二种方式告知IOC容器哪个是默认的service实现,前者优先级更高。
而对于某一interface,在容器中已经存在了默认的service实现,如Tapestry5内置的一些service,假如需要用自己实现的service覆盖已经存在的默认实现就会用到AliasOverride声明。
以下举例说明:


public interface IHibernateBase {
public void test();
}

public class HibernateBase implements IHibernateBase {
public void test() {
System.out.println("test in hibernateBase...");
}
}

public class HibernateBase2 implements IHibernateBase {
public void test() {
System.out.println("test in hibernateBase2...");
}
}

一、在AppModule中注册以下service,对于这种情况,存在3个service都实现相同的Interface,在page中@Inject时必须要用@service指定使用哪个serviceId。

/**
* 注册二个实现IHibernateBase接口的service
* serviceId: HibernateBase 和 HibernateBase2
*/
public static void bind(ServiceBinder binder) {
binder.bind(IHibernateBase.class, HibernateBase.class).withId("HibernateBase");
binder.bind(IHibernateBase.class, HibernateBase2.class).withId("HibernateBase2");
}

/**
* 注册一个新的serviceId: HibernateBase3
*/
public static IHibernateBase buildHibernateBase3() throws Exception {
IHibernateBase hibernate = new HibernateBase2();
// operation on hiberante object ...
return hibernate;
}

二、在AppModule注册以下service,用Alias指明interface的默认实现service:

/**
* 注册二个实现IHibernateBase接口的service
* serviceId: HibernateBase 和 HibernateBase2
*/
public static void bind(ServiceBinder binder) {
// binder.bind(IHibernateBase.class, HibernateBase.class); // 默认serviceId: HibernateBase
binder.bind(IHibernateBase.class, HibernateBase.class).withId("HibernateBase1");
binder.bind(IHibernateBase.class, HibernateBase2.class).withId("HibernateBase2");
}

/**
* 注册一个新的serviceId: HibernateBase3
*/
public static IHibernateBase buildHibernateBase3() throws Exception {
IHibernateBase hibernate = new HibernateBase2();
// operation on hiberante object ...
return hibernate;
}

/**
* 用Alias声明HibernateBase3做为默认的service。
*/
public static void contributeAlias(@InjectService("HibernateBase3") IHibernateBase hibernate,
Configuration configuration) {
configuration.add(AliasContribution.create(IHibernateBase.class, hibernate));
}

三、当存在默认service时,需要用AliasOverrides覆盖实现:

/**
* 注册二个实现IHibernateBase接口的service
* serviceId: HibernateBase 和 HibernateBase2
*/
public static void bind(ServiceBinder binder) {
binder.bind(IHibernateBase.class, HibernateBase.class); // 默认serviceId: HibernateBase
binder.bind(IHibernateBase.class, HibernateBase2.class).withId("HibernateBase2");
}

/**
* 注册一个新的serviceId: HibernateBase3
*/
public static IHibernateBase buildHibernateBase3() throws Exception {
IHibernateBase hibernate = new HibernateBase2();
// operation on hiberante object ...
return hibernate;
}

/**
* 用AliasOverrides声明HibernateBase3覆盖原来默认的HibernateBase
* 做为IHibernateBase的默认的service。
*/
public static void contributeAliasOverrides(@InjectService("HibernateBase3") IHibernateBase hibernate,
Configuration configuration) {
configuration.add(AliasContribution.create(IHibernateBase.class, hibernate));
}

Reference: http://tapestry.apache.org/tapestry5/tapestry-core/guide/alias.html

No comments :