2010-07-17 107 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