如果有两个相同的名称和不同的类bean,如何通过名称获取正确的bean

时间:2020-12-12 20:55:26

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. 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. But actully I am wrong the spring did not give it.

当我使用下面的代码来获取bean时,spring会抛出异常。但我不明白原因。我认为当我使用bean名称和bean类来获取它时,spring会给我正确的bean。但实际上我错了,春天没有给它。

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。

2 个解决方案

#1


2  

The answer that Himly quotes, does not let Spring create beans with the same name. It actually prevents it from starting up, since building the application will fail.

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

If multiple beans are defined with the same name, then the one defined later will override the one defined earlier. 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,则稍后定义的bean将覆盖之前定义的bean。因此,在您的情况下,只有一个名为approve_sign_up_project_request | Task_1tm7e53的bean将存在,除非您禁用bean定义覆盖。

#2


0  

I already understaned the reason.

我已经理解了原因。

When definitioned two same name and different type bean. The spring will choose the last one to overriding others.

定义两个相同名称和不同类型的bean时。春天会选择最后一个来覆盖其他人。

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
the spring cannot find it and then the spring will throw the excetpion.

当我使用名称和UserTaskCompleter类型来获取bean表单beanFactory时,spring无法找到它,然后spring将抛出异常。

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

#1


2  

The answer that Himly quotes, does not let Spring create beans with the same name. It actually prevents it from starting up, since building the application will fail.

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

If multiple beans are defined with the same name, then the one defined later will override the one defined earlier. 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,则稍后定义的bean将覆盖之前定义的bean。因此,在您的情况下,只有一个名为approve_sign_up_project_request | Task_1tm7e53的bean将存在,除非您禁用bean定义覆盖。

#2


0  

I already understaned the reason.

我已经理解了原因。

When definitioned two same name and different type bean. The spring will choose the last one to overriding others.

定义两个相同名称和不同类型的bean时。春天会选择最后一个来覆盖其他人。

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
the spring cannot find it and then the spring will throw the excetpion.

当我使用名称和UserTaskCompleter类型来获取bean表单beanFactory时,spring无法找到它,然后spring将抛出异常。

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