如何将方法拦截器绑定到提供程序?

时间:2011-12-06 20:13:29

标签: java guice

是否可以将方法拦截器绑定到提供程序而不是实例?

e.g。我使用下面的代码绑定拦截器如何将INTERCEPTOR绑定到提供程序,然后绑定到注释?

bindInterceptor(
    Matchers.any(), Matchers.annotatedWith(ANNOTATION.class), new INTERCEPTOR());

2 个答案:

答案 0 :(得分:18)

Guice不允许在非Guice构建的实例上使用AOP:Guice AOP Limitations

“实例必须由Guice通过@Inject-annotated或无参数构造函数创建”

这意味着使用提供程序创建的实例不会成为AOP的候选者。

另一方面,只要您的提供商在提及的条件下由Guice实例化,您的提供商可能是AOP的候选人。

这是一个证明这一点的例子:

AOP注释:

@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD)
@interface AOPExample {}

提供者:

public class ExampleProvider implements Provider<Example> {

    @AOPExample
    public Example get() {
        System.out.println("Building...");
        return new Example();
    }
}

目标示例:

public class Example {

    @AOPExample
    public void tryMe() {
        System.out.println("example working...");
        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

模块:

public class ExampleModule extends AbstractModule {
    @Override
    protected void configure() {
        bindInterceptor(Matchers.any(), Matchers.annotatedWith(AOPExample.class), new LoggingAOP());

        bind(Example.class).toProvider(ExampleProvider.class);
    }
}

测试代码:

public class Test {

    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new TestModule());

        ExampleProvider exampleProvider = injector.getInstance(ExampleProvider.class);
        Example example = exampleProvider.get();

        example.tryMe();

        Example directExample = injector.getInstance(Example.class);

        directExample.tryMe();

    }
}

测试输出:

start
Building...
end took: 3
example working...
start
Building...
end took: 0
example working...

请注意,“示例工作...”未被计时器代码包围。然而,Provider.get(“Building ...”)是。

如果您的问题是:拦截器(新的INTERCEPTOR())是否可以通过Guice Provider提供,答案是否定的。您可以获得此功能的最接近的方法是在模块配置方法中调用requestInjection()。这将为您的Interceptor注入适当的代码。从你的拦截器中你可以使用Providers来避免任何导致你在启动期间变慢的开销。

这就是我的意思:

模块:

public class TestModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(String.class).toInstance("One");
        bind(String.class).annotatedWith(Names.named("two")).toInstance("Two");

        LoggingAOP loggingAOP = new LoggingAOP();

        bindInterceptor(Matchers.any(), Matchers.annotatedWith(AOPExample.class), loggingAOP);

        requestInjection(loggingAOP);

        bind(Example.class).toProvider(ExampleProvider.class);
    }
}

拦截器:

public class LoggingAOP implements MethodInterceptor {

    @Inject
    private Provider<SomethingThatTakesALongTimeToInit> provider;

    public Object invoke(MethodInvocation invocation) throws Throwable {
        provider.get()...
        System.out.println("start");
        long start = System.currentTimeMillis();
        Object value =  invocation.proceed();
        System.out.println("end took: " + (System.currentTimeMillis() - start));
        return value;
    }
}

希望这能回答你的问题。

答案 1 :(得分:0)

据我所读,问题是,如何将 interceptor 类型本身绑定到提供程序,而不是在配置时实例化拦截器。

我认为没有简单的方法可以做到这一点,但是可以编写一个拦截器,该拦截器本身接受实现类型的提供者。 the Guice AOP documentation中显示了一个示例:

public class NotOnWeekendsModule extends AbstractModule {
    protected void configure() {
    bindInterceptor(any(),
                    annotatedWith(NotOnWeekends.class),
                    new WeekendBlocker(getProvider(Calendar.class)));
    }
}