简体   繁体   English

Spring @configurable NullPointerException,@autowired 服务是 null

[英]Spring @configurable NullPointerException, @autowired service is null

I'm trying to use @configurable in spring to use a @autowired service in a non bean class I create.我正在尝试在 spring 中使用 @configurable 在我创建的非 bean class 中使用 @autowired 服务。
It doesn't want to work anymore whatever I try.无论我尝试什么,它都不想再工作了。
Can someone tell me what I'm doing wrong?有人可以告诉我我做错了什么吗? (I did some research but I'm totally clueless now) (我做了一些研究,但我现在完全无能为力)
Here is a very basic code example I made:这是我制作的一个非常基本的代码示例:

pom.xml pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.5</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo2</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Configuration ComponentScan class配置ComponentScan class

package com.example.demo2;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.aspectj.EnableSpringConfigured;

@Configuration
@ComponentScan
@EnableSpringConfigured
public class AspectJConfig
{
    
}

@SpringBootApplication class @SpringBootApplication class

package com.example.demo2;

import javax.annotation.PostConstruct;

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

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class Demo2Application
{
    //@Autowired
    //private HelloWorldService helloWorldService;
    
    public static void main(String[] args)
    {
        SpringApplication.run(Demo2Application.class, args);
    }
    
    @PostConstruct
    public void doSomethingIProbablyShouldNotBeDoing()
    {
        //helloWorldService.sayHello();
        HelloWorldClient client = new HelloWorldClient();
        client.sayHello();
    }
    
}

class with @Configurable and @Autowired service class 带有@Configurable 和@Autowired 服务

package com.example.demo2;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;

@Configurable
public class HelloWorldClient
{
    @Autowired
    private HelloWorldService service;
    
    public void sayHello()
    {
        // Used injected instance of service
        service.sayHello();
    }
}

@Service class @服务 class

package com.example.demo2;

import org.springframework.stereotype.Service;

@Service
public class HelloWorldService
{
    public void sayHello()
    {
        System.out.println("Hello world!");
    }
}

Also here is a link to my previous post on that subject.这里还有一个链接,指向我之前关于该主题的帖子。 I did received an answer to my question that was working.我确实收到了我的问题的有效答案。 But for whatever reason it doesn't work anymore on my side.但无论出于何种原因,它在我这边不再起作用。
Spring @configurable NullPointerException Spring @configurable NullPointerException

@Configurable should be used in connection with native AspectJ, not with Spring AOP, see here . @Configurable应该与本机 AspectJ 结合使用,而不是与 Spring AOP 结合使用,请参见此处 Because the annotation is meant to be used with POJOs rather than Spring beans, this makes sense.因为该注解旨在用于 POJO 而不是 Spring bean,所以这是有道理的。

In my answer to your first question , we used AspectJ Maven Plugin to do compile-time weaving (CTW).我对您的第一个问题的回答中,我们使用了 AspectJ Maven 插件来进行编译时织入 (CTW)。 Either you need to do the same here or configure load-time weaving (LTW) instead.您需要在此处执行相同的操作,或者改为配置加载时织入 (LTW)

When using LTW, in order for org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect to work, which is responsible for achieving the POJO dependency injection, you need either of使用 LTW 时,为了让org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect工作,它负责实现 POJO 依赖注入,您需要

  • -javaagent:/path/to/aspectjweaver.jar on the JVM command line or -javaagent:/path/to/aspectjweaver.jar在 JVM 命令行或
  • -javaagent:/path/to/spring-instrument.jar on the JVM command line and @EnableLoadTimeWeaving in your Spring configuration or -javaagent:/path/to/spring-instrument.jar在 JVM 命令行和@EnableLoadTimeWeaving在你的 Spring 配置或
  • de.invesdwin:invesdwin-instrument in the dependency list plus a code snippet initialising the weaver in your application. de.invesdwin:invesdwin-instrument在依赖列表中加上一个代码片段来初始化你的应用程序中的编织器。 On more recent Java versions, you probably also need --add-opens java.base/java.lang=ALL-UNNAMED on the JVM command line to enable invesdwin-instrument to work correctly, using reflection.在更新的 Java 版本中,您可能还需要--add-opens java.base/java.lang=ALL-UNNAMED在 JVM 命令行上启用invesdwin-instrument以使用反射正常工作。

You also need spring-aspects for the AnnotationBeanConfigurerAspect to be found.您还需要spring-aspects才能找到AnnotationBeanConfigurerAspect Optionally, you might want to add your own META-INF/aop.xml (or org/aspectj/aop.xml ) file in the resources directory, if you want to configure certain weaving options or deactivate unneeded aspects from spring-aspects , if the corresponding warning messages on the console get on your nerves.或者,您可能希望在资源目录中添加自己的META-INF/aop.xml (或org/aspectj/aop.xml )文件,如果您想要配置某些编织选项或停用spring-aspects中不需要的方面,如果控制台上相应的警告消息会让您心烦意乱。

I know that this is not trivial, which is why I think that the CTW approach is easier to set up.我知道这不是微不足道的,这就是为什么我认为 CTW 方法更容易设置。 But if you want to apply aspects dynamically via LTW, you need to use one of the approaches mentioned above.但是如果你想通过 LTW 动态应用方面,你需要使用上面提到的方法之一。 It is not rocket science, just a bit complicated when doing it the first time.这不是火箭科学,第一次做的时候有点复杂。 But like Miyamoto Musashi said: "It may seem difficult at first, but all things are difficult at first."但就像宫本武藏说的那样: “乍看之下似乎很难,但万事开头难。”


Update: Here is an MCVE for you, ie a full, minimal example:更新:这是给你的MCVE ,即一个完整的、最小的例子:

https://github.com/kriegaex/SO_AJ_SpringMavenConfigurableNPE_74184130 https://github.com/kriegaex/SO_AJ_SpringMavenConfigurableNPE_74184130

Feel free to play with it and remove the code using invesdwin-instrument and the corresponding dependency, if you want to use -javaagent and Spring on-board means.如果您想使用-javaagent和 Spring 机载方式,请随意使用它并使用invesdwin-instrument和相应的依赖项删除代码。 I actually recommend that.我实际上建议这样做。

You are creating service manually using new HelloWorldClient() @Autowired works only when bean/service is created by spring您正在使用new HelloWorldClient()手动创建服务@Autowired仅在 bean/service 由 spring 创建时有效

try autowiring HelloWorldClient in Demo2Application and not creating it manually尝试在Demo2Application中自动装配HelloWorldClient而不是手动创建它

Maybe You could try Spring @Autowired on a class new instance maybe it works也许您可以在 class 新实例上尝试 Spring @Autowired也许它可以工作

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM