Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java springboot:在不同组件之间共享bean_Java_Spring_Spring Boot - Fatal编程技术网

Java springboot:在不同组件之间共享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

我在bean配置中声明了一个bean,如下所示:

@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