当有两个相同名称和不同 class bean 时如何按名称获取正确的 bean

how to get the right bean by name when have two same name and different class bean

我有两个 spring bean。它们的名称相同,但 class 不同。

这是 bean 定义。

这是第一个。

@Bean(name = "approve_sign_up_project_request|Task_1tm7e53")
    public StudentTaskToResponseDataConverter perfectUserProfileVO() {
        return studentTaskVO -> {
            ResponseVo vo = toResponseVO(studentTaskVO);
            vo.setData(new PerfectUserProfileVO());

            return vo;
        };
    }

这是第二个

@Bean(name = "approve_sign_up_project_request|Task_1tm7e53")
    public UserTaskCompleter perfectUserProfile() {
        return new UserTaskCompleter() {
            @Override
            public void validate(Task task, CompleteUserTaskDTO dto) throws RuntimeException {
                Long studentId = getStudentId(task);
                UserProfileIntegrityValidatedResultDTO results = userService.
                        validateTheIntegrityOfUserProfile(studentId);
                if (results.getComplete()) {
                    //nothing to do for now
                }else {
                    LOGGER.error("Validated failed cause the student -- {} not yet perfected the profile",
                            studentId);
                    throw new UserProfileImperfectException("Missing fields are " + results.getMissingFields());
                }
            }

            @Override
            public void executeBusinessLogic(Task task, CompleteUserTaskDTO dto) {

            }

            @Override
            public Map<String, Object> getTheVariablesForCompleterUserTask(Task task, CompleteUserTaskDTO dto) {
                return null;
            }
        };
    }

并且当我使用下面的代码获取 bean 时,spring 将抛出异常。但是我不明白原因。 我认为当我使用 bean 名称和 bean class 获取它时 spring 会给我正确的 bean。但其实我错了spring没有给

这里是获取bean的代码

private UserTaskCompleter getBean(CompleteUserTaskDTO dto) {
        String beanName = dto.getProcessDefinitionKey() + "|" + dto.getActivityId();
        return applicationContext.getBean(beanName, UserTaskCompleter.class);
    }

这里是例外

org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'approve_sign_up_project_request|Task_1tm7e53' is expected to be of type 'com.hikedu.backend.camunda.beanconfig.taskcompleter.UserTaskCompleter' but was actually of type 'com.hikedu.backend.camunda.beanconfig.tasktoresponsedatecoverter.signupprojectprocess.SignUpProjectProcessTaskConverterConfig$$Lambda5/484805627'
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:384)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1091)
    at com.hikedu.backend.camunda.beanconfig.taskcompleter.BaseUserTaskCompleter.getBean(BaseUserTaskCompleter.java:45)
    at com.hikedu.backend.camunda.beanconfig.taskcompleter.BaseUserTaskCompleter.validate(BaseUserTaskCompleter.java:29)
    at com.hikedu.backend.service.impl.camunda.signupprojectprocess.BaseSignUpProjectProcessServiceImpl.completeUserTask(BaseSignUpProjectProcessServiceImpl.java:165)
    at com.hikedu.backend.controller.SignUpProjectProcessUserTaskController.completerStudentTask(SignUpProjectProcessUserTaskController.java:93)
    at com.hikedu.backend.controller.SignUpProjectProcessUserTaskController$$FastClassBySpringCGLIB$$a695dddd.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)

谁能告诉我当有两个名称相同但 calss 不同的 bean 时如何通过名称获取正确的 bean。

我已经明白原因了

当定义了两个同名不同类型的bean。 spring 将选择最后一个覆盖其他。

在我的例子中,只有一个名为 "approve_sign_up_project_request|Task_1tm7e53" 的 bean,类型是 StudentTaskToResponseDataConverter。

当我使用名称和 UserTaskCompleter 类型从 beanFactory 获取 bean 时
spring 找不到它然后 spring 将抛出异常。

如何允许 spring 创建同名 bean?

我从

中找到了答案

这是答案的重要部分

You may use an initializer when building your Spring Boot app:

@SpringBootApplication
public class SpringBootApp {

    public static void main(String... args) {
        new SpringApplicationBuilder(SpringBootApp.class)
            .initializers(new ApplicationContextInitializer<GenericApplicationContext>() {
                @Override
                public void initialize(GenericApplicationContext applicationContext) {
                    applicationContext.setAllowBeanDefinitionOverriding(false);
                }
            })
        .run(args);

    }
}

Or with java 8:

new SpringApplicationBuilder(SpringBootApp.class)
    .initializers((GenericApplicationContext c) -> c.setAllowBeanDefinitionOverriding(false) )
    .run(args);

Himly 引用的答案,不让Spring创建同名bean。 它实际上阻止了它启动,因为构建应用程序将失败。

如果定义了多个同名bean,则后面定义的会覆盖前面定义的。因此,在您的情况下,只有一个名为 approve_sign_up_project_request|Task_1tm7e53 的 bean 将存在,除非您禁用 bean 定义覆盖。