1

我有一个问题,我需要RoomService注入一个 ClassA,我在 ClassA 中发现它工作正常,roomService 的 id 是相同的。

虽然出于某种原因,我需要 roomservice 根据一些输入参数为我创建房间实例,所以我使用下面的配置来实现这一点:

@Configuration
@EnableAspectJAutoProxy
public class Application {

private static ApplicationContext ctx = new AnnotationConfigApplicationContext(Application.class);

    public static ApplicationContext getApplicationContext(){
    return ctx;
}

    @Bean        
    public RoomService roomService(){
        return new RoomService();//Singleton
    }

    @Bean
    @Scope("prototype")
    public AbstractRoom room(AbstractRoom.Mode roomMode){
        RoomService roomService = (RoomService) ctx.getBean(RoomService.class);
        LogUtil.debug("--------from application:" +roomService.id1);//here, I find the id is different every time
        return roomService.newRoom(roomMode);
    }
}

问题是我需要RoomService单身,但我发现在 Application.java 中, ctx.getBean(roomService) 总是返回一个具有不同 id 的不同 bean。Spring不应该重用同一个bean吗?这是为什么?

这是我在 RoomService.java 中创建房间的方法

public AbstractRoom createRoom(String userID,int playerCount,Mode roomMode){

    ApplicationContext ctx =Application.getApplicationContext();
    AbstractRoom room = (AbstractRoom)ctx.getBean(AbstractRoom.class,roomMode);

}

更新:我尝试重用相同的 ctx,但它不起作用。一个提示是,当我运行 tomcat 启动它时,我发现我的构造函数RoomService()被多次调用(我在其中设置了一个断点。)

这是我的 web.xml

 <!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>wodinow</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
    </context-param>

    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

请帮忙!

4

1 回答 1

2

每次检索您的实例时,RoomService您都在创建一个新ApplicationContext实例。但是单例 bean 只保证在ApplicationContext.

ApplicationContext因此,如果您希望 bean 是单例的,则每次检索它时都必须使用相同的实例。

来自 Spring 文档:

单例:(默认)将单个 bean 定义限定为每个 Spring IoC 容器的单个对象实例

更新 1

您可以只调用roomService()您的room()方法来获取房间服务,而无需创建应用程序上下文,并且 Spring 将确保它们是相同的实例,因为它被标记为@Bean具有隐式单例范围。

更新 2

根据更新后的问题,您的代码通常存在以下几个问题:

1.不要ApplicationContext在你的配置类中创建。当您在Tomcat中启动 Spring 应用程序时,Spring 会为您创建应用程序上下文。您只需要告诉 Spring 它应该注册哪些配置类。

2.从您的配置类中删除room()bean 定义。创建房间的方法应该在RoomService. 因此,例如,如果您需要在 Spring MVC 控制器中创建一个新房间,您将在其上注入RoomServiceand callcreateRoom方法。注入的服务将是单例的。例子:

@Controller
@RequestMapping("/rooms")
public class RoomController {

    @Autowired
    private RoomService roomService;

    @RequestMapping(value="/create", method=POST)
    public String createRoom() {
        roomService.createRoom(/* Parameters for room creation */);
        return "redirect:/somelocation";
    }
}

尝试根据这些建议重新编写代码,它应该可以工作。

于 2014-11-02T12:04:16.207 回答