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

Micronaut Data @Repository注解引发Bean实例化异常问题

问题描述

近期使用Micronaut框架开发数据库交互程序,因接触Gradle项目配置时间较短,初步怀疑问题与Gradle配置相关。
项目拆分为两个模块:

  • main模块:存放Application启动类
  • masterdata模块:存放全部业务代码

masterdata模块包含以下代码:

  1. 带/test接口的Controller,接口仅返回字符串,代码如下:
package core.masterdata.module.controllers;

import core.masterdata.module.entities.Person;
import core.masterdata.module.repositories.PersonRepository;
import core.masterdata.module.services.PersonService;
import io.micronaut.core.version.annotation.Version;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import jakarta.inject.Inject;

import java.util.Optional;

import static core.masterdata.module.constants.EntitiesConstants.BASE_URL;

@Controller(BASE_URL + "/person/")
@Version("1")
public class PersonController {

    @Inject
    PersonService personService;

    @Inject
    PersonRepository personRepository;

    @Get("test")
    public String getPerson(Long pId){
        return "test";
    }
}
  1. Repository接口代码如下:
package core.masterdata.module.repositories;

import core.masterdata.module.entities.Person;
import io.micronaut.data.annotation.Repository;
import io.micronaut.data.repository.CrudRepository;

@Repository
public interface PersonRepository extends CrudRepository<Person, Long> {
}
  1. 实体类代码如下:
package core.masterdata.module.entities;

import javax.persistence.*;

@Entity
@Table(name = "Person")
public class Person {

    @Id
    @GeneratedValue
    @Column
    private Long id;

    @Column
    private String name;

    public Person(String name){
        this.name = name;
    }

    public Person() {
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setId(Long id) {
        this.id = id;
    }
}

模块内另有一个标注@Singleton注解的空类。

项目可以正常构建编译,但在Controller或Service中注入Repository后调用对应API时会触发运行时错误。测试发现:

  • 在Controller中注入上述@Singleton标注的空类时运行无异常
  • 如果将Repository注入到该空类、再将空类注入到Controller中,仍会触发相同错误

核心异常信息如下:

Unexpected error occurred: Error instantiating bean of type  [core.masterdata.module.controllers.PersonController]
Message: Multiple possible bean candidates found: [io.micronaut.aop.InterceptorRegistry, io.micronaut.aop.InterceptorRegistry]
Path Taken: new PersonController() --> PersonController.personRepository
io.micronaut.context.exceptions.BeanInstantiationException: Error instantiating bean of type  [core.masterdata.module.controllers.PersonController]
Caused by: io.micronaut.context.exceptions.NonUniqueBeanException: Multiple possible bean candidates found: [io.micronaut.aop.InterceptorRegistry, io.micronaut.aop.InterceptorRegistry]
问题原因

该报错是典型的多模块Gradle配置错误导致的类重复加载问题:
业务模块masterdata没有使用官方标准的io.micronaut.library插件配置,错误地将Micronaut核心依赖(含InterceptorRegistry的aop模块)通过implementation/api直接声明,导致main启动模块、masterdata业务模块在构建时各自引入了一份完全相同的InterceptorRegistry类,Micronaut IoC容器启动扫描Bean时发现两个同类型的候选Bean,无法确定注入优先级,最终抛出非唯一Bean异常。

普通@Singleton注解的自定义类不需要AOP代理增强,所以注入时不会触发InterceptorRegistry的加载流程,不会报错;而@Repository标注的Repository接口需要Micronaut Data通过AOP实现代理类,实例化时必须注入InterceptorRegistry,就触发了重复Bean的错误。

另外代码中实体类使用javax.persistence.*注解,如果使用Micronaut 4及以上版本,需要统一替换为jakarta.persistence.*,但这个问题不会触发当前的重复Bean异常。

解决方案

按以下步骤调整配置即可修复:

  • 检查两个模块的build.gradle插件配置:存放启动类的main模块应用io.micronaut.application插件,存放业务代码的masterdata模块仅应用io.micronaut.library插件,禁止在子模块中重复引入Micronaut核心BOM、micronaut-core、micronaut-aop等核心依赖,核心依赖版本统一通过根项目或主模块的Micronaut插件配置管理。
  • masterdata子模块参考配置如下:
plugins {
    id "io.micronaut.library"
}

micronaut {
    // 版本号和main模块保持完全一致
    version "对应Micronaut版本"
}

dependencies {
    // 仅声明模块需要的业务依赖,核心依赖由插件自动引入
    annotationProcessor "io.micronaut.data:micronaut-data-processor"
    implementation "io.micronaut.data:micronaut-data-jdbc"
    // 其他业务依赖,比如数据库驱动、验证相关包等
}
  • main模块通过implementation project(':masterdata')正常引入业务模块即可,不需要额外配置扫描路径等参数,Micronaut会自动识别子模块内的Bean。
  • 配置调整完成后执行./gradlew clean清理全部旧构建缓存,再重新构建启动项目即可解决问题。
  • 如果你使用的是Micronaut 4及以上版本,将实体类中所有javax.persistence.*的导入替换为jakarta.persistence.*,避免后续JPA实体映射报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 06:21:31