繁体   English   中英

Spring Autowired 和 Builder 注释

[英]Spring Autowired and Builder annotations

我有一个 Spring AppUser 类,它有一个 @Autowired 注释字段(FriendList),如下所示:

@Getter
@Setter
@Builder
@Document(collection = "app_users")
@Component
public class AppUser {

  @Id
  @NotBlank(message = ErrorConstants.ANDROID_USER_ACCOUNT_MANAGER_ID_IS_NULL)
  private String androidUserAccountManagerId;

  @NotBlank(message = ErrorConstants.NULL_NAME)
  private String name;

  private Friend bestFriend;

  @Autowired
  @Setter(AccessLevel.NONE)
  private FriendList friendList;

  private boolean manualBestFriendOverride;

  public Optional<Friend> getFriend(String friendName) {
    return friendList.getFriend(friendName);
  }

  public void calculateBestFriend() {
    if (!manualBestFriendOverride) {
      bestFriend = friendList.calculateAndReturnBestFriend();
    }
  }
}

这个想法是每次创建一个新的 AppUser 时,它都会@Autowire 从头开始​​使用相同的默认朋友列表。

AppUser 正在 WebController 方法中创建:

  @PostMapping("/{androidUserAccountManagerId}/setNewAppUser/{appUserName}")
  public void setNewAppUser(
      @NotNull @PathVariable String androidUserAccountManagerId,
      @NotNull @PathVariable @Pattern(regexp = "^[A-z]{2,20}$", message = "Incorrect name format!")
          String appUserName) {
    databaseQueryClass.save(
        AppUser.builder()
            .androidUserAccountManagerId(androidUserAccountManagerId)
            .name(appUserName)
            .build());
  }

但是,当在其他方法中调用friendList 字段时,我收到了一个空指针异常。 本质上,自动装配似乎没有与 AppUser 构建器一起工作。

经过一些阅读后,由于 IoC 和依赖注入由 Spring 排序,因此在正在实例化的类中调用 new 或 build 并自动装配一个字段似乎是不好的做法。

我的问题是,我如何明智地绕过这个设计? 这是可能的吗? 或者我应该停止尝试在我必须创建的新实例中自动装配一个字段? 或者,有没有一种方法可以在遇到此端点时自动连接新用户?

提前感谢您的帮助。

用于上下文的 FriendList 类:

@ToString
@EqualsAndHashCode
@Builder
public class FriendList {

  @NotNull private List<Friend> listOfFriends;

  public Optional<Friend> getFriend(String friendName) {
    return listOfFriends.stream().filter(o -> o.getName().equals(friendName)).findAny();
  }

  public Friend calculateAndReturnBestFriend() {
    if(listOfFriends.isEmpty()){
      return null;
    }

    java.util.Collections.sort(listOfFriends);
    return listOfFriends.get(0);
  }

  public boolean addToFriendList(String friendName) {
    if (getFriend(friendName).isPresent()) {
      return false;
    }
    return listOfFriends.add(
        Friend.builder().name(friendName).meetingDates(new TreeSet<>()).meetUpNumber(0).build());
  }
}

编辑(对不起,我错过了这个上下文......)

我在 AppConfig 类中定义了一个 bean:

@Configuration
public class AppConfig {

  @Bean
  @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
  public FriendList getFriendList() {
    return FriendList.builder().listOfFriends(new ArrayList<>()).build();
  }
}

关于您的@Autowired问题,只要您让 spring 容器为您管理该新 bean,就可以使用新的运算符或构建器。

例如,您可以执行以下操作:

@Configuration
public class AppConfig {
    @Bean
    public FriendList firendList() {
        return FriendList.builder()
                      //...
                    .build());
    }
}

然后像这样使用它: @Import(AppConfig.class)

请注意,只有当FriendList像默认值一样在开始时创建时,上面的内容才有效,此时所有可用信息。 而且它只适用于由 spring 管理的AppUser组件。 如果您在控制器中使用 builder 创建 AppUser,则需要在控制器中 @Autowired FriendList 并将其设置在 builder 上。

另外,如果好友是动态创建的,假设一开始你有 10 个好友,1 小时后你将有另外 10 个好友,你需要查看所有 20 个好友,那么你需要另一种方法。 最简单的方法是将朋友存储在数据库中,每次只获取每个朋友并将它们设置在 AppUser 上。 或者从缓存映射中检索它们。

您也可以在这种情况下使用@Autowired ,但更复杂,您需要直接自动装配好友列表:

@Autowired
private List<Friend> friends;

每个Friend都应该动态创建。 像这样的东西

Friend friend = new Friend(); 
context.registerBean(Friend.class, () -> friend);  //context here is an ApplicationContext type aka Spring Container.

还可以从此处使用ObjectProvider检查此示例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM