简体   繁体   English

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

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

I have two spring bean. 我有两个春豆。 They are name is same but the class is defferent. 它们的名称是相同的,但类是不同的。

Here is the bean definitions. 这是bean的定义。

This one is the first. 这是第一个。

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

            return vo;
        };
    }

This one is the second 这是第二个

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

And When I use below code to get the bean the spring will throw an excetpion. 当我使用下面的代码获取bean时,弹簧将引发异常。 But I did not understand the reason. 但是我不明白原因。 I think the spring will give me the right bean when I use the bean name and bean class to get it. 我认为当我使用bean名称和bean类来获取它时,春天会给我合适的bean。 But actully I am wrong the spring did not give it. 但是我确实错了,春天没有给它。

Here is the code of to get bean 这是获取bean的代码

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

Here is the exception 这是例外

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)

Can someone tell me how to get the right bean by name when have two same name and different calss bean. 有人可以告诉我当有两个相同的名称和不同的calss bean时如何按名称获取正确的bean。

The answer that Himly quotes, does not let Spring create beans with the same name. Himly引用的答案不允许Spring创建具有相同名称的bean。 It actually prevents it from starting up, since building the application will fail. 实际上,由于构建应用程序将失败,因此它无法启动。

If multiple beans are defined with the same name, then the one defined later will override the one defined earlier. 如果定义了多个具有相同名称的bean,则稍后定义的bean将覆盖先前定义的bean。 As a result, in your case only one bean named approve_sign_up_project_request|Task_1tm7e53 will exist, unless you disable the bean definition overriding. 结果,在您的情况下,除非禁用bean定义覆盖,否则只有一个名为approve_sign_up_project_request|Task_1tm7e53 bean将存在。

I already understaned the reason. 我已经明白了原因。

When definitioned two same name and different type bean. 定义两个相同名称和不同类型的bean时。 The spring will choose the last one to overriding others. 春天将选择最后一个取代其他。

In my case there are just one bean named "approve_sign_up_project_request|Task_1tm7e53" and the type is StudentTaskToResponseDataConverter. 在我的情况下,只有一个名为“ approve_sign_up_project_request | Task_1tm7e53”的bean,类型为StudentTaskToResponseDataConverter。

When I use the name and the UserTaskCompleter type to get the bean form beanFactory 当我使用名称和UserTaskCompleter类型获取bean形式beanFactory时
the spring cannot find it and then the spring will throw the excetpion. 弹簧找不到它,然后弹簧就会抛出异常。

How to allow the spring create same name bean ? 如何让spring创建同名bean?

I find the answer from here 我从这里找到答案

Here is the import part of the answer 这是答案的重要部分

You may use an initializer when building your Spring Boot app: 您可以在构建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); } } 

Or with java 8: 或使用Java 8:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM