【问题标题】:Jersey RESTful: Spring bean creation managementJersey RESTful:Spring bean 创建管理
【发布时间】:2013-11-27 20:26:15
【问题描述】:

我有以下 Jersey RESTful Web 服务类来服务 HTTP 请求/响应:

@Path("/customer")
public class CustomerService {

    private static ApplicationContext context;
    public static CustomerJDBCTemplate dbController;

    static {
        context = new ClassPathXmlApplicationContext("beans.xml");
        dbController = (CustomerJDBCTemplate) context.getBean("customerJDBCTemplate");
    }

        //methods for GET/POST requests ...
}

这里我使用静态变量dbController 作为我的DAO 对象。因为我希望在我的应用程序中只有一个dbController 实例,所以我给它一个静态属性,以便所有Jersey 类可以共享相同的dbController 实例。例如,如果我有另一个使用 DAO 的 Jersey 类,那么我可以将它用作 CustomerService.dbController.create() 之类的东西。但我想知道这是否是在 Jersey 类中实例化 DAO bean 的正确和最合适的方法,因为如果未调用 Path: /customer 处的资源,则不会实例化 DAO bean。

我也可以在另一个 Jersey 类中重复上述 bean 实例化步骤:

@Path("/another")
public class AnotherService {

    private static ApplicationContext context;
    public static  CustomerJDBCTemplate dbController;

    static {
        context = new ClassPathXmlApplicationContext("beans.xml");
        dbController = (CustomerJDBCTemplate) context.getBean("customerJDBCTemplate");
    }

        //methods for GET/POST requests ...
}

我的问题是:这会创建与第一个不同的实例吗?还是CustomerService.dbControllerAnotherService.dbController 指的是同一个对象?

如果我想在非 Jersey 类(例如,服务层类)中使用第一个 DAO 对象 CustomerService.dbController,我是否应该使用第一种方法仅在一个 Jersey 类中创建 bean 作为公共静态变量和在所有使用dbController 的类中引用它?这里的最佳做法是什么?

【问题讨论】:

    标签: java spring rest dependency-injection jersey


    【解决方案1】:

    最佳做法是使用@Inject 而不是static。 Jersey 有自己的注入机制

    public class MyApplication extends ResourceConfig {
    public MyApplication() {
        register(new FacadeBinder());
    

    注册为单身人士

    public class FacadeBinder extends AbstractBinder {
    
      @Override
      protected void configure() {
        bind(MyManager.class).to(MyManager.class);
      }
    }
    

    然后在您的资源端点中,您可以使用已注册的类:

    @Path("/jersey")
    public class MyEndpoint implements MyInterface {
      @Inject
      MyManager myManager;
    

    或者您可以与其他一些注入框架集成,例如 Guice 或 Spring。

    【讨论】:

    • 谢谢。在我的示例中,dbController 是通过 Spring bean 配置文件注入的。我将其设为静态的原因是我想在另一个类中重用相同的 dbController bean,以便这个 DAO bean 在我的应用程序中只有一个实例。如果我使用@Inject注解,就相当于我的Spring bean注入。那么有什么区别呢?
    • 区别在于你的类中的static代码。例如,如果您编写单元测试,则需要初始化 Spring 上下文才能使其工作,这非常耗时。另一个重要的事情是代码中的字符串文字。他们在大型项目中容易出错。
    【解决方案2】:

    首先,如果你打算使用 Jersey+Spring,我认为 jersey-spring 集成是worth checking out

    此外,使用任何依赖注入/控制反转框架的全部意义在于管理“bean”的生命周期和相互依赖关系。 DI/IoC 库和框架可以避免这种静态/依赖关系的噩梦,并帮助您构建可测试、可扩展的应用程序。

    This part of the Spring reference documentation 应该让事情更清楚。 默认,Spring 为您创建和管理单例 bean(一个实例由您的应用程序中的所有人共享)。查看beans scopes documentation

    一般经验法则:直接注入/使用应用程序上下文有点代码味道(特别是如果您硬编码上下文文件的名称!)。

    如果您正在寻找最佳实践,the Jersey+Spring example should help you

    【讨论】:

    • 感谢您的评论和 Jersey-Spring 指南的链接。我通读了链接中的示例代码。我没有使用应用程序上下文 getBean() 方法找到任何 bean 实例化。那么示例代码中实例化的bean在哪里呢?是不是通过class MyApplication extends ResourceConfigMyApplication需要在web.xml中注册?
    • Bean 实例化由 Spring 完成。您只需向 Spring 描述您的应用程序上下文(使用 JavaConfig 或 XML 文件),然后 Spring 将处理其余部分(即实例化 + 注入)。请注意,getBean 仅从应用程序上下文中检索现有 bean,这意味着它已经被实例化。因此,在这种情况下,示例应用程序使用 XML file 注册 bean 定义。
    • 我知道 bean 定义在 XML 文件中。但是从示例代码来看,没有像ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml") 这样的Java 代码来实际实例化source code 中的bean。所以我想知道示例中的 applicationContext 是在哪里实例化的。
    • 谢谢布赖恩。 web.xml 真的是我错过的东西。它隐藏得如此之深,以至于我找不到 bean 实例化 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-23
    • 2014-09-28
    • 1970-01-01
    • 2014-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多