Java springboot:在不同组件之间共享bean
我在bean配置中声明了一个bean,如下所示:Java springboot:在不同组件之间共享bean,java,spring,spring-boot,Java,Spring,Spring Boot,我在bean配置中声明了一个bean,如下所示: @Configuration public class BeanConfig { @Bean public MemberDTO getMemberDTO() { return new MemberDTO(); } } 当用户调用我的服务时,我使用他们提供的用户名和密码调用不同服务的端点以获取用户信息: @Component public class CustomAuthenticationProvider
@Configuration
public class BeanConfig {
@Bean
public MemberDTO getMemberDTO() {
return new MemberDTO();
}
}
当用户调用我的服务时,我使用他们提供的用户名和密码调用不同服务的端点以获取用户信息:
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
private static final Logger LOGGER = LogManager.getLogger(CustomAuthenticationProvider.class);
private @Autowired MemberDTO memberDTO;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String loginGeniuneFailMessage = "";
boolean loginGeniuneFail = false;
try {
String username = authentication.getName();
String password = authentication.getCredentials().toString();
String endPoint = credentialsBaseUrl + "/api/login";
HttpResponse<MemberDTO> response_auth = Unirest.get(endPoint)
.basicAuth(username, password)
.header("Accept", "*/*")
.asObject(MemberDTO.class);
int status_auth = response_auth.getStatus();
if (status_auth == 200) {
if (response_auth.getBody() == null) {
LOGGER.info("account validation - could not parse response body to object");
UnirestParsingException ex = response_auth.getParsingError().get();
LOGGER.error("parsing error: ", ex);
} else {
memberDTO = response_auth.getBody();
}
}
...
} catch (Exception ex) {
...
}
}
@组件
公共类CustomAuthenticationProvider实现AuthenticationProvider{
私有静态最终记录器Logger=LogManager.getLogger(CustomAuthenticationProvider.class);
private@Autowired MemberDTO至MemberDTO;
@凌驾
公共身份验证(身份验证)引发AuthenticationException{
字符串logingenefailmessage=“”;
布尔logingeninefail=false;
试一试{
字符串username=authentication.getName();
字符串密码=authentication.getCredentials().toString();
字符串endPoint=credentialsBaseUrl+“/api/login”;
HttpResponse response\u auth=Unirest.get(端点)
.basicAuth(用户名、密码)
.header(“接受”、“*/*”)
.A对象(成员到类);
int status_auth=response_auth.getStatus();
如果(状态_auth==200){
if(response_auth.getBody()==null){
info(“帐户验证-无法将响应主体解析为对象”);
UnirestParsingException ex=response_auth.getParsingError().get();
LOGGER.error(“解析错误:”,ex);
}否则{
memberDTO=response_auth.getBody();
}
}
...
}捕获(例外情况除外){
...
}
}
我希望将用户信息存储在memberDTO中,并在其他组件的其他位置使用memberDTO,而不是每次调用登录API:
@Component
public class MemberLogic {
private @Autowired MemberDTO memberDTO;
public ResponseEntity<?> processMemberInformation(WrapperDTO wrapperDTO, BindingResult result) {
if (result.hasFieldErrors()) {
String errors = result.getFieldErrors().stream()
.map(p -> p.getDefaultMessage()).collect(Collectors.joining("\n"));
return ResponseEntity.badRequest().body("An error occured while trying to persist information: " + errors);
}
String name = memberDTO.getName();
...
}
}
@组件
公共类成员逻辑{
private@Autowired MemberDTO至MemberDTO;
公共响应属性processMemberInformation(WrapperDTO WrapperDTO,BindingResult){
if(result.hasfielders()){
String errors=result.getFieldErrors().stream()
.map(p->p.getDefaultMessage()).collect(收集器.joining(“\n”));
return ResponseEntity.badRequest().body(“尝试持久化信息时出错:“+错误”);
}
String name=memberDTO.getName();
...
}
}
现在的问题是“memberDTO.getName()”返回null,即使该值是从CustomAuthenticationProvider中的初始API调用设置的
我的问题是:为什么这不起作用?这是解决类似问题的最佳方法吗
谢谢
我的问题是:为什么这不起作用?这是解决类似问题的最佳方法吗
这不起作用,因为Java使用按值传递语义而不是按引用传递语义。这意味着语句memberDTO=response\u auth.getBody();
实际上不会使Spring容器开始指向response\u auth.getBody()返回的memberDTO
。它仅使CustomAuthenticationProvider
中的memberDTO
引用指向响应中的对象。Spring容器仍继续引用原始memberDTO
对象
解决此问题的一种方法是定义一个可用于与DTO
实例交互的DAO
类,而不是直接创建DTO
bean:
@Configuration
public class BeanConfig {
@Bean
public MemberDAO getMemberDAO() {
return new MemberDAO();
}
}
CustomAuthenticationProvider
然后可以使用:MemberDAO.setMemberDTO(response_auth.getBody());在MemberDAO
中设置MemberDTO
最后,MemberLogic
可以访问MemberDTO
作为String name=memberDAO.getMemberDTO().getName();
注意:与从MemberDAO
返回MemberDTO
不同,MemberDAO
可以定义一个名为getName
的方法,该方法从MemberDTO
中提取名称并返回它。(告诉不要问原则)。也就是说,正如评论中所建议的,最佳做法是使用SecurityContext
存储用户信息
我的问题是:为什么这不起作用?这是解决类似问题的最佳方法吗
这不起作用,因为Java使用按值传递语义而不是按引用传递语义。这意味着语句memberDTO=response\u auth.getBody();
实际上不会使Spring容器开始指向response\u auth.getBody()返回的memberDTO
。它仅使CustomAuthenticationProvider
中的memberDTO
引用指向响应中的对象。Spring容器仍继续引用原始memberDTO
对象
解决此问题的一种方法是定义一个可用于与DTO
实例交互的DAO
类,而不是直接创建DTO
bean:
@Configuration
public class BeanConfig {
@Bean
public MemberDAO getMemberDAO() {
return new MemberDAO();
}
}
CustomAuthenticationProvider
然后可以使用:MemberDAO.setMemberDTO(response_auth.getBody());在MemberDAO
中设置MemberDTO
最后,MemberLogic
可以访问MemberDTO
作为String name=memberDAO.getMemberDTO().getName();
注意:与从MemberDAO
返回MemberDTO
不同,MemberDAO
可以定义一个名为getName
的方法,该方法从MemberDTO
中提取名称并返回它。(告诉不要问原则)。也就是说,正如评论中所建议的,最佳做法是使用SecurityContext
来