Skip to content

Better error reporting for @Bean creating when bean instance has been replaced with an incompatible type #28897

@junyongz

Description

@junyongz

This would be even tougher to spot the error if the BeanPostProcessor instance is from other libraries.

12:43:19.439 [main] WARN org.springframework.context.annotation.AnnotationConfigApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'taskExecutor' defined in com.welcome.samples.junit.BeanPostProcessorComponentTest$CustomAsyncConfigurer: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [java.util.concurrent.Executor]: Illegal arguments to factory method 'getAsyncExecutor'; args: ; nested exception is java.lang.IllegalArgumentException: object is not an instance of declaring class

class BeanPostProcessorComponentTest {

    @Test
    void endToEnd() {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        ctx.register(CustomAsyncConfigurer.class, ProcessingAsyncConfigurerPostProcessor.class);
        ctx.refresh();
        ctx.close();
    }
    
    
    @Configuration
    public static class CustomAsyncConfigurer implements AsyncConfigurer {
        
        @Bean("taskExecutor")
        public Executor getAsyncExecutor() {
            return new ConcurrentTaskExecutor();
        }
    }

    public static class ProcessingAsyncConfigurerPostProcessor implements BeanPostProcessor {
        public Object postProcessBeforeInitialization(Object bean, String beanName)
                throws BeansException {
            if (bean instanceof AsyncConfigurer && !(bean instanceof FullyCustomAsyncConfigurer)) {
                return new FullyCustomAsyncConfigurer((AsyncConfigurer) bean);
            }
            
            return bean;
        }
    }
    
    public static class FullyCustomAsyncConfigurer extends AsyncConfigurerSupport {
        
        private AsyncConfigurer delegate;
        
        public FullyCustomAsyncConfigurer(AsyncConfigurer delegate) {
            this.delegate = delegate;
        }
        
        @Override
        public Executor getAsyncExecutor() {
            return new Executor() {
                
                @Override
                public void execute(Runnable command) {
                    FullyCustomAsyncConfigurer.this.delegate.getAsyncExecutor().execute(command);
                }
            };
        }
        
        @Override
        public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
            return this.delegate.getAsyncUncaughtExceptionHandler();
        }
    }

}

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)type: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions