我有一些在Spring Boot应用程序中通用的数据对象-一个是登录的employee
对象,另一个是category
。我创建了一个@Component
类,其中包含这些都是静态变量。这样,我什至不必为其自动接线。它们可以像CurrentContext.employee
一样直接在控制器中使用。
@Component
public final class CurrentContext {
public static Category currentCategory;
public static Employee employee;
@Autowired
private CategoryService categoryService;
@Autowired
private EmployeeService employeeService;
@EventListener
public void onApplicationEvent(ContextRefreshedEvent event) {
currentCategory = categoryService.getCategory();
}
@EventListener
public void onLoginSuccess(InteractiveAuthenticationSuccessEvent event) {
employee = employeeService.getEmployeeByUserId(((MyUserDetails) event.getAuthentication().getPrincipal()).getUserId());
}
}
这是正确的方法吗?请建议是否有更好的方法来处理共享数据
修改
一些背景-我需要当前登录的employee
和一个category
这对所有员工都是通用的。因此,我在控制器中autowired
employeeService
和categoryService
,并使用它们来获取数据。几乎所有控制器方法都需要它们,因此,我想创建一个此类的bean,以便直接在控制器中使用它们,并保存频繁的数据库调用。
答案 0 :(得分:0)
通常,我们仅将与跨领域关注点相关的依赖项(即整个应用程序中的依赖项,例如安全性,日志记录,事务内容,时间提供者等)放在静态字段中。
通过以静态方式访问此类依赖关系,我们无需在对象之间通过方法参数/构造函数将它们传递给对象,这将使API更加整洁,而不会产生此类噪音(BTW。这称为{{ 1}}。)
您的Ambient Context Pattern
对象很可能属于此类型,因此可以以静态方式访问它。但是由于它们的作用域是每个会话的,所以您不能简单地将其放在类的静态字段中。如果是,那么您在所有会议中总是得到同一名员工。相反,您必须以某种方式将其存储在会话范围内的对象中(例如Employee
)。然后,在开始处理Web请求时,可以从会话中获取该请求,然后将其放入封装在“ ContextHolder”对象内的HttpSession
中。然后,您以静态方式访问该“ ContextHolder”。
听起来很复杂又可怕吗?不用担心,因为Spring Security已经为您实现了这些东西。您需要做的是customize Authentication#getPrincipal()
or extend default Authentication
包含您的ThreadLocal
。然后使用Employee
对于您的SecurityContextHolder.getContext().getAuthentication()
来说,如果它们不是跨领域的关注点,并且不是应用程序范围,那么使singleton bean获得其值是一种更好的OOP设计。
currentCategory
然后将@Component
public final class CurrentCategoryProvider {
@Autowired
private CategoryService categoryService;
public Category getCurrentCategory(){
//or cache the value to the an internal properties depending on your requirements
return categoryService.getCategory();
}
}
注入需要访问CurrentCategoryProvider
的bean。