如何让@Service类通过new实例化并解决Autowired字段为空问题
解决方案
一、修复UserContext的依赖注入问题
放弃使用@Configurable,采用以下两种更可靠的方式:
方式1:通过Spring管理的RoleFactory创建UserContext
- 给
RoleFactory添加@Component注解,让Spring容器接管它的生命周期; - 在
RoleFactory中通过构造函数注入UserService和所有Role实现类,Spring会自动收集同类型的Bean:
@Component public class RoleFactory { private final UserService userService; private final List<Role> roleList; public RoleFactory(UserService userService, List<Role> roleList) { this.userService = userService; this.roleList = roleList; } public Role getRoleByType(String roleType) { return roleList.stream() .filter(role -> role.getType().equals(roleType)) .findFirst() .orElseThrow(() -> new IllegalArgumentException("无效角色类型")); } public UserContext createUserContext(String roleType) { Role targetRole = getRoleByType(roleType); return new UserContext(userService, targetRole); } }
UserContext改为普通类,通过构造函数接收UserService和Role实例:
public class UserContext { private final UserService userService; private Role currentRole; public UserContext(UserService userService, Role currentRole) { this.userService = userService; this.currentRole = currentRole; } public void executeTargetAction() { currentRole.handleAction(userService); } }
- 控制器中注入
RoleFactory,获取当前用户角色后创建UserContext:
@RestController @RequestMapping("/users") public class UserController { private final RoleFactory roleFactory; public UserController(RoleFactory roleFactory) { this.roleFactory = roleFactory; } @GetMapping("/operate") public ResponseEntity<?> doOperate() { // 从SecurityContextHolder获取当前用户角色 Authentication auth = SecurityContextHolder.getContext().getAuthentication(); UserPrincipal principal = (UserPrincipal) auth.getPrincipal(); String userRole = principal.getRole(); UserContext context = roleFactory.createUserContext(userRole); context.executeTargetAction(); return ResponseEntity.ok().build(); } }
方式2:让Role实现类成为Spring Bean,直接注入UserService
- 给所有
Role实现类(如UserRole)添加@Component注解; - 在
Role实现类中直接注入UserService:
@Component public class UserRole implements Role { private final UserService userService; public UserRole(UserService userService) { this.userService = userService; } @Override public void handleAction() { userService.processUserLogic(); } }
UserContext简化为仅接收Role实例:
public class UserContext { private Role currentRole; public UserContext(Role currentRole) { this.currentRole = currentRole; } public void executeTargetAction() { currentRole.handleAction(); } }
- 控制器中通过
ApplicationContext或RoleFactory获取对应Role实例,创建UserContext。
二、解决直接new UserService的问题
- 彻底删除所有
new UserService()的写法:Service必须由Spring容器管理,所有需要使用UserService的场景按以下方式处理:- 若调用类是Spring管理的(如
@Component、@Controller标记的类),直接通过构造函数注入UserService; - 若调用类不是Spring管理的(如
ClassGetModel),要么给该类添加@Component转为Spring组件,要么在调用它的地方注入UserService,通过构造函数或方法参数传递进去:// 将ClassGetModel转为Spring组件 @Component public class ClassGetModel { private final UserService userService; public ClassGetModel(UserService userService) { this.userService = userService; } // 使用userService的业务方法 }
- 若调用类是Spring管理的(如
- 无需手动编写
UserService的全参构造函数,Spring会自动处理所有依赖的注入,避免参数过多的麻烦。
三、优化状态模式的角色系统
- 所有
Role实现类交由Spring管理,通过@Component标记,Spring会自动收集所有Role实现类并注入到RoleFactory的List<Role>中,无需手动维护角色列表; - 杜绝在非Spring管理类中直接创建Service或Role实例,确保所有依赖都通过Spring容器注入,保证依赖完整性。
内容的提问来源于stack exchange,提问作者Cross
相关产品推荐
相关产品推荐

