Spring Autowired 和 Builder 注释
Spring Autowired and Builder annotations
我有一个 spring AppUser class,它有一个 @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 相同的默认 friendList 从头开始。
正在 WebController 方法中创建 AppUser:
@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 排序,在正在实例化的 class 中调用 new 或构建并自动装配字段似乎是不好的做法。
我的问题是,如何明智地绕过这个设计?这可能吗?或者我应该停止尝试在我必须创建的新实例中自动装配一个字段吗?或者,有没有一种方法可以让我在命中此端点时自动连接新用户?
提前感谢您的帮助。
朋友列表 class 上下文:
@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 class:
@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 组件。
如果您在控制器中使用构建器创建 AppUser,则需要在控制器中@Autowired FriendList 并在构建器上设置它。
另外一个注意事项如果朋友是动态创建的,为了举例说明,如果一开始你有 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 from here。
我有一个 spring AppUser class,它有一个 @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 相同的默认 friendList 从头开始。
正在 WebController 方法中创建 AppUser:
@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 排序,在正在实例化的 class 中调用 new 或构建并自动装配字段似乎是不好的做法。
我的问题是,如何明智地绕过这个设计?这可能吗?或者我应该停止尝试在我必须创建的新实例中自动装配一个字段吗?或者,有没有一种方法可以让我在命中此端点时自动连接新用户?
提前感谢您的帮助。
朋友列表 class 上下文:
@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 class:
@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 组件。 如果您在控制器中使用构建器创建 AppUser,则需要在控制器中@Autowired FriendList 并在构建器上设置它。
另外一个注意事项如果朋友是动态创建的,为了举例说明,如果一开始你有 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 from here。