Google Guice, перехватчики и приватные модули - PullRequest
3 голосов
/ 29 февраля 2012

Новый постер здесь, надеюсь, я не нарушаю никаких правил:)

Я использую PrivateModule в google-guice, чтобы иметь несколько источников данных для одной и той же среды. Но мне трудно заставить MethodInterceptor работать внутри приватных модулей. Ниже приведен простой тестовый пример, который объясняет «проблему».

Простой класс обслуживания будет:

interface Service {
    String go();
}

class ServiceImpl implements Service {

    @Override @Transactional
    public String go() {
        return "Test Case...";
    }

}

Класс MyModule будет:

class MyModule extends AbstractModule {

    @Override
    protected void configure() {
        install(new PrivateModule() {
            @Override
            protected void configure() {
                bind(Service.class).to(ServiceImpl.class);
                bindInterceptor(
                    Matchers.any(),
                    Matchers.annotatedWith(Transactional.class),
                    new MethodInterceptor() {
                    @Override
                    public Object invoke(MethodInvocation i)
                            throws Throwable {
                        System.out.println("Intercepting: "
                                + i.getMethod().getName());
                        return i.proceed();
                    }
                });
                expose(Service.class);
            }
        });
    }

}

И последний контрольный пример:

public class TestCase {

    @Inject Service service;

    public TestCase() {
        Guice.createInjector(new MyModule()).injectMembers(this);
    }

    public String go() {
        return service.go();
    }

    public static void main(String[] args) {
        TestCase t = new TestCase();
        System.out.println(t.go());
    }

}

Вы ожидаете, что результат будет:

Intercepting: go
Test Case...

Но этого не происходит, перехватчик не используется, выводится только муравей Test Case....

Если я связываю / выставляю ServiceImpl вместо интерфейса, тогда он работает.

Заранее спасибо, С Уважением, LL

Ответы [ 2 ]

0 голосов
/ 02 марта 2012

Вам необходимо явно связать ServiceImpl в приватном модуле. Проблема с вашим существующим кодом заключается в том, что он наследует привязку для ServiceImpl от родительского модуля. Из PrivateModule документов,

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

Добавление этой строки должно решить проблему:

bind(ServiceImpl.class);
0 голосов
/ 01 марта 2012

Ну ... я понял это вскоре после того, как отправил вопрос:)

Проблема в том, что вам также необходимо expose() класс ServiceImpl. Таким образом, связывание / разоблачение будет.

bind(ServiceImpl.class); // ServiceImpl annotated with @Singleton
bind(Service.class).to(ServiceImpl.class);
expose(ServiceImpl.class);
expose(Service.class);

С уважением,
LL

...