Spring中@Configurable失效:@Autowired注入Service报NullPointerException求助
Spring @Configurable 无法注入@Autowired Service 问题
我尝试在Spring中使用@Configurable注解,想在手动创建的非Bean类里注入@Autowired修饰的Service,但无论怎么尝试都没法正常工作。之前调研过相关问题,现在完全没头绪,以下是我写的极简代码示例:
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>
配置扫描类(AspectJConfig)
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 { }
SpringBoot启动类(Demo2Application)
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(); } }
带@Configurable的客户端类(HelloWorldClient)
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类(HelloWorldService)
package com.example.demo2; import org.springframework.stereotype.Service; @Service public class HelloWorldService { public void sayHello() { System.out.println("Hello world!"); } }
之前我在相关问题中得到过有效解决方案,但现在在当前环境下无法正常运行。
解决方案
1. 补全AspectJ核心依赖
@Configurable依赖AspectJ织入实现对象注入,你的pom.xml缺少关键依赖,需添加:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </dependency>
2. 启用AspectJ织入
@Configurable必须通过AspectJ织入才能生效,二选一即可:
方式一:编译时织入(推荐)
在pom.xml的build/plugins中添加AspectJ编译插件,确保编译阶段完成织入:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.14.0</version> <configuration> <complianceLevel>17</complianceLevel> <source>17</source> <target>17</target> <aspectLibraries> <aspectLibrary> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> </aspectLibrary> </aspectLibraries> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>test-compile</goal> </goals> </execution> </executions> </plugin>
方式二:加载时织入
如果不想修改编译流程,可启用加载时织入:
- 在
src/main/resources下创建META-INF/aop.xml:
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "https://www.eclipse.org/aspectj/dtd/aspectj.dtd"> <aspectj> <weaver> <include within="com.example.demo2..*"/> </weaver> <aspects> <aspect name="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect"/> </aspects> </aspectj>
- 启动时添加JVM参数:
-javaagent:/path/to/aspectjweaver.jar(IDE中可在VM Options里配置)
3. 明确@Configurable注入规则
给@Configurable添加属性,指定注入方式:
@Configurable(autowire = Autowire.BY_TYPE) public class HelloWorldClient { // ... }
4. 调整对象创建时机
@PostConstruct执行时Spring上下文可能未完全初始化,改为在上下文就绪后创建对象:
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) public class Demo2Application implements ApplicationListener<ContextRefreshedEvent> { public static void main(String[] args) { SpringApplication.run(Demo2Application.class, args); } @Override public void onApplicationEvent(ContextRefreshedEvent event) { HelloWorldClient client = new HelloWorldClient(); client.sayHello(); } }
5. 简化Spring配置
将@EnableSpringConfigured直接加到启动类上,避免配置类被遗漏扫描:
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) @EnableSpringConfigured public class Demo2Application { // ... }
内容的提问来源于stack exchange,提问作者whiteRabbit
相关产品推荐
相关产品推荐

