小编典典

如何使用main(String [] args)方法中的自动关联(@Autowired)引用?

spring-boot

我正在尝试使用主类的自动引用,并且面临:

无法静态引用非静态字段zipCodeLookupService。

这是显而易见的。但是我想知道如何处理这种情况。涉及主类时自动接线的正确方法是什么?我的代码如下-

接口类

package com.example.services;
public interface IZipCodeLookup {
    String retriveCityForZip(String zipCode);
}

服务等级

package com.example.services;

import org.springframework.stereotype.Service;

@Service
public class ZipCodeLookupService implements IZipCodeLookup {

    @Override
    public String retriveCityForZip(String zipCode) {

        //below is mock code. actual code does a db lookup using a DAO.
        if(zipCode=="94123") return "San Francisco";
        return "not found in DB";
    }
}

这是需要服务班级的主要班级

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.example.services.IZipCodeLookup;

@SpringBootApplication
public class AutowireWithMainClassApplication {

    @Autowired
    IZipCodeLookup zipCodeLookupService;

    public static void main(String[] args) {
        SpringApplication.run(AutowireWithMainClassApplication.class, args);
        String city;
        //this will not work, compilation error
        //Cannot make a static reference to the non-static field zipCodeLookupService
        city=zipCodeLookupService.retriveCityForZip(args[0]);

        System.out.println("city for zipcode " + args[0] + " is " +city);       
    }
}

有人可以建议-涉及主类时如何或正确的方式使用自动装配。

(由于将Autowired引用设为静态仍然无法工作)
AutowireWithMainClassApplication课堂上,更改为-

@Autowired
static IZipCodeLookup zipCodeLookupService;

抛出

线程“主”中的异常java.lang.NullPointerException


阅读 2049

收藏
2020-05-30

共1个答案

小编典典

@SpringBootApplication注解注解的类不是经典bean。
它从 静态 方法创建Spring上下文。
但是自动装配的依赖关系不能是 静态的

这就是为什么此声明:

city=zipCodeLookupService.retriveCityForZip(args[0]);

不会引发Spring异常,而是引发NullPointerException您声明zipCodeLookupServicestatic字段的经典异常。


在您的情况下,作为一种解决方法,您可以将使用Spring bean的处理移到 实例 方法中,该 实例
方法javax.annotation.PostConstruct在您的主类内以方法注释,并将传递给该main()方法的参数存储在字段中,以便以后可以使用它:

private static String[] args;
@Autowired
IZipCodeLookup zipCodeLookupService;

public static void main(String[] args) {
    AutowireWithMainClassApplication.args = args;
    SpringApplication.run(AutowireWithMainClassApplication.class, args);
}

@PostConstruct
public void init() {
    String city=zipCodeLookupService.retriveCityForZip(args[0]);
    System.out.println("city for zipcode " + args[0] + " is " +city); 
}

要回答您的评论,您应注意以下几点 @PostConstruct

1)它不是特定于Spring的注释。因此,官方文档可能会讨论比Spring更通用的事物或特定但不同的事物,例如EJB(最初是为它们引入的)。

2)Javadoc的第一句话总结了一般的预期行为。

PostConstruct批注用于需要依赖注入完成以执行任何初始化之后需要执行的方法上。

但是这句话

“完成依赖项注入后执行”

的确意味着:

“在完成所有依赖项注入后执行”

我们通常谈论依赖注入,而不是每次依赖注入。
所以,是的,请坚持这一点。

将其应用于您的案例应该使事情更清楚。
AutowireWithMainClassApplication作为类被认为是一个Spring bean
@SpringBootApplication标注有@Configuration其本身标注了@Component
和任何Spring bean一样,它可以声明依赖注入。
那是一个依赖注入:

@Autowired
IZipCodeLookup zipCodeLookupService;

但是,您当然可以声明您想要的尽可能多的依赖项注入:

@Autowired
IZipCodeLookup zipCodeLookupService;

@Autowired
OtherClass otherClass;

...

因此,只有在 所有 依赖项都被有效注入后,PostConstruct才会被调用一次。

2020-05-30