自动扫描guice

Leo*_*eon 7 java jersey ioc-container guice

我之前从未使用过guice,我想在一个基于jersey-RS API的示例项目上尝试一下,该项目由service-bean支持.我遵循了这个指南:http://randomizedsort.blogspot.de/2011/05/using-guice-ified-jersey-in-embedded.html并且能够将它带到工作中.我的设置非常简单,通过Guice调用JAX-RS资源,并且有一个注释@Inject并由Guice注入的字段:

@Path("configuration")
@Produces(MediaType.APPLICATION_JSON)
@Singleton
public class ConfigurationResource {

    @Inject
    private ConfigurationService configurationService;
Run Code Online (Sandbox Code Playgroud)

到目前为止一切都那么好,一切都像它应该的那样,除了以下:我使用GuiceServletContextListener进行设置并且必须明确地命名每个组件:

@WebListener
public class GuiceInitializer extends GuiceServletContextListener{
    @Override
    protected Injector getInjector() {
        return Guice.createInjector(new JerseyServletModule() {
            @Override
            protected void configureServlets() {
                //resources
                bind(ConfigurationResource.class);

                //services
                bind(ConfigurationService.class).to(ConfigurationServiceImpl.class);

                // Route all requests through GuiceContainer
                serve("/management/*").with(GuiceContainer.class);
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

我发现显式命名所有依赖项非常不方便.之前我曾使用独立运动衫,它完全能够自动扫描已定义包装中的资源.此外,Spring和CDI能够将实现映射到接口,而无需明确命名它们.

现在问题部分:

  • guice有自动扫描扩展/设置吗?我在互联网上找到了一些,但很难说它们中哪些仍然可用且最新.

  • 有没有其他可能使实现和资源配置更方便?

提前致谢.莱昂

leo*_*eon 10

我不认为Guice已经内置了对Spring框架的组件扫描等内容的支持.但是,在Guice中模拟此功能并不困难.

您只需要编写如下的帮助程序模块

import com.google.inject.AbstractModule;
import org.reflections.Reflections;

import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * To use this helper module, call install(new ComponentScanModule("com.foo", Named.class); in the configure method of 
 * another module class.
 */
public final class ComponentScanModule extends AbstractModule {
    private final String packageName;
    private final Set<Class<? extends Annotation>> bindingAnnotations;

    @SafeVarargs
    public ComponentScanModule(String packageName, final Class<? extends Annotation>... bindingAnnotations) {
        this.packageName = packageName;
        this.bindingAnnotations = new HashSet<>(Arrays.asList(bindingAnnotations));
    }

    @Override
    public void configure() {
        Reflections packageReflections = new Reflections(packageName);
        bindingAnnotations.stream()
            .map(packageReflections::getTypesAnnotatedWith)
            .flatMap(Set::stream)
            .forEach(this::bind);
    }
}
Run Code Online (Sandbox Code Playgroud)

要组件扫描com.foo类包和子包以便携带类@Singleton,请以这种方式使用它:

public class AppModule extends AbstractModule {
   public void configure() {
     install(new ComponentScanModule("com.foo", Singleton.class));
   }
}
Run Code Online (Sandbox Code Playgroud)