使用new创建对象时Spring注入bean null,如何解决?

时间:2014-11-02 10:15:00

标签: java spring dependency-injection refactoring inversion-of-control

我有一个应用程序,现在我正在尝试使用Spring来重构它,并且在使用new创建对象时遇到问题,但我不知道如何解决它。

这是真实情况:

我有Controller,需要CommandService个实例,而CommandService需要RoomService才能创建AbstractRoom个实例以放入RoomService实例的hashmap。

我有两种AbstractRoom名为RoomA,RoomB,它们来自AbstractRoomAbstractRoom需要GameService个实例。

我会将一个param从commandService传递给roomService,以便roomservice可以创建一个正确的房间实例。

现在的问题是,我使用roomservice.createRoom来创建一个使用new来做这件事的房间。所以Spring无法将GameService注入我的抽象室,因此我有一个null gameService。

但是CommandService会从用户那里获得一些输入并委托给RoomService来为它创建一个房间,所以在用户输入内容之前我不知道会创建哪个房间实例:

CommandService.java:

    private String handleCreateRoom(String userID, int playerCount,
        Mode roomMode) {
        ...
        AbstractRoom theNewRoom=roomService.createRoom(userID, playerCount, roomMode);
        ...        
        }

以下是我如何从RoomService.java创建createRoom:

public AbstractRoom createRoom(String userID,int playerCount,Mode roomMode){
    AbstractRoom room = newRoom(roomMode);// create a room based on the roomMode
    room.initRoom(userID, playerCount);// init the room
    userToRoom.put(userID, room.getRoomNum());//some context 
    return room;
}


public AbstractRoom newRoom(AbstractRoom.Mode roomMode) {
    Integer randomNumObject;
    AbstractRoom newRoom;
    .....
    if(roomMode.equals(Mode.AUTO_JUDGE)||roomMode.equals(Mode.PLAYER_JUDGE)){//wodi room

           newRoom=new RoomA(randomNumObject,roomMode);//RoomA
    }
    ....
    else{//RoomB
        newRoom=new RoomB(randomNumObject);
    }

    roomMap.put(randomNumObject, newRoom);//some context 
    return newRoom;
}

这是我的AbstractRoom.java

public abstract class AbstractRoom {

        protected Mode roomMode;    
        @Autowired
        protected GameService gameService;
        .....
}

我的配置是:

@Configuration
@EnableAspectJAutoProxy
public class Application {
    @Bean
    public CommandService commandService(){
        return new CommandService();//singleton
    }
    @Bean
    public RoomService roomService(){
        return new RoomService();//singleton
    }       
    @Bean
    public GameService gameService(){
        return new GameService();//singleton
    }

1 个答案:

答案 0 :(得分:0)

最后,我通过将AbstractRoom作为带有scope = prototype的bean来解决这个问题,并从roomservice bean返回实例。

@Configuration
@EnableAspectJAutoProxy
public class Application {      
    @Bean
    public CommandService commandService(){
        return new CommandService();
    }

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

    @Bean
    public GameService gameService(){
        return new GameService();
    }

    @Bean
    @Scope("prototype")
    public AbstractRoom room(AbstractRoom.Mode roomMode){
        RoomService roomService = roomService();
        return roomService.newRoom(roomMode);
    }

在RoomService.java中,注入一个ApplicationContext,然后从容器中获取Room。

public class RoomService {

    @Autowired
    private ApplicationContext ctx;

    public AbstractRoom createRoom(String userID,int playerCount,Mode roomMode){
        AbstractRoom room = (AbstractRoom)ctx.getBean(AbstractRoom.class,roomMode);
    }
}