简体   繁体   中英

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.

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.

Here is the code of to get 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.

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.

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.

I already understaned the reason.

When definitioned two same name and different type 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.

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.

How to allow the spring create same name 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:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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