Showing posts with label IOC. Show all posts
Showing posts with label IOC. Show all posts

Sunday, July 27, 2008

如何获取Tapestry5在IoC中注册的serviceId及其当前状态


import java.util.Formatter;
import java.util.List;

import org.apache.tapestry5.ioc.Registry;
import org.apache.tapestry5.ioc.RegistryBuilder;
import org.apache.tapestry5.ioc.services.ServiceActivity;
import org.apache.tapestry5.ioc.services.ServiceActivityScoreboard;
import org.apache.tapestry5.ioc.services.Status;
import org.apache.tapestry5.services.TapestryModule;

// import my.test.project.services.AppModule;

public class Test {

public static void main(String[] args) {
RegistryBuilder builder = new RegistryBuilder();

builder.add(TapestryModule.class);
// 通过add方法可以将多个module加载进来,将其中的service全部注册到IoC中
// builder.add(AppModule.class, TapestryModule.class);

Registry registry = builder.build();

registry.performRegistryStartup();

StringBuilder buffer = new StringBuilder("Startup status:\n\n");
Formatter f = new Formatter(buffer);

int unrealized = 0;

ServiceActivityScoreboard scoreboard = registry.getService(ServiceActivityScoreboard.class);

List serviceActivity = scoreboard.getServiceActivity();

int longest = 0;

// One pass to find the longest name, and to count the unrealized services.
for (ServiceActivity activity : serviceActivity) {
Status status = activity.getStatus();

longest = Math.max(longest, activity.getServiceId().length());

if (status == Status.DEFINED || status == Status.VIRTUAL)
unrealized++;

}

String formatString = "%" + longest + "s: %s\n";

// A second pass to output all the services
for (ServiceActivity activity : serviceActivity) {
f.format(formatString, activity.getServiceId(), activity.getStatus().name());
}

f.format("\n%4.2f%% unrealized services (%d/%d)\n", 100. * unrealized / serviceActivity.size(), unrealized,
serviceActivity.size());

System.out.println(buffer.toString());
}
}

@Marker annotation of tapestry5

Used to define one or more marker annotations for a service implementation. This allows for injection based on the combination of type and marker interface. These marker interfaces should not have any values. The mere presence of the marker annotation is all that is needed.
当一个interface有多个实现的service时,可以为每个service实现定义一个标记(@Marker),然后就可结合对象接口的类型和这个标记来确认service并注入此service实现,当然也可以用@Inject结合@Service("serviceID")这种方式注入。

Tapestry defines two such services, in the TapestryModule.


@Marker(ClasspathProvider.class)
public AssetFactory buildClasspathAssetFactory(ResourceCache resourceCache,

ClasspathAssetAliasManager aliasManager)
{
ClasspathAssetFactory factory = new ClasspathAssetFactory(resourceCache, aliasManager);

resourceCache.addInvalidationListener(factory);

return factory;
}

@Marker(ContextProvider.class)
public AssetFactory buildContextAssetFactory(ApplicationGlobals globals)
{
return new ContextAssetFactory(request, globals.getContext());
}

Here's an example, you can see how Tapestry is figuring out which service to inject based on the presence of those annotations:

public void contributeAssetSource(MappedConfiguration configuration,
@ContextProvider
AssetFactory contextAssetFactory,

@ClasspathProvider
AssetFactory classpathAssetFactory)
{
configuration.add("context", contextAssetFactory);
configuration.add("classpath", classpathAssetFactory);
}

Reference: http://tapestry.apache.org/tapestry5/tapestry-ioc/cookbook/basics.html

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