【问题标题】:@Autowired dependency has null members@Autowired 依赖有空成员
【发布时间】:2021-11-13 09:15:31
【问题描述】:

我的配置类:

@Configuration
public class TimeOutConfig {

    @Value("${value1}")
    private int value1;

    @Value("${value2}")
    private int value2;

    @Bean()
    User boTimeOut() {
        System.out.println("In BOTimeOutConfig");
        BeanTest b1 = new BeanTest(value1, value2);
        User u1 = new User(b1);
        return u1;
    }


    @Value("${value3}")
    private int value3;

    @Value("${value4}")
    private int value4;

    @Bean(name = "BSETimeout")
    User getBSEUser() {
        System.out.println("In BSETimeOutConfig");
        User u2 = new User( new BeanTest(value3, value4));
        return u2;
    }

}

BeanTest 类:

@Component
public class BeanTest {

    private int v1;
    private int v2;

   BeanWebClient b1;

    public BeanTest(){}

    public BeanTest(int v1, int v2){
        this.v1=v1;
        this.v2=v2;
        beanWebClient();
        
    }
    public BeanWebClient beanWebClient() {
        //System.out.println("In BeanTest class beanWebClient() method execution v1 and v2: "+v1+v2);
        b1 = new BeanWebClient(v1,v2);
        System.out.println("In BeanTest class beanWebClient() method execution v1 and v2: "+b1.getV1()+" "+b1.getV2());
        return b1;
    }

    public void message()
    {
        b1.webClientMessage();
        //System.out.println("V1= "+v1+" V2= "+v2);
    }
}

BeanWebClient 类:

@Component
public class BeanWebClient {

    private int v1;
    private int v2;
    public BeanWebClient(int v1, int v2){

        this.v1=v1;
        this.v2=v2;
        System.out.println("Received from BeanTest "+v1+" "+v2);
    }

    public BeanWebClient(){

    }

    public int getV1() {
        return v1;
    }
    public int getV2() {
        return v2;
    }

    public void webClientMessage(){

        System.out.println("In BeanWebClient class, printing from autowired dependency "+v1+" "+v2);
    }

}

我的用户类:

@Component
public class User {

    @Autowired
    private BeanTest beanTest;



    public User(BeanTest beanTest){

        this.beanTest=beanTest;
    }

    public void message()
    {

        beanTest.message();
    }


    public User() {

        //System.out.println("user create... hashCode :" + this.hashCode());
    }
}

最后,我的服务类:

@Service
public class BeanService {

    @Autowired
    @Qualifier("boTimeOut")
    private User boUser;

    @Autowired
    @Qualifier("BSETimeout")
    private User bseUser;

    public void printBO()
    {
        boUser.message();

    }
    public void printBSE()
    {
        bseUser.message();
    }

}

我试图了解组件和自动装配依赖项在 Spring Boot 中是如何工作的。在我的 User 类中,自动装配的 BeanTest 类在配置期间被初始化——所有必要的打印语句都被执行。但是当我调用 Service 类的函数时,自动装配的 User 依赖项对于 beanTest 及其成员为 null。与此相反,当我在我的 User 类中创建 BeanTest 对象时,一切都按预期工作。这就是我的意思:

@Component
public class User {

    BeanTest beanTest;



    public User(BeanTest beanTest){

        this.beanTest=beanTest;
    }

    public void message()
    {

        beanTest.message();
    }


    public User() {

        //System.out.println("user create... hashCode :" + this.hashCode());
    }
}

我有点理解在 User 类中自动装配的 bean 是从容器中获取的,它是 null。由于我在我的服务类中自动装配特定的用户依赖项,我不明白为什么它不起作用。 有人可以解释一下是否以及如何正确地将 BeanTest 类自动连接到 User 类中。 抱歉,有这么多代码文件。

输出 这是我在没有@Autowire 的情况下手动创建 BeanTest 对象时得到的输出

