2016-07-08 50 views
2

我有以下類別:創建@現有對象的UnitOfWork感知代理

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

現在,FooService是不是一種資源,所以Dropwizard不知道這件事,並沒有自動的代理它。然而,Dropwizard的聰明人讓我可以通過UnitOfWorkAwareProxyFactory獲得代理。

我試着用攔截器向Guice餵食這些代理,但是我遇到了一個問題,因爲UnitOfWorkAwareProxyFactory只能創建新的實例,並且永遠不會讓我通過現有的對象。新實例的事情是,我不知道給它的參數,因爲它們是由Guice注入的。

如何創建@UnitOfWork -aware代理現有對象?

這裏是我到目前爲止做出的攔截:

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

當然,如果Dropwizard(或吉斯)我提供了一個簡單的方法來做到這一點,這是什麼呢?

+1

注:我已經成功地由含有適當的變化,這將在Dropwizard 1.1提供一個公關。它基本上使'UnitOfWorkAspect'公開,這在Guice和其他依賴注入框架中更容易使用。 –

回答

4

作爲從Dropwizard 1.1:(尚未公佈後,截至2016年8月10日)的

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