当具有两个相同的名称和不同的类Bean时如何按名称获取正确的Bean

时间:2018-09-30 07:56:34

标签: java spring spring-boot javabeans

我有两个春豆。它们是相同的名称,但类是不同的。

这是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时,弹簧将引发异常。但是我不明白原因。 我认为当我使用bean名称和bean类来获取它时,春天会给我合适的bean。但是我确实错了,春天没有给它。

这是获取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$$Lambda$625/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。

2 个答案:

答案 0 :(得分:2)

Himly引用的答案不允许Spring创建具有相同名称的bean。 实际上,它会阻止它启动,因为构建应用程序将失败。

如果定义了多个具有相同名称的bean,则稍后定义的一个将覆盖先前定义的一个。结果,在您的情况下,除非禁用bean定义覆盖,否则只有一个名为approve_sign_up_project_request|Task_1tm7e53的bean将存在。

答案 1 :(得分:0)

我已经明白了原因。

定义两个相同名称和不同类型的bean时。春天将选择最后一个取代其他。

在我的情况下,只有一个名为“ approve_sign_up_project_request | Task_1tm7e53”的bean,类型为StudentTaskToResponseDataConverter。

当我使用名称和UserTaskCompleter类型获取bean形式beanFactory时
春天找不到了,春天就会抛出异常。

如何允许spring创建同名bean?

我从here

找到了答案

这是答案的重要部分

  

在构建Spring Boot应用程序时,您可以使用初始化程序:

@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);

    }
}
     

或使用Java 8:

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