2010-07-17 106 views
7

對於豐富的域驅動設計,我想使用對JPA/Hibernate實體bean的Guice依賴注入。我正在尋找一個類似於非Spring bean的Spring @configurable註釋的解決方案。實體bean的Guice依賴注入?

有人知道圖書館嗎?任何代碼示例?

回答

5

你可以用AspectJ做到這一點。

創建@Configurable註解:

@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.TYPE}) 
public @interface Configurable { 
} 

創建一個AspectJ @Aspect與此類似:

@Aspect 
public class ConfigurableInjectionAspect { 
    private Logger log = Logger.getLogger(getClass().getName()); 

    @Pointcut("@within(Configurable) && execution(*.new(..)) && target(instantiated)") 
    public void classToBeInjectedOnInstantiation(Object instantiated) {} 

    @After(value = "classToBeInjectedOnInstantiation(instantiated)", 
      argNames = "instantiated") 
    public void onInstantiation(Object instantiated) { 
     Injector injector = InjectorHolder.getInjector(); 
     if (injector == null) { 
      log.log(Level.WARNING, "Injector not available at this time"); 
     } else { 
      injector.injectMembers(instantiated); 
     } 
    } 
} 

創建(和使用)控股類的噴油器:

public final class InjectorHolder { 

    private static Injector injector; 

    static void setInjector(Injector injector) { 
     InjectorHolder.injector = injector; 
    } 

    public static Injector getInjector() { 
     return injector; 
    } 
} 
配置META-INF/aop.xml:
<aspectj> 
    <weaver options="-verbose"> 
     <include within="baz.domain..*"/> 
     <include within="foo.bar.*"/> 
    </weaver> 
    <aspects> 
     <aspect name="foo.bar.ConfigurableInjectionAspect"/> 
    </aspects> 
</aspectj> 

與aspectjweaver啓動VM:

-javaagent:lib/aspectjweaver.jar 

註釋域類:

@Entity 
@Table(name = "Users") 
@Configurable 
public class User { 
    private String username; 
    private String nickname; 
    private String emailAddress; 
    @Inject 
    private transient UserRepository userRepository 

    public User() {} 
} 
1

由於實體是由JPA提供者創建的,所以我沒有看到Guice何時會進場。也許看看Salve項目的方法。

+0

謝謝,像藥膏一個codeweaving解決方案可以真正做的伎倆。我嘗試過Salve,但是它的文檔有限,我無法做任何事情(甚至沒有錯誤信息)。只希望一些簡單的示例代碼,例如使用AspectJ或更好的AOP。 – Kdeveloper 2010-07-18 05:13:59

+0

@Kdeveloper:我對Salve沒有任何經驗,所以我不推薦它,但它可能會給你一些想法來實現類似的東西,這就是爲什麼我提到它 – 2010-07-19 13:26:50

3

我發現這個問題有點髒的解決方法。

假設僅存在兩種方法來創建T類型的實體對象:

  • javax.inject.Provider<T>
  • 獲取一個從實體管理器(其將調用@PostLoad註解的方法)Quering它。

此外,假設您擁有所有實體的基礎結構基類,那麼您可以將實體監聽器添加到此實體中。在這個例子中,我使用靜態注入 - 也許有更好的方法。

@MappedSuperclass 
public abstract class PersistentDomainObject<K extends Serializable & Comparable<K>> 
    implements Comparable<PersistentDomainObject<K>>, Serializable { 

    private static transient Injector injector; 

    @PostLoad 
    private final void onAfterLoaded() { 
     injector.injectMembers(this); 
    } 

    @EmbeddedId 
    private K id; 

    public K getId() { return id; } 

    // ... compareTo(), equals(), hashCode(), maybe a @Version member ... 
} 

在你的模塊設置,您只需要調用requestStaticInjection(PersistentDomainObject.class);

現在,你根本就創建一個像

@Entity 
public class MyDomainEntity extends PersistentDomainObject<SomeEmbeddableIdType> 
    implements HatLegacyId { 

    @Inject 
    private transient MyDomainService myDomainService; 

    private String name; 
    // ... common stuff 
} 

它壞事實體類,你必須在沒有人相信會創造一個MyDomainEntity自己,但會要求Provider<MyDomainEntity>。這可以通過隱藏構造函數來提供。

親切的問候,

AVI

+0

即使靜態注入在某種程度上不鼓勵,添加依賴像AspectJ目前不適合我的項目。此外,解決方案適合我的問題,相當乾淨。 – Iacopo 2012-09-10 10:32:53