java - 在私有(private) Guice 模块中公开通用绑定(bind)

标签 java persistence guice

我最近开始使用 Google Guice,学习在网上找到的教程和代码,但现在我陷入了困境。

我尝试创建一个可以在每个 EntityDAO 基础上扩展的 GenericDAO。我无法弄清楚如何配置现有的私有(private) Guice 模块。

这是我的 PrivateModule,其中 Person 是一个使用 String 作为身份的实体。 Address 类是另一个不依赖于 GenericDAO 的实体(目前为止,我试图让它从简单开始)。

public class PersistModule extends PrivateModule {

    @Override
    protected void configure() {
        install(new JpaPersistModule("jpa"));

        bind(PersistenceLifeCycleManager.class)
            .annotatedWith(PersistService.class)
            .to(PersistenceLifeCycleManagerImpl.class);
        expose(PersistenceLifeCycleManager.class)
            .annotatedWith(PersistService.class);

        bind(new TypeLiteral<GenericDAO<Person, String>>() {})
            .to(new TypeLiteral<PersonDao>() {});
        // How to expose this??

        bind(AddressDao.class).asEagerSingleton();
        expose(AddressDao.class);
        bind(EntityLocator.class).asEagerSingleton();
        expose(EntityLocator.class);
    }
}

尝试运行此命令时出现 ConfigurationException:

com.google.inject.ConfigurationException: Guice configuration errors:

1) Unable to create binding for com.guicetest.server.dao.PersonDao. It was already configured on one or more child injectors or private modules
   (bound by a just-in-time binding)
  If it was in a PrivateModule, did you forget to expose the binding?
  while locating com.guicetest.server.dao.PersonDao

1 error
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1004)
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:961)
at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1013)
at com.guicetest.server.service.PersonService.getAllPersons(PersonService.java:43)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.google.web.bindery.requestfactory.server.ReflectiveServiceLayer.invoke(ReflectiveServiceLayer.java:182)
at com.google.web.bindery.requestfactory.server.ServiceLayerDecorator.invoke(ServiceLayerDecorator.java:111)
at com.google.web.bindery.requestfactory.server.ServiceLayerDecorator.invoke(ServiceLayerDecorator.java:111)
at com.google.web.bindery.requestfactory.server.ServiceLayerDecorator.invoke(ServiceLayerDecorator.java:111)
at com.google.web.bindery.requestfactory.server.SimpleRequestProcessor.processInvocationMessages(SimpleRequestProcessor.java:463)
at com.google.web.bindery.requestfactory.server.SimpleRequestProcessor.process(SimpleRequestProcessor.java:233)
at com.google.web.bindery.requestfactory.server.SimpleRequestProcessor.process(SimpleRequestProcessor.java:135)
at com.google.web.bindery.requestfactory.server.RequestFactoryServlet.doPost(RequestFactoryServlet.java:133)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at com.google.inject.servlet.ServletDefinition.doService(ServletDefinition.java:263)
at com.google.inject.servlet.ServletDefinition.service(ServletDefinition.java:178)
at com.google.inject.servlet.ManagedServletPipeline.service(ManagedServletPipeline.java:91)
at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:62)
at com.guicetest.server.injector.PersistFilter.doFilter(PersistFilter.java:39)
at com.google.inject.servlet.FilterDefinition.doFilter(FilterDefinition.java:163)
at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:58)
at com.google.inject.servlet.ManagedFilterPipeline.dispatch(ManagedFilterPipeline.java:118)
at com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:113)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1088)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.handler.RequestLogHandler.handle(RequestLogHandler.java:49)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:324)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:843)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:647)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)

Google Guice 用户指南并没有真正帮助我,但我才刚刚开始使用它,所以也许我错过了一些东西,但这真的很简单。

-- 编辑--

MyGuiceServletContextListner.java

public class MyGuiceServletContextListner extends GuiceServletContextListener {

    @Override
    protected Injector getInjector() {
        return Guice.createInjector(new MyServletModule(),
            new PersistModule());
    }

}

MyServletModule.java

public class MyServletModule extends ServletModule {

