Tapestry IoC Service

Services

可以在AppModule类中追加如下方法:

public static SomeInterface build(){
    return new SomeInterfaceImpl();
}

我们的方法可以使build,也可以是以build开头的方法,如buildSomething。

还有一种更为推荐的方式为使用

public static void bind(ServiceBinder binder){
    binder.bind(SomeInterface.class, SomeInterfaceImpl.class);
}

甚至,如果一个接口跟它的实现类在一个package下的话,并且实现类的名字为接口的名字+impl的话,可以省略掉后一个参数,如:

public static void bind(ServiceBinder binder){ binder.bind(SomeInterface.class); } 

 

Service Id

每一个Service都有一个名字,默认的名字就是Service的class名称,如果修改的话,可以使用@ServiceId注解

@ServiceId("FileSystemIndexer")
public static Indexer buildIndexer(@InjectService("FileSystem") FileSystem fileSystem)
{
   . . .
}

另外一种就是

public static Indexer buildFileSystemIndexer(@InjectService("FileSystem") FileSystem fileSystem)
{
   . . .
}

还有一种

@ServiceId("FileSystemIndexer")
public class IndexerImpl implements Indexer
{
    ...
}

// Module.class
binder.bind(Indexer.class, IndexerImpl.class);

还有另外一种:

binder.bind(Indexer.class, IndexerImpl.class).withId("FileSystemIndexer");

HOLLY SHIT! SO MANY KINDS OF METHODS RESULT IN I DON'T KNOW WHICH TO CHOOSE.

 

Service之间可能是相互依赖的,如我们有一个Service,它的实现需要用到别的Service,这时需要按照如下方法进行服务的注册:

public static Indexer build(JobScheduler scheduler, FileSystem fileSystem)
{
  IndexerImpl indexer = new IndexerImpl(fileSystem);
  scheduler.scheduleDailyJob(indexer);
  return indexer;
}

如果我们依赖的Service有多个实现,那么我们就需要用到@ServiceId这个注解了:

public static Indexer build(@InjectService("JobScheduler")JobScheduler scheduler,  @InjectService("FileSystem")FileSystem fileSystem)
{
  IndexerImpl indexer = new IndexerImpl(fileSystem);
  scheduler.scheduleDailyJob(indexer);
  return indexer;
}

 

如果有多个Service依赖了另外同一个Service的话,我们可以给module类追加一个构造器,并且把这个被依赖的Service作为它的构造参数。

 

@Marker

可以通过设定自定义的注解来帮助Tapestry去定位一个服务的实现。小猿没啥兴趣~

Tapestry有一个自定义的Marker——@Local,它会告诉Tapestry只允许找自己这个module中的实现~

 

advise

这是用来给service追加一些建议,保证的东西。

例如:给某些想要返回一个String类型的值得service方法追加一个判断,如果返回的是一个NULL的话,就返回一个空字符串

public static void adviseNonNull(MethodAdviceReceiver receiver) {
...
}

这里面有几个问题

1 这个方法的返回值是void,且是static的。

2 这个方法的适用范围没有设定,所以追加适用范围@Match("*")或@Match("*DAO")。

3 建议内容没有设定,所以追加建议内容,是以内部类的方式来实现的,

MethodAdvice advice = new MethodAdvice(){
    void advice(MethodInvocation invocation){
        // 首先方法运行
        invocation.proceed();
        // 可以得到结果了,如果是null的话
        if (getReturnValue().equals(null)) {
             invocation.setReturnValue("");
        }
    }
}

没有任何问题,什么时候触发这个advice呢?

4 设定触发条件,返回类型是String的时候。

        for (Method method : receiver.getInterface().getMethods()) {
            if (method.getReturnType().equals(String.class)) {
                receiver.adviseMethod(method, advice);
            }
        }

所以结合起来:

    /**
     * If the return value, of the method of some service, is null, then set it into ""
     */
    @Match("*")
    public static void adviseNonNull(MethodAdviceReceiver receiver) {

        MethodAdvice advice = new MethodAdvice() {

            public void advise(MethodInvocation invocation) {
                invocation.proceed();

                if (invocation.getReturnValue().equals(null)) {
                    invocation.setReturnValue("");
                }
            }
        };

        // for those method of services of which the return type is String.class
        // Add the advice above
        for (Method method : receiver.getInterface().getMethods()) {
            if (method.getReturnType().equals(String.class)) {
                receiver.adviseMethod(method, advice);
            }
        }

    }

 

其它的一些advise

// LOG ADDING
@Match("*") public static void adviseLogging(LoggingAdvisor loggingAdvisor, Logger logger, MethodAdviceReceiver receiver) { loggingAdvisor.addLoggingAdvice(logger, receiver); }
// 所有DAO下面的service方法中如果标记了@CommitAfter就会自动将把业务提交
@Match("*Dao") public static void adviseTransactions(HibernateTransactionAdvisor advisor, MethodAdviceReceiver receiver) { advisor.addTransactionCommitAdvice(receiver); }

 

posted @ 2014-06-09 16:49  VoctrALs  阅读(324)  评论(0编辑  收藏  举报