In BOTimeOutConfig
Received from BeanTest 10 20
In BeanTest class beanWebClient() method execution v1 and v2: 10 20
In BSETimeOutConfig
Received from BeanTest 30 40
In BeanTest class beanWebClient() method execution v1 and v2: 30 40
2021-11-13 14:37:58.161  WARN 404383 --- [           main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2021-11-13 14:37:58.613  INFO 404383 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2021-11-13 14:37:58.622  INFO 404383 --- [           main] c.paytmmoney.errordb.ErrordbApplication  : Started ErrordbApplication in 4.04 seconds (JVM running for 4.379)
2021-11-13 14:38:07.768  INFO 404383 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-11-13 14:38:07.768  INFO 404383 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2021-11-13 14:38:07.769  INFO 404383 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
In /test method
In BeanWebClient class, printing from autowired dependency 10 20
In /test method
In BeanWebClient class, printing from autowired dependency 30 40

当我自动装配 BeanTest 类时,这是输出:

In BOTimeOutConfig
Received from BeanTest 10 20
In BeanTest class beanWebClient() method execution v1 and v2: 10 20
In BSETimeOutConfig
Received from BeanTest 30 40
In BeanTest class beanWebClient() method execution v1 and v2: 30 40
2021-11-13 14:40:36.072  WARN 404724 --- [           main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2021-11-13 14:40:36.585  INFO 404724 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2021-11-13 14:40:36.596  INFO 404724 --- [           main] c.paytmmoney.errordb.ErrordbApplication  : Started ErrordbApplication in 4.353 seconds (JVM running for 4.75)
2021-11-13 14:40:45.081  INFO 404724 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-11-13 14:40:45.081  INFO 404724 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2021-11-13 14:40:45.082  INFO 404724 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
In /test method
2021-11-13 14:40:45.204 ERROR 404724 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause

java.lang.NullPointerException: null
    at com.paytmmoney.errordb.repository.BeanTest.message(BeanTest.java:42) ~[main/:na]
    at com.paytmmoney.errordb.repository.User.message(User.java:22) ~[main/:na]
    at com.paytmmoney.errordb.service.BeanService.printBO(BeanService.java:21) ~[main/:na]

我正在使用休息控制器来调用服务类中的函数。
谢谢!!!

【问题讨论】:

  • 您正在混合字段注入 (@Autowired) 和构造函数注入。你的项目看起来很乱。您能否在 Github 上提供一个可重现的最小示例?
  • @SimonMartinelli 我在这里添加了代码 - github.com/Aditya149349/StackOverflow 非常感谢您的帮助!
  • 有很多问题。为什么要在服务中使用限定符?
  • 我必须同意@SimonMartinelli,您的代码很难遵循。您在TimeOutConfig 文件中创建User bean,但随后您还使用@Component 注释User 类(实际上是“创建”一个bean)。此外,问题似乎并不在于您的 beanTest 在您的 User 对象中为空。问题似乎出在BeanTest.message() 方法中。 b1 很可能为空。您是否尝试过从 BeanTestBeanWebClientUser 类中删除 @Component 注释,因为它们似乎与您正在尝试做的事情无关。
  • 抱歉,没有,因为我不知道预期会发生什么,因为您没有提供有关代码的上下文。

标签: java spring-boot javabeans autowired


【解决方案1】:

鉴于您在TimeOutConfig 中自行创建BeanTestUser 实例,请删除BeanTestBeanWebClientUser 中的所有@Component@Autowired 注释,如下所示:

public class BeanTest {

    private int v1;
    private int v2;
    BeanWebClient b1;

    public BeanTest(){}

    public BeanTest(int v1, int v2){
        this.v1=v1;
        this.v2=v2;
        beanWebClient();
    }
    
    public BeanWebClient beanWebClient() {
        //System.out.println("In BeanTest class beanWebClient() method execution v1 and v2: "+v1+v2);
        b1 = new BeanWebClient(v1,v2);
        System.out.println("In BeanTest class beanWebClient() method execution v1 and v2: "+b1.getV1()+" "+b1.getV2());
        return b1;
    }

    public void message() {
        b1.webClientMessage();
        //System.out.println("V1= "+v1+" V2= "+v2);
    }
}
public class BeanWebClient {

    private int v1;
    private int v2;
    
    public BeanWebClient(int v1, int v2) {}
        this.v1=v1;
        this.v2=v2;
        System.out.println("Received from BeanTest "+v1+" "+v2);
    }

    public BeanWebClient(){ }

    public int getV1() {
        return v1;
    }
    
    public int getV2() {
        return v2;
    }

    public void webClientMessage(){
        System.out.println("In BeanWebClient class, printing from autowired dependency "+v1+" "+v2);
    }
}
public class User {

    private BeanTest beanTest;

    public User(BeanTest beanTest) {
        this.beanTest=beanTest;
    }
    
    public User() {
        //System.out.println("user create... hashCode :" + this.hashCode());
    }

    public void message() {
        beanTest.message();
    }
}

【讨论】:

  • 但是我将无法使用@AutowiredBeanTest 依赖注入User 对吗?正如您在回答中所显示的那样,我必须手动创建对象 User
  • 当然,但这不正是您在TimeOutConfig 课程中所做的吗?您正在自己创建所有实例并将两个 User 实例注册为 Spring 管理的 Bean,以后可以将其注入您的 BeanService
  • 是的。但我认为我在配置本身时,可以将BeanTest 的实例初始化为User 类。当我将User 中的成员函数创建为private BeanTest beanTest 但当我使用@Autowired private BeanTest beanTestNOT 时,这有效。现在我的问题是,在配置时,如果我使用@Autowired for 在用户中注入 BeanTest,它会被初始化但是在服务类中,当我检查User 类的成员函数时,beanTest 为空。我想知道为什么它在配置期间被初始化但在服务类中使用User 时显示为空
  • 但这就是问题所在,并不是beanTest 为空。 null 是BeanWebClient b1,因为在这种情况下BeanTest 实例是使用不调用beanWebClient() 的默认无参数构造函数创建的。此外,正如我之前所说,您不能在 User 类上仅使用 @Component 注册两个 User 实例,因此您必须按照我在 TimeOutConfig 类中的答案进行操作。
  • 对,当你提到默认的无参数构造函数时,我开始理解这一点。是的,我意识到将@Component 用于 User 类是没有意义的。谢谢您的帮助。有什么方法可以使用@Autowired 在User 中注入和实例化BeanTest。用例的原因我需要使用UserbeanTestBeanWebClient 函数,并且如前所述,我有两组不同的值,每个User Bean 处理一组值。 再次感谢您的耐心和回复所有内容
猜你喜欢
  • 1970-01-01
  • 2014-07-26
  • 1970-01-01
  • 2012-06-23
  • 2018-07-02
  • 2020-01-19
  • 2021-06-24
  • 2021-08-11
  • 1970-01-01
相关资源
最近更新 更多