Как привязать метод перехватчик к провайдеру? - PullRequest
11 голосов
/ 07 декабря 2011

Есть ли способ связать перехватчик метода с поставщиком, а не с экземпляром?

например. Я использую приведенный ниже код для привязки перехватчиков. Как бы я связал INTERCEPTOR с поставщиком, а затем с аннотацией?

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

Ответы [ 2 ]

18 голосов
/ 08 февраля 2012

Guice не позволяет AOP для экземпляров, не созданных Guice: Ограничения AOP Guice

"Экземпляры должны создаваться Guice с помощью конструктора с аннотациями @ Inject или без аргументов"

Это означает, что экземпляры, созданные с помощью провайдера, не будут кандидатами в AOP.

С другой стороны, если ваш провайдер создан Guice на указанных условиях, ваш провайдер может быть кандидатом в 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 («Строим ...»).

Если ваш вопрос: может ли перехватчик (новый INTERCEPTOR ()) быть предоставлен через провайдера Guice, ответ - нет. Самое близкое, что вы можете получить к этой функциональности, - это вызвать requestInjection () в методе configure модуля. Это введет вашему Перехватчику соответствующий код. С вашего перехватчика вы можете использовать провайдеров, чтобы избежать каких-либо накладных расходов, которые вызывают медлительность при запуске.

Вот что я имею в виду:

Модуль:

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;
    }
}

Надеюсь, это ответит на ваш вопрос.

0 голосов
/ 26 октября 2018

Вопрос в том, как я это прочитал, заключается в том, как связать себя перехватчик типа с поставщиком, а не создавать экземпляр перехватчика во время конфигурации.

Я не думаю, что есть простой способ сделать это, но можно написать перехватчик, который сам принимает поставщика для типа реализации.Пример этого показан в документации Guice AOP :

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