    @Override
    protected void configureServlets() {
        filter("/*").through(PersistFilter.class);
        bind(ExceptionHandler.class).to(RequestFactoryExceptionHandler.class);
        bind(ServiceLayerDecorator.class).to(MyServiceLayerDecorator.class);
        Map<String, String> params = new HashMap<String, String>();
        params.put("symbolMapsDirectory", "WEB-INF/classes/symbolMaps/");
        serve("/gwtRequest").with(MyRequestFactoryServlet.class, params);
    }
}

GenericDAOImpl.java

public abstract class GenericDAOImpl<E extends AbstractEntity, P> implements GenericDAO<E, P> {

    @Inject
    @PersistService
    private PersistenceLifeCycleManager manager;
    @Inject
    private Provider<EntityManager> em;
    private Class<E> entityClass;

    @SuppressWarnings("unchecked")
    @Transactional
    @Override
    public P create(E entity) { ... }

    // etc ...

    @Transactional
    @Override
    public List<E> getAll() {
        List<E> list = null;
        TypedQuery<E> qry = (TypedQuery<E>) getEntityManager()
            .createNamedQuery(getEntityClass().getSimpleName()+".getAll", , getEntityClass());
        if (qry != null) {
            list = qry.getResultList();
        }
        return list;
    }

    @SuppressWarnings("unchecked")
    @Override
    public Class<E> getEntityClass() {
    if (entityClass == null) {
    Type type = getClass().getGenericSuperclass();
        if (type instanceof ParameterizedType) {
            ParameterizedType paramType = (ParameterizedType) type;
            entityClass = (Class<E>) paramType.getActualTypeArguments()[0];
            } else {
                throw new IllegalArgumentException("Could not guess entity class by reflection");
            }
        }
        return entityClass;
    }

}

PersonDao.java

public class PersonDao extends GenericDAOImpl<Person, String> {

    @Transactional
    public Person getPersonByEmailId(String emailId) { ... }

}

PersonService.java

public class PersonService {

    @Inject
    private Injector injector;

    // ...

    public List<Person> getAllPersons() {
        PersonDao pd = injector.getInstance(PersonDao.class);
        return pd.getAll();
    }

最佳答案

您可以公开 TypeLiteralprivate module :

TypeLiteral<GenericDAO<Person, String>> personDaoTypeLiteral = new TypeLiteral<GenericDAO<Person, String>>() {};
bind(personDaoTypeLiteral).to(PersonDao.class);
expose(personDaoTypeLiteral);

然后在你的PersonService中,您无法获取 PersonDAO 的实例,因为该模块公开了 GenericDAO<Person, String> .

public class PersonService {

    @Inject
    private Injector injector;

    public List<Person> getAllPersons() {
        TypeLiteral<GenericDAO<Person, String>> personDaoTypeLiteral = new TypeLiteral<GenericDAO<Person, String>>() {};
        PersonDao pd = injector.getInstance(Key.get(personDaoTypeLiteral));
        return pd.getAll();
    }
}

请注意,这些类型文字的代码不清楚。您可以使用常量:

public class Literals {
    public static final TypeLiteral<GenericDAO<Person, String>> PERSON_DAO = new TypeLiteral<GenericDAO<Person, String>>() {
    };
}

然后

bind(Literals.PERSON_DAO).to(PersonDao.class);
expose(Literals.PERSON_DAO);

injector.getInstance(Key.get(Literals.PERSON_DAO));

关于java - 在私有(private) Guice 模块中公开通用绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15410615/

相关文章:

java - 向 ArrayList<Integer> 实例添加值只能按顺序完成

java - EntityManager em.remove() 和 em.persist() 未反射(reflect)在同一上下文中,而反射(reflect)了实体中的更改

java - 将 key 注入(inject)MapBinder

testng - 如何在 TestNG 测试类中使用 @Factory 注释和 @Guice

java - Guice:Singleton.class 和@Singleton 的区别

java - 不确定如何使用 Java 泛型解决此问题

java - 许多作家一个读者没有并发

java - 使用 JPA 更新集合时出现问题

java - 为什么我的数据没有持久化?

java - 架构师迫切希望使用 SOAP over JMS