2016-07-08 4 views
2

Ich habe die folgenden Klassen:erstellen @ UnitOfWork-aware Proxies vorhandener Objekte

public FooDAO extends AbstractDAO<Foo> { // Dropwizard DAO 
    @Inject FooDAO(SessionFactory sf) { super(sf); } 
    public void foo() { /* use SessionFactory */ } 
} 

public class FooService { 
    private final FooDAO fooDAO; // Constructor-injected dependency 
    @Inject FooService (FooDAO fooDAO) { this.fooDAO = fooDAO; } 

    @UnitOfWork 
    public void foo() { 
    this.fooDAO.foo(); 
    System.out.println("I went through FooService.foo()"); 
    } 
} 

Nun FooService nicht eine Ressource ist, so Dropwizard darüber nicht weiß und nicht automatisch Proxy es. Aber die schlauen Jungs von Dropwizard haben es geschafft, dass ich einen Proxy durch UnitOfWorkAwareProxyFactory bekomme.

Ich habe versucht, diese Proxies zu Guice mit einem Interceptor zu füttern, aber ich sah ein Problem, weil UnitOfWorkAwareProxyFactory nur immer neue Instanzen erstellt und mich nie vorhandene Objekte passieren lassen. Die Sache mit neuen Instanzen ist, dass ich die Parameter nicht kenne, um es zu geben, da sie von Guice injiziert werden.

Wie erstelle ich @UnitOfWork -aware Proxies von vorhandenen Objekten?

Hier ist der Interceptor die ich bisher gemacht habe:

public class UnitOfWorkModule extends AbstractModule { 
    @Override protected void configure() { 
    UnitOfWorkInterceptor interceptor = new UnitOfWorkInterceptor(); 
    bindInterceptor(Matchers.any(), Matchers.annotatedWith(UnitOfWork.class), interceptor); 
    requestInjection(interceptor); 
    } 

    private static class UnitOfWorkInterceptor implements MethodInterceptor { 
    @Inject UnitOfWorkAwareProxyFactory proxyFactory; 
    Map<Object, Object> proxies = new IdentityHashMap<>(); 

    @Override public Object invoke(MethodInvocation mi) throws Throwable { 
     Object target = proxies.computeIfAbsent(mi.getThis(), x -> createProxy(mi)); 
     Method method = mi.getMethod(); 
     Object[] arguments = mi.getArguments(); 
     return method.invoke(target, arguments); 
    } 

    Object createProxy(MethodInvocation mi) { 
     // here, what to do? proxyFactory will only provide objects where I pass constructor arguments, but... I don't have those! 
    } 
    } 
} 

Natürlich, wenn Dropwizard (oder Guice) bietet mir einen einfacheren Weg, dies zu tun, was es ist?

+1

Hinweis: Ich habe erfolgreich eine PR enthält eine entsprechende Änderung vorgenommen, die in Dropwizard 1.1 verfügbar sein werden, . Es macht im Grunde "UnitOfWorkAspect" öffentlich, was in Guice und anderen Frameworks zur Abhängigkeitsinjektion * viel * einfacher zu verwenden ist. –

Antwort

4

Wie aus Dropwizard 1.1: (noch nicht veröffentlicht, Stand: 10. August 2016)

public class UnitOfWorkModule extends AbstractModule { 

    @Override 
    protected void configure() { 
    UnitOfWorkInterceptor interceptor = new UnitOfWorkInterceptor(); 
    bindInterceptor(Matchers.any(), Matchers.annotatedWith(UnitOfWork.class), interceptor); 
    requestInjection(interceptor); 
    } 

    @Provides 
    @Singleton 
    UnitOfWorkAwareProxyFactory provideUnitOfWorkAwareProxyFactory(HibernateBundle<AlexandriaConfiguration> hibernateBundle) { 
    return new UnitOfWorkAwareProxyFactory(hibernateBundle); 
    } 

    private static class UnitOfWorkInterceptor implements MethodInterceptor { 

    @Inject 
    UnitOfWorkAwareProxyFactory proxyFactory; 

    @Override 
    public Object invoke(MethodInvocation mi) throws Throwable { 
     UnitOfWorkAspect aspect = proxyFactory.newAspect(); 
     try { 
     aspect.beforeStart(mi.getMethod().getAnnotation(UnitOfWork.class)); 
     Object result = mi.proceed(); 
     aspect.afterEnd(); 
     return result; 
     } catch (InvocationTargetException e) { 
     aspect.onError(); 
     throw e.getCause(); 
     } catch (Exception e) { 
     aspect.onError(); 
     throw e; 
     } finally { 
     aspect.onFinish(); 
     } 
    } 
    } 
}