1

ClassA を注入する必要があるという問題があり、ClassARoomServiceで見つかったのは正常に動作し、roomService の ID は同じです。

何らかの理由で、入力パラメーターに基づいてルームインスタンスを作成するためにルームサービスが必要なので、以下の構成を使用してこれを実現します。

@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 を再利用しようとしましたが、機能しません。ヒントの 1 つは、RoomService()Tomcat を実行して開始するときに、コンストラクターが数回呼び出されていることを発見したことです (ブレークポイントを入れました)。

これが私の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

したがって、Bean をシングルトンにしたい場合は、Bean をApplicationContext取得するたびに同じインスタンスを使用する必要があります。

春のドキュメントから:

singleton: (デフォルト) Spring IoC コンテナーごとに単一の Bean 定義を単一のオブジェクト インスタンスにスコープします。

更新 1

メソッドを呼び出すだけroomService()で、アプリケーション コンテキストを作成せずにルーム サービスを取得できます。Spring は、暗黙的なシングルトン スコープを持つものroom()としてマークされているため、それらが同じインスタンスであることを保証します。@Bean

更新 2

ここでの更新された質問に基づいて、一般的なコードのいくつかの問題があります。

1.ApplicationContext構成クラスで作成しないでください。TomcatでSpring アプリケーションを起動すると、Springによってアプリケーション コンテキストが作成されます。どの構成クラスを登録する必要があるかをSpringに伝える必要があるだけです。

2.room()構成クラスから Bean 定義を削除します。ルームの作成方法は にあるはずですRoomService。たとえば、Spring MVC コントローラーで新しいルームを作成する必要がある場合は、メソッドを注入してメソッドRoomServiceを呼び出しますcreateRoom。挿入されたサービスはシングルトンになります。例:

@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 に答える