Guice TypeListener not notified about the injected class Type

I have the following Guice module:

class MyModule extends AbstractModule {

    @Override
    protected void configure() {
        bindListener(Matchers.any(), new TypeListener() {...});    
    }

    @Provides
    SomeClass createSomeClass(final Parameter param) {
        log(param.getValue()); <-- this gets logged
        ...
    }
}

What I found strange is that my TypeListener doesn't get notified about the Parameter type. Even though the provider is beign called and returns SomeClass . I also see the log statement so clearly the Parameter was injected by Guice.

@Override
protected void configure() {
    bind(Parameter.class);
    bindListener(Matchers.any(), new TypeListener() {...});    
}

I'm aware of Untargetted bindings and the statement:

An untargetted binding informs the injector about a type, so it may prepare dependencies eagerly.

I would still expect Guice to call the TypeListener for any type which is either explicitly binded or injected for the first time.

So do I need to make untargetted binding for such classes as a rule of thumb?

NOTE: marking the Parameter constructor with @Inject doesn't solve the problem.

EDIT:

The complete example (hope I din't leave too much garbage) is as follows:

public class TestGuice {

    public static void main(String[] args) {
        Injector parentInjector = Guice.createInjector(new ParentModule());
        Injector childInjector = parentInjector.createChildInjector(new SubModule());

        childInjector.getInstance(Runnable.class).run();
    }

    static class ParentModule extends AbstractModule {

        @Override
        protected void configure() {

        }
    }

    static class SubModule extends  AbstractModule {

        @Override
        protected void configure() {
            bind(SampleInjectedClass.class); // <-- Comment/uncomment here

            final TypeListener typeListener = new TypeListener() {
                public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
                    System.out.println("Type: " + type.getRawType());
                }
            };

            bindListener(Matchers.any(), typeListener);
        }

        @Provides
        Runnable createRunnable(final SampleInjectedClass sampleClass) {
            return new Runnable() {

                @Override
                public void run() {
                    sampleClass.test();
                }
            };
        }
    }

    static class SampleInjectedClass {
        public void test() {
            System.out.println("Test");
        }
    }
}

If the line is present the output is:

Type: class com.barcap.test.TestGuice$SampleInjectedClass

Type: class com.google.inject.internal.ProviderMethod

Test

If I remove the line I get:

Type: class com.google.inject.internal.ProviderMethod

Test

I noticed that if the injector wasn't created via the createChildInjector code the bind(...) is not necessary.


Just-in-time bindings created for child injectors will be created in an ancestor injector whenever possible. This means that, without the bind(SampleInjectedClass.class); line, the binding for SampleInjectedClass is created in the parent injector. Since the parent injector doesn't have your TypeListener , it won't be triggered.


Can you check your code? In my test on Guice 3, I couldn't reproduce what you're seeing.

Also, from the TypeListener docs, emphasis mine and typo sic:

public abstract void hear (TypeLiteral<I> type, TypeEncounter<I> encounter)

Invoked when Guice encounters a new type eligible for constructor or members injection. Called during injector creation (or afterwords if Guice encounters a type at run time and creates a JIT binding) .

Though all the rest of your dependencies will be called on the TypeListener immediately when the injector is created, implicit ("just-in-time") bindings will not.

However, based on my example above, it appears that when a parameter is included in a provider method, it is registered on the same listener immediately. Can you produce a short self-contained example that shows the behavior you're asking about?

链接地址: http://www.djcxy.com/p/16932.html

上一篇: 将现有的列转换为标识

下一篇: Guice TypeListener没有通知注入的类类型