Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/309.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 为什么我的Spring@Autowired字段为空?_Java_Spring_Null_Nullpointerexception_Autowired - Fatal编程技术网

Java 为什么我的Spring@Autowired字段为空?

Java 为什么我的Spring@Autowired字段为空?,java,spring,null,nullpointerexception,autowired,Java,Spring,Null,Nullpointerexception,Autowired,注意:这是一个常见问题的标准答案 我有一个Spring@Service类(MileageFeeCalculator),它有一个@Autowired字段(rateService),但当我尝试使用它时,该字段是null。日志显示,mileageFeeCaulatorbean和mileageGateServicebean都在创建中,但是每当我尝试在我的服务bean上调用mileageCharge方法时,我都会得到一个NullPointerException。为什么Spring没有在现场自动布线 控制器

注意:这是一个常见问题的标准答案

我有一个Spring
@Service
类(
MileageFeeCalculator
),它有一个
@Autowired
字段(
rateService
),但当我尝试使用它时,该字段是
null
。日志显示,
mileageFeeCaulator
bean和
mileageGateService
bean都在创建中,但是每当我尝试在我的服务bean上调用
mileageCharge
方法时,我都会得到一个
NullPointerException
。为什么Spring没有在现场自动布线

控制器类:

@Controller
public class MileageFeeController {    
    @RequestMapping("/mileage/{miles}")
    @ResponseBody
    public float mileageFee(@PathVariable int miles) {
        MileageFeeCalculator calc = new MileageFeeCalculator();
        return calc.mileageCharge(miles);
    }
}
服务类别:

@Service
public class MileageFeeCalculator {

    @Autowired
    private MileageRateService rateService; // <--- should be autowired, is null

    public float mileageCharge(final int miles) {
        return (miles * rateService.ratePerMile()); // <--- throws NPE
    }
}
当我尝试
获取/里程/3
时,会出现以下异常:

java.lang.NullPointerException: null
    at com.chrylis.example.spring_autowired_npe.MileageFeeCalculator.mileageCharge(MileageFeeCalculator.java:13)
    at com.chrylis.example.spring_autowired_npe.MileageFeeController.mileageFee(MileageFeeController.java:14)
    ...

带注释的
@Autowired
字段为
null
,因为Spring不知道您使用
new
创建的
mileAgeCalculator
的副本,也不知道如何自动连线它

有三个主要的逻辑组件:应用程序可使用的组件(bean)的注册表(称为
ApplicationContext
),配置器系统,通过将依赖项与上下文中的bean匹配,将对象的依赖项注入其中,以及一个依赖项解算器,它可以查看许多不同bean的配置,并确定如何按照必要的顺序实例化和配置它们

IoC容器并不神奇,除非您以某种方式通知它,否则它无法了解Java对象。当您调用
new
时,JVM会实例化新对象的一个副本,并直接将其交给您——它从未经历过配置过程。有三种方法可以配置bean

我已经发布了所有这些代码,使用SpringBoot启动,在;您可以查看每种方法的完整运行项目,以了解使其工作所需的一切标记为
NullPointerException

注射你的豆子 最好的选择是让Spring自动连接所有bean;这需要最少的代码,并且是最容易维护的。要使自动布线按您所希望的方式工作,还可以像下面这样自动布线
mileagefeeculator

@Controller
public class MileageFeeController {

    @Autowired
    private MileageFeeCalculator calc;

    @RequestMapping("/mileage/{miles}")
    @ResponseBody
    public float mileageFee(@PathVariable int miles) {
        return calc.mileageCharge(miles);
    }
}
@Service
public class MileageFeeCalculator {

    @Autowired
    private MileageRateService rateService; // <--- will be autowired when constructor is called

    public MileageFeeCalculator() {
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this)
    }

    public float mileageCharge(final int miles) {
        return (miles * rateService.ratePerMile()); 
    }
}
MyBean myBean = (MyBean)SpringUtils.ctx.getBean(MyBean.class);
ApplicationContext context =
    new ClassPathXmlApplicationContext(new String[] {
        "common.xml",
        "token.xml",
        "pep-config.xml" });
    TokenInitializer ti = context.getBean(TokenInitializer.class);
如果您需要为不同的请求创建服务对象的新实例,您仍然可以使用注入

通过注入
@mileageCalculator
服务对象工作的标记:

使用@Configurable 如果确实需要使用
new
创建的对象进行自动连接,则可以插入对象。这种方法将代码插入到对象的构造函数中,提醒Spring正在创建它,以便Spring可以配置新实例。这需要在构建中进行一些配置(例如使用
ajc
进行编译)并启用Spring的运行时配置处理程序(
@enablespringconfigulated
,使用JavaConfig语法)。Roo活动记录系统使用这种方法来允许实体的
新的
实例获得必要的持久性信息

@Service
@Configurable
public class MileageFeeCalculator {

    @Autowired
    private MileageRateService rateService;

    public float mileageCharge(final int miles) {
        return (miles * rateService.ratePerMile());
    }
}
通过在服务对象上使用
@Configurable
工作的标记:

