范围原型不起作用

时间:2017-12-13 13:34:21

标签: spring scope prototype config qualifiers

我有以下配置:

@Configuration
public class GameConfig {
    @Bean(name = "redsox")
    public Team getRedSox() {
        return new Team("RedSox");
    }

    @Bean(name = "boston")
    public Team getBoston() {
        return new Team("Boston");
    }

    @Bean @Scope(value="prototype") 
    public Game getGame(@Qualifier("boston") Team t1, @Qualifier("redsox") Team t2) {
        return new Game( t1, t2 );
    }

    @Bean
    GameController gameController(Game g) {
        return new GameController(g);
    }
}
@RestController
@RequestMapping("game")
public class GameController {

    Game game;

    public GameController(Game game) {
        this.game = game;
    }

    @RequestMapping(path = "play", method = RequestMethod.GET)
    public Team play() {
        return game.play();
    }

    @RequestMapping(path = "setHomeTeam", method = RequestMethod.POST)
    public void setHomeTeam(@RequestBody Team t) {
        game.setHomeTeam(t);
    }
}
public class Game {

    private Team homeTeam;
    private Team awayTeam;

    public Game (Team homeTeam, Team awayTeam){
        this.homeTeam = homeTeam;
        this.awayTeam = awayTeam;
    }

    public Team play (){
        Random randomGenerator = new Random();
        // Generate random integers in the range 0..1
        int randomInt = randomGenerator.nextInt(2);
        if (randomInt == 0 )
            return this.homeTeam;
        else
            return this.awayTeam;
    }

    public void setHomeTeam (Team t){
        this.homeTeam = t;
    }

    public void setAwayTeam (Team t){
        this.awayTeam = t;
    }
}
@Getter  @NoArgsConstructor @AllArgsConstructor
public class Team {
    private String name;
}

我希望游戏不要单挑。 但是当我拨打POST请求时http://localhost:8080/game/setHomeTeam 然后我调用GET请求http://localhost:8080/game/play它会记住setHomeTeam。

我找到的唯一解决方案是以另一种方式配置gameController:

@Bean  
@Scope(value="prototype")
GameController gameController(
    @Qualifier("boston") Team t1, 
    @Qualifier("redsox") Team t2
) {
    return new GameController(new Game(t1, t2));
}

但是这会将控制器+游戏创建为非Singletone。 我想只有Game non-Singletone。 有没有更好/更有效的方法?

3 个答案:

答案 0 :(得分:2)

@Bean 
@Scope(value="request",proxyMode = ScopedProxyMode.TARGET_CLASS) 
public Game getGame(@Qualifier("boston") Team t1, @Qualifier("redsox") Team t2) {
    return new Game( t1, t2 );
}

如果我们有界面,我们会使用:ScopedProxyMode.INTERFACES

看看http://www.baeldung.com/spring-bean-scopes 部分" 4.1。请求范围" 注释@RequestScope等同于

@Scope(value="request",proxyMode = ScopedProxyMode.TARGET_CLASS)

或简称@RequestScope

如果类(游戏)是最终的,则此解决方案不可用,因为创建了代理calss。

答案 1 :(得分:2)

实现限定符的更好方法是使用注释 定义2个注释:

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface Redsox {
}

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface Boston {
}
在配置文件中

,更改以下bean:

@Bean @Redsox
public Team getRedSox() {
    return new Team("RedSox");
}

@Bean @Boston
public Team getBoston() {
    return new Team("Boston");
}

@Bean @Scope(value="prototype",proxyMode = ScopedProxyMode.TARGET_CLASS)
public Game getGame(@Boston Team t1, @Redsox Team t2) {
    return new Game( t1, t2 );
}

答案 2 :(得分:0)

另一个选择是在 gameController 中定义:

@Lookup
public  Game getGameBean(){
    return null;
}

以上等效于 context.getBean(Game.class),因为您没有应用程序Spring上下文。 而且您不需要在bean定义中定义 proxyMode