Hoe methode interceptor binden aan provider?

Is er een manier om een ​​methode-interceptor te binden aan een provider in plaats van een instantie?

bijv. Ik gebruik de onderstaande code om interceptors te binden, hoe zou ik INTERCEPTOR binden aan een provider en vervolgens aan de annotatie?

bindInterceptor(
    Matchers.any(), Matchers.annotatedWith(ANNOTATION.class), new INTERCEPTOR());
11
Welnu, elke methode is ideaal, we hebben een systeem voor prestatiecontrole dat oproepen van de methode en tijdstippen van uitvoering enz. Onderschept. Ik wil de interceptor lui initialiseren.
toegevoegd de auteur Usman Ismail, de bron
Wat probeer je te onderscheppen? de methode get() of misschien een setter-methode?
toegevoegd de auteur John Ericksen, de bron

1 antwoord

Guice does not allow AOP on instances not built by Guice: Guice AOP Limitations

"Exemplaren moeten door Guice worden gemaakt door een constructor met @ Inject-annotatie of zonder argument"

Dit betekent dat instanties die zijn gemaakt met een provider, geen kandidaat zijn voor AOP.

Aan de andere kant, zolang uw Provider wordt geïnstantieerd door Guice onder de vermelde voorwaarden, kan uw Provider een kandidaat zijn voor AOP.

Hier is een voorbeeld dat dit laat zien:

AOP-annotatie:

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

provider:

public class ExampleProvider implements Provider {

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

Doel voorbeeld:

public class Example {

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

}

module:

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

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

Testcode:

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();

    }
}

Testoutput:

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

Merk op dat het "voorbeeld werken ..." niet wordt omringd door de timercode. De Provider.get ("Gebouw ...") is echter.

Als uw vraag is: kan de interceptor (nieuwe INTERCEPTOR ()) via een Guice-provider worden verstrekt, dan is het antwoord nee. Het dichtst bij deze functionaliteit is het requestInjection() aanroepen in de module-configuratiemethode. Dit zal uw Interceptor met de juiste code injecteren. Vanuit uw interceptor kunt u mogelijk Providers gebruiken om elke vorm van overhead te vermijden die u traag maakt tijdens het opstarten.

Dit is wat ik bedoel:

module:

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

Onderschepper:

public class LoggingAOP implements MethodInterceptor {

    @Inject
    private Provider 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;
    }
}

Ik hoop dat dit je vraag beantwoordt.

18
toegevoegd
Geweldig "Hello World" -voorbeeld voor Guice AOP.
toegevoegd de auteur ripper234, de bron
Bedankt @ ripper234. Overigens hebben we vergelijkbare (bijna identieke) faciliteiten in Transfuse, een project waaraan ik heb gewerkt: androidtransfuse .org/documentation.html # method_interceptors
toegevoegd de auteur John Ericksen, de bron