【问题标题】:Guice dependency injection for entity beans?实体bean的Guice依赖注入?
【发布时间】:2011-06-18 20:37:51
【问题描述】:

对于富域驱动设计,我想在 JPA/Hibernate 实体 bean 上使用 Guice 依赖注入。我正在寻找与非 Spring bean 的 Spring @configurable 注释类似的解决方案。

有人知道图书馆吗?有代码示例吗?

【问题讨论】:

    标签: hibernate jpa domain-driven-design aop guice


    【解决方案1】:

    您可以使用 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() {}
    }
    

    【讨论】:

      【解决方案2】:

      我为这个问题找到了一个有点肮脏的解决方法。

      假设只有两种方法可以创建T类型的实体对象:

      • javax.inject.Provider&lt;T&gt; 获取一个
      • 从实体管理器查询它(将调用@PostLoad 注释方法)。

      进一步假设您的所有实体都有一个基础设施基类,您只需向该实体添加一个实体侦听器即可。在这个例子中,我使用了静态注入——也许有更好的方法。

      @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&lt;MyDomainEntity&gt;。这可以通过隐藏构造函数来提供。

      亲切的问候,

      avi

      【讨论】:

      • 尽管在某种程度上不鼓励静态注入,但目前添加像 AspectJ 这样的依赖项对于我的项目来说是负担不起的。此外,该解决方案适合我的问题并且非常干净。
      【解决方案3】:

      由于实体是由 JPA 提供者创建的,我看不到 Guice 什么时候会发挥作用。不妨看看Salve 项目的方法。

      【讨论】:

      • 谢谢,像 Salve 这样的代码编织解决方案真的可以解决问题。我尝试了 Salve,但它的文档有限,我无法让它做任何事情(甚至没有错误消息)。只是希望有一些简单的示例代码,例如使用 AspectJ 甚至更好的 AOP。
      • @Kdeveloper:我没有任何使用 Salve 的经验,所以我不能推荐它,但它可能会给你一些想法来实现类似的东西,这就是我提到它的原因
      猜你喜欢
      • 2011-12-09
      • 1970-01-01
      • 2014-06-28
      • 1970-01-01
      • 1970-01-01
      • 2011-01-02
      • 2018-12-07
      • 2019-08-16
      • 1970-01-01
      相关资源
      最近更新 更多