手动bean查找:不推荐 这种方法仅适用于在特殊情况下与遗留代码接口。几乎总是最好创建一个单例适配器类,Spring可以自动连接,遗留代码可以调用,但也可以直接向Spring应用程序上下文请求bean

为此,您需要一个类,Spring可以向该类提供对
ApplicationContext
对象的引用:

@Component
public class ApplicationContextHolder implements ApplicationContextAware {
    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;   
    }

    public static ApplicationContext getContext() {
        return context;
    }
}
然后,您的遗留代码可以调用
getContext()
并检索它所需的bean:

@Controller
public class MileageFeeController {    
    @RequestMapping("/mileage/{miles}")
    @ResponseBody
    public float mileageFee(@PathVariable int miles) {
        MileageFeeCalculator calc = ApplicationContextHolder.getContext().getBean(MileageFeeCalculator.class);
        return calc.mileageCharge(miles);
    }
}

通过在Spring上下文中手动查找服务对象来工作的标记:

注释的
@Autowired
字段为
null
,因为Spring不知道您使用
new
创建的
里程数计算器的副本,也不知道自动连线它

有三个主要的逻辑组件:应用程序可使用的组件(bean)的注册表(称为
ApplicationContext
),配置器系统,通过将依赖项与上下文中的bean匹配,将对象的依赖项注入其中,以及一个依赖项解算器,它可以查看许多不同bean的配置,并确定如何按照必要的顺序实例化和配置它们

IoC容器并不神奇,除非您以某种方式通知它,否则它无法了解Java对象。当您调用
new
时,JVM会实例化新对象的一个副本,并直接将其交给您——它从未经历过配置过程。有三种方法可以配置bean

我已经发布了所有这些代码,使用SpringBoot启动,在;您可以查看每种方法的完整运行项目,以了解使其工作所需的一切标记为
NullPointerException

注射你的豆子 最好的选择是让Spring自动连接所有bean;这需要最少的代码,并且是最容易维护的。要使自动布线按您所希望的方式工作,还可以像下面这样自动布线
mileagefeeculator

@Controller
public class MileageFeeController {

    @Autowired
    private MileageFeeCalculator calc;

    @RequestMapping("/mileage/{miles}")
    @ResponseBody
    public float mileageFee(@PathVariable int miles) {
        return calc.mileageCharge(miles);
    }
}
@Service
public class MileageFeeCalculator {

    @Autowired
    private MileageRateService rateService; // <--- will be autowired when constructor is called

    public MileageFeeCalculator() {
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this)
    }

    public float mileageCharge(final int miles) {
        return (miles * rateService.ratePerMile()); 
    }
}
MyBean myBean = (MyBean)SpringUtils.ctx.getBean(MyBean.class);
ApplicationContext context =
    new ClassPathXmlApplicationContext(new String[] {
        "common.xml",
        "token.xml",
        "pep-config.xml" });
    TokenInitializer ti = context.getBean(TokenInitializer.class);
如果您需要为不同的请求创建服务对象的新实例,您仍然可以使用注入

通过注入
@mileageCalculator
服务对象工作的标记:

使用@Configurable 如果确实需要使用
new
创建的对象进行自动连接,则可以插入对象。这种方法将代码插入到对象的构造函数中,提醒Spring正在创建它,以便Spring可以配置新实例。这需要一点配置
@Inject
Calculator myCalculator
MileageFeeCalculator calc = new MileageFeeCalculator();
@Controller
public class MileageFeeController {

    @Autowired
    MileageFeeCalculator calc;  

    @RequestMapping("/mileage/{miles}")
    @ResponseBody
    public float mileageFee(@PathVariable int miles) {
        return calc.mileageCharge(miles);
    }
}
@Service
public class ClassB {

    private ClassA classA;

    @Autowired
    public ClassB(ClassA classA) {
        this.classA = classA;
    }

    public void useClassAObjectHere(){
        classA.callMethodOnObjectA();
    }
}
ApplicationContext context =
    new ClassPathXmlApplicationContext(new String[] {
        "common.xml",
        "token.xml",
        "pep-config.xml" });
    TokenInitializer ti = context.getBean(TokenInitializer.class);
<context:component-scan base-package="package.path"/>
<bean id="someAbac" class="com.pep.SomeAbac" init-method="init"/>
<bean id="settings" class="com.pep.Settings"/>
@Autowired private Settings settings;
<context:component-scan base-package="some.shit"/>
//import org.junit.Test; // JUnit4
import org.junit.jupiter.api.Test; // JUnit5

@SpringBootTest
public class MyTests {
    ....
@SpringBootApplication
public class Application {
    @Autowired MyComponent comp;
}
@Component
public class MyComponent {
    @Autowired ComponentDAO dao;

    public MyComponent() {
        // dao is null here
    }

    @PostConstruct
    public void init() {
        // dao is initialized here
    }
}
    private OrderingClient orderingClient;
    private Sales2Client sales2Client;
    private Settings2Client settings2Client;

    @Autowired
    public BrinkWebTool(OrderingClient orderingClient, Sales2Client sales2Client, Settings2Client settings2Client) {
        this.orderingClient = orderingClient;
        this.sales2Client = sales2Client;
        this.settings2Client = settings2Client;
    }