当前位置: 首页 > 面试题库 >

在独立应用程序中使用Jersey的依赖项注入

慕凌龙
2023-03-14
问题内容

我在这里有一个界面

interface Idemo{
  public int getDemo(int i);
}

这是一种实现

class DemoImpl implements Idemo{
  @Override
  public int getDemo(int i){
    return i+10;
  }
}

并且有一类依赖于Idemo

class Sample{
  @Inject
  Idemo demo;

  public int getSample(int i){
    return demo.getDemo(i);
  }
}

现在说我要测试Sample类

public class SampleTest extends JerseyTest {
  @Inject
  Sample s;

  @Override
  protected Application configure() {
    AbstractBinder binder = new AbstractBinder() {
      @Override
      protected void configure() {
        bind(Demo.class).to(Idemo.class);
        bind(Sample.class).to(Sample.class); //**doesn't work**
      }
    };
    ResourceConfig config = new ResourceConfig(Sample.class);
    config.register(binder);
    return config;
  }
  @Test
  public void test_getSample() {
    assertEquals(15, s.getSample(5)); //null pointer exception
  }
}

这里没有创建Sample实例,并且s保持为null。我想这是因为当执行到达指定绑定的行时,已经创建了该测试类。但是我不确定。使用Spring
Autowired而不是jersey CDI相同的作品

如果Sample是资源/控制器类,那么测试框架可以创建它的实例而无需注入它,但是是否可以使用Jersey DI测试其他任何非Web类呢?


问题答案:

它与Spring兼容的原因是测试类由Spring容器通过使用进行管理@RunWith(SpringJUnit4ClassRunner.class)。运行程序会将所有托管对象注入测试对象。JerseyTest不以这种方式进行管理。

如果需要,您可以创建自己的运行程序,但是您需要稍微了解一下HK2(Jersey的DI框架)的工作方式。看一下文档。一切都围绕着ServiceLocator。在独立环境中,您可能会看到类似的内容来引导DI容器

ServiceLocatorFactory factory = ServiceLocatorFactory.getInstance();
ServiceLocator locator = factory.create(null);
ServiceLocatorUtilities.bind(locator, new MyBinder());

然后获得服务,做

Service service = locator.getService(Service.class);

在测试类的情况下,我们不需要获得对服务对象的任何访问权限,我们可以简单地使用注入测试对象ServiceLocator

locator.inject(test);

上面test是在自定义运行器中传递给我们的测试类实例。这是自定义运行器的示例实现

import java.lang.annotation.*;
import org.glassfish.hk2.api.*;
import org.glassfish.hk2.utilities.*;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.*;

public class Hk2ClassRunner extends BlockJUnit4ClassRunner {

    private final ServiceLocatorFactory factory = ServiceLocatorFactory.getInstance();
    private Class<? extends Binder>[] binderClasses;

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

        public Class<? extends Binder>[] value();
    }

    public Hk2ClassRunner(Class<?> cls) throws InitializationError {
        super(cls);
        Binders bindersAnno = cls.getClass().getAnnotation(Binders.class);
        if (bindersAnno == null) {
            binderClasses = new Class[0];
        }
    }

    @Override
    public Statement methodInvoker(FrameworkMethod method, final Object test) {
        final Statement statement = super.methodInvoker(method, test);
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                ServiceLocator locator = factory.create(null);
                for (Class<? extends Binder> c : binderClasses) {
                    try {
                        ServiceLocatorUtilities.bind(locator, c.newInstance());
                    } catch (InstantiationException | IllegalAccessException ex) {
                        throw new RuntimeException(ex);
                    }
                }
                locator.inject(test);
                statement.evaluate();
                locator.shutdown();
            }
        };
    }
}

在运行程序中,methodInvoker每个测试方法都会调用,因此我们正在为每个调用的测试方法创建一组新的对象。

这是一个完整的测试案例

@Binders({ServiceBinder.class})
@RunWith(Hk2ClassRunner.class)
public class InjectTest {

    public static class Service {

        @Inject
        private Demo demo;

        public void doSomething() {
            System.out.println("Inside Service.doSomething()");
            demo.doSomething();
        }   
    }

    public static class Demo {
        public void doSomething() {
            System.out.println("Inside Demo.doSomething()");
        }
    }

    public static class ServiceBinder extends AbstractBinder {
        @Override
        protected void configure() {
            bind(Demo.class).to(Demo.class);
            bind(Service.class).to(Service.class);
        }
    }


    @Inject
    private Service service;

    @Test
    public void testInjections() {
        Assert.assertNotNull(service);
        service.doSomething();
    }
}


 类似资料:
  • 问题内容: 我正在寻找在 独立的(桌面/秋千)* 应用程序中使用 Spring的 示例或教程,我进行了很多搜索,但找不到有用的东西,所有示例和教程均适用于Web应用程序,请告知。 * 问题答案: 使用maven创建独立应用程序,如下所示: 使用Maven创建独立的应用程序 将applicationContext放在类路径中,并按如下所示将其加载到主类中: 在此处查看全文: http://www.d

  • 现在假设我们想要使用 Spark API 写一个独立的应用程序。我们将通过使用 Scala(用 SBT),Java(用 Maven) 和 Python 写一个简单的应用程序来学习。 我们用 Scala 创建一个非常简单的 Spark 应用程序。如此简单,事实上它的名字叫 SimpleApp.scala: /* SimpleApp.scala */ import org.apache.spark.S

  • 例如,Foos的资源可能如下所示: 对于酒吧:

  • 问题内容: 我正在考虑开发由两部分组成的桌面应用程序: 用户界面(例如Java应用) 后端Node.js服务器 2个部分通过插座连接。不要问为什么我知道这很奇怪。 我将希望能够为客户提供带有安装程序的应用程序。我不希望用户必须自己安装Node.js。 有没有一种方法可以独立安装Node.js服务器,即无需在系统上全局安装Node.js。 对于任何(Windows,Linux,Mac OS X …)

  • 从零开始,没有任何以前的Jersey 1.x知识,我很难理解如何在我的Jersey 2.0项目中设置依赖注入。 我也知道HK2在Jersey 2.0中可用,但我似乎找不到有助于Jersey 2.0集成的文档。 我可以让容器启动并提供我的资源,但是当我将@inject添加到MyService时,框架就会抛出一个异常: 我的starter项目可在github:https://github.com/do

  • 问题内容: 这是我的代码: 为什么不起作用?我懂了。在独立的应用程序中可以使用自动装配吗? 问题答案: Spring在独立应用程序中工作。您使用错误的方式来创建Spring bean。这样做的正确方法是: 在第一种情况下(问题中的那个),您将自己创建对象,而不是从Spring上下文中获取对象。因此,Spring没有机会获得依赖关系(这会导致)。 在第二种情况(此答案中的一种)中,您是从Spring