范围原型不工作

scope prototype not working

我有以下配置:

@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));
}

但这会将控制器 + 游戏创建为非单音。 我只想拥有非单音游戏。 有没有更好/有效的方法?

@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.

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

实现限定符的更好方法是使用注释 定义 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 );
}

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

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

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

中定义proxyMode