简体   繁体   中英

Cannot autowire service into implementation of AsyncUncaughtExceptionHandler

I have a problem with spring autowiring. I've got a class that implements AsyncUncaughtExceptionHandler.

@Component
public class MyExceptionHandler implements AsyncUncaughtExceptionHandler {

    @Autowired
    MyService myService;

    @Override
    public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
        if (throwable instanceof MyException) {
            myService.handleException((MyException) throwable);
        } else {
            //...
        }
    }

When the code runs into the places where myService is called, Nullpointer is thrown as myService is null. MyService is autowired on other places without any problem, only autowiring in the implementation of AsyncUncaughtExceptionHandler seems to cause issues.

@Service
public class MyService {

    public void handleException(MyException e) {
        //...
    }
}

I've been through some questions on StackOverflow, which solved similar problems. Those problems were caused by proxy mechanisms, but I did not manage to make the code work. Also, I am not sure if this is the problem.

Any help is appreciated. Thanks in advance.

You need to mark MyExceptionHandler as a bean as well:

@Component
public class MyExceptionHandler implements AsyncUncaughtExceptionHandler {

Mistake was actually on my side in configuration of asyncExceptionHandler.

had to change this:

@Configuration
@EnableAsync
@ComponentScan
public class AsyncConfiguration implements AsyncConfigurer {

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new RccAsyncExceptionHandler();
    }
}

into this:

@Configuration
@EnableAsync
@ComponentScan
public class AsyncConfiguration implements AsyncConfigurer {

    @Autowired
    MyExceptionHandler rccAsyncExceptionHandler;

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return rccAsyncExceptionHandler;
    }
}

Rookie mistake, but I couldn't find it for very long time.

What is happening here is,

  1. The async code is run on a separate thread(Hence @ComponentScan to see and initialize new threads).
  2. By default all beans are singleton (see bean scope in spring for more details). Since the new thread runs in a different container. It wont get the reference of the service bean and hence null.
  3. Why did @ComponentScan not handle it? Component scan is mostly scanning a subset of packages and the service may be defined in a different package.

Solution: Make the service bean application scope using @ApplicationScope annotation.

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