You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Autowired注解在跨包自定义SimpleJpaRepository子类中注入失败排查

问题描述

我有一个Spring Boot应用,在handler类里用@Autowired注入com.example.utils.IDGenerator能正常初始化,但在com.example.customutils.JtJPARepositoryImpl(继承SimpleJpaRepository)里同样用@Autowired注入IDGenerator,变量始终为null。

原因分析
  1. Spring Data JPA Repository的特殊创建机制:JtJPARepositoryImpl作为Repository的基类,其实例是由Spring Data JPA的动态代理工厂生成的,不属于普通Spring Bean范畴。Spring默认不会对这类动态生成的类执行@Autowired成员变量的注入逻辑。
  2. 构造函数的特殊性:当前JtJPARepositoryImpl的构造函数是给Spring Data框架调用的,仅用于传入JpaEntityInformation和EntityManager,框架不会自动处理类中其他@Autowired标注的成员变量。
  3. 组件扫描不生效:虽然@ComponentScan包含了com.example.customutils包,但JtJPARepositoryImpl没有标注@Component,Spring不会把它当作普通Bean来处理依赖注入。
解决方案

方案1:改用构造函数注入(推荐)

修改JtJPARepositoryImpl的构造函数,把IDGenerator作为参数传入,Spring Data会在创建Repository实例时自动注入依赖:

public class JtJPARepositoryImpl<T extends BaseEntity, ID extends Serializable>
        extends SimpleJpaRepository<T, ID> implements JtJPARepository<T, ID>, Serializable {

    private final IDGenerator idGenerator;

    // 将IDGenerator加入构造函数
    public JtJPARepositoryImpl(JpaEntityInformation entityInformation, EntityManager entityManager, IDGenerator idGenerator) {
        super(entityInformation, entityManager);
        this.idGenerator = idGenerator;
    } 
}

注:需确保IDGenerator是Spring容器中的有效Bean(当前已满足,因为handler类可正常注入)。

方案2:手动从ApplicationContext获取Bean

如果不想修改构造函数,可让JtJPARepositoryImpl实现ApplicationContextAware接口,手动获取IDGenerator实例:

public class JtJPARepositoryImpl<T extends BaseEntity, ID extends Serializable>
        extends SimpleJpaRepository<T, ID> implements JtJPARepository<T, ID>, Serializable, ApplicationContextAware {

    private IDGenerator idGenerator;

    @Autowired
    public JtJPARepositoryImpl(JpaEntityInformation entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.idGenerator = applicationContext.getBean(IDGenerator.class);
    }
}

方案3:使用@Configurable(需额外配置)

给JtJPARepositoryImpl添加@Configurable注解,结合AspectJ编译时织入,让动态生成的类支持Spring依赖注入。但这种方式需要额外配置AspectJ,步骤繁琐,不推荐作为首选方案。

相关代码片段

com.example.customutils.JtJPARepositoryImpl(原代码)

public class JtJPARepositoryImpl<T extends BaseEntity, ID extends Serializable>
        extends SimpleJpaRepository<T, ID> implements JtJPARepository<T, ID>, Serializable {

    @Autowired
    private IDGenerator idGenerator;

    @Autowired
    public JtJPARepositoryImpl(JpaEntityInformation entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);
    } 
}

com.example.serviceapplication.ServiceApplication

@Slf4j
@SpringBootApplication
@ImportResource({"classpath:applicationContext.xml"})
@ComponentScan(basePackages = {
        "com.example.serviceapplication",
        "com.example.utils",
        "com.example.customutils"
})
@EnableJpaRepositories(basePackages = "com.jumbotail.serviceapplication.repository",
        repositoryBaseClass = JtJPARepositoryImpl.class)
public class ServiceApplication {

    @Inject
    private ServiceProperties ServiceProperties;

    private final ApplicationContext applicationContext;

    public ServiceApplication(ApplicationContext applicationContext) {

        ServiceProperties baseConfiguration = new ServiceProperties();
        baseConfiguration.setDynamoDBConfiguration(new DynamoDBConfiguration(10000,10000));

        this.applicationContext = applicationContext;
        DynamoDBClient dynamoDBClient = new DynamoDBClient(baseConfiguration);

        ((GenericWebApplicationContext)this.applicationContext).registerBean(BaseConfiguration.class,baseConfiguration);
        ((GenericWebApplicationContext)this.applicationContext).registerBean(DynamoDBClient.class,baseConfiguration);
    }

    public static void main(String[] args) {
        SpringApplication.run(ServiceApplication.class, args);
        log.info("Started Service");
    }

    @PostConstruct
    public void init() {
        log.info("Initializing application with Service properties- {}", ServiceProperties);
        ApplicationConfiguration.initialize(ServiceProperties.getEnvironment());
    }

    @Bean
    public BaseConfiguration getBaseConfiguration() {
        BaseConfiguration baseConfiguration = new BaseConfiguration();
        baseConfiguration.setEnvironment(ServiceProperties.getEnvironment());
        return baseConfiguration;
    }

    @Bean
    public HealthCheckConfiguration healthCheckConfiguration() {
        return serviceProperties.getHealthCheckConfiguration();
    }
}

com.example.utils.IDGenerator

@Slf4j
@Component
@Qualifier("IDGenerator")
public class IDGenerator {

    private static final String IDCOUNTER_TABLE = "IDCounter";
    private static final String IDCOUNTER_KEY_NAME = "namespace";
    private static final String IDCOUNTER_VALUE_NAME = "counter";
    private static final String IDCOUNTER_VERSION_NAME = "version";
    private final DynamoDBClient dynamoDBClient;

    public IDGenerator(DynamoDBClient dynamoDBClient) {
        this.dynamoDBClient = dynamoDBClient;
    }
}

内容的提问来源于stack exchange,提问作者ADA Home

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 07:17:07