Mik*_*kov 7 java spring design-patterns dependency-injection anti-patterns
问题有点夸夸其谈.我和同事就以下模式发生了争执:
@Component
public class MetaService {
public static UserService userService;
public static GroupService groupService;
public static PermissionService permissionService;
// ...more fields
@Autowired
public MetaService(UserService userService,
GroupService groupService
PermissionService permissionService) {
MetaService.userService = userService;
MetaService.groupService = groupService;
MetaService.permissionService = permissionService;
}
}
Run Code Online (Sandbox Code Playgroud)
基本上,MetaService
是多个Spring bean @Service
类的入口点/包装器.而且还有一个类似于bean类的MetaDao
包装器@Repository
:
@Component
public class MetaDao {
public static UserDao userDao;
public static GroupDao groupDao;
public static PermissionDao permissionDao;
// ...more fields
@Autowired
public MetaDao(UserDao userDao,
GroupDao groupDao,
PermissionDao permissionDao) {
MetaDao.userDao = userDao;
MetaDao.groupDao = groupDao;
MetaDao.permissionDao = permissionDao;
}
}
Run Code Online (Sandbox Code Playgroud)
拥有这样一个Meta类的想法是通过为调用和方法提供简洁的API来减少代码库@RestController
和@Service
类,例如:@Service
@Repository
@RestController
public class UserController {
@PostMapping
public UserCreateResponse createUser(UserCreateRequest request) {
MetaService.userService.createAndReturn(userEntity);
// other service calls
}
}
Run Code Online (Sandbox Code Playgroud)
换句话说,这是@Autowired
在每个@Service
内部都有字段/构造函数的替代@Controller
方法.在我看来,这种方法大大减少了样板重复代码.
好吧,我的同事们说:这种方法使代码更难理解/维护,因为@Service
在一个地方组合组件会隐藏使用它们的其他组件的依赖模型.换句话说,如果有为UserController
类声明的字段.快速找出哪些组件UserController
取决于它会更容易.另外,模拟这样的依赖进行单元测试更加困难.而这种方法最重要的是超反模式.虽然我同意嘲笑部分,但其他一切对我来说都是荒谬的.
问题是,这真的是一种反模式吗?
关于OOP的原则,我发现通过public static
属性甚至final
关键字来暴露分组服务是一个不好的原则。我认为这种方法增加了复杂性:如果要添加更多 DAO/服务怎么办?- 那么你将被迫扩大MetaDao
班级规模MetaSerice
。
通过这个外观暴露这些服务,另一个不必要的层将允许真正不需要的UserController
使用和服务 - 有必要吗?touch
它破坏了封装。使用这种广泛使用的方法:
@RestController
public class UserController {
@Autowired
private final UserService userService;
// ...
}
Run Code Online (Sandbox Code Playgroud)