Frühjahr async funktioniert nicht, wenn implementiert AsyncConfigurer
Having a Spring-Konfiguration-Klasse für den asynchronen Methoden wie:
@Configuration
@EnableAsync(proxyTargetClass = true)
@EnableScheduling
public class AsyncConfiguration {
@Autowired
private ApplicationContext applicationContext;
@Bean
public ActivityMessageListener activityMessageListener() {
return new ActivityMessageListener();
}
@Bean
public TaskExecutor defaultExecutor()
{
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setCorePoolSize(10);
threadPoolTaskExecutor.setMaxPoolSize(10);
threadPoolTaskExecutor.setQueueCapacity(Integer.MAX_VALUE);
return threadPoolTaskExecutor;
}
Alle meine @Async
Methoden arbeitet wie erwartet, aber wenn ich implementieren AsyncConfigurer
in AsyncConfiguration
um zum abfangen von Ausnahmen Umsetzung getAsyncUncaughtExceptionHandler()
Methode, meine Bohnen sind nicht proxyweiterleitung so Methoden @Async
läuft nicht in einem pool Testamentsvollstrecker.
Dies ist die nicht-funktionierenden Konfiguration:
@Configuration
@EnableAsync(proxyTargetClass = true)
@EnableScheduling
public class AsyncConfiguration implements AsyncConfigurer {
@Autowired
private ApplicationContext applicationContext;
@Bean
public ActivityMessageListener activityMessageListener() {
return new ActivityMessageListener();
}
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setCorePoolSize(10);
threadPoolTaskExecutor.setMaxPoolSize(10);
threadPoolTaskExecutor.setQueueCapacity(Integer.MAX_VALUE);
return threadPoolTaskExecutor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SimpleAsyncUncaughtExceptionHandler();
}
Was könnte passiert sein?
Sind wir mit @Async
wie diese:
public class ActivityMessageListener extends BaseMessageListener {
public static final String PARAM_USER_ID = "userId";
public static final String PARAM_COMPANY_ID = "companyId";
public static final String PARAM_CREATE_DATE = "createDate";
public static final String PARAM_CLASS_NAME = "className";
public static final String PARAM_CLASS_PK = "classPK";
public static final String PARAM_TYPE = "type";
public static final String PARAM_EXTRA_DATA = "extraData";
public static final String PARAM_RECEIVED_USER_ID = "receiverUserId";
@Override @Async(value = "defaultExecutor")
public Future<String> doReceive(Message message) throws Exception {
String name = Thread.currentThread().getName();
Map<String, Object> parameters = message.getValues();
Long userId = (Long)parameters.get(ActivityMessageListener.PARAM_USER_ID);
Long companyId = (Long)parameters.get(ActivityMessageListener.PARAM_COMPANY_ID);
Date createDate = (Date)parameters.get(ActivityMessageListener.PARAM_CREATE_DATE);
String className = (String)parameters.get(ActivityMessageListener.PARAM_CLASS_NAME);
Long classPK = (Long)parameters.get(ActivityMessageListener.PARAM_CLASS_PK);
Integer type = (Integer)parameters.get(ActivityMessageListener.PARAM_TYPE);
String extraData = (String)parameters.get(ActivityMessageListener.PARAM_EXTRA_DATA);
Long receiverUserId = (Long)parameters.get(ActivityMessageListener.PARAM_RECEIVED_USER_ID);
ActivityLocalServiceUtil.addActivity(userId, companyId, createDate, className, classPK, type, extraData, receiverUserId);
return new AsyncResult<String>(name);
}
}
- Denn es ist eine config-time-Klasse, die sollte nicht umgesetzt werden, indem Ihre eigentlichen Klassen, die sind async, Sie sind für die Konfiguration der asynchronen Verarbeitung.
- Sorry, aber ich verstehe nicht, könnte Sie erweitern Ihre Antwort?
- Die
AsyncConfigurer
wenn für die Konfiguration der asynchronen Infrastruktur sollte es werden, implementiert durch configuration beans " NOTY Ihren Dienst Bohnen. - Ah ok, ja, es ist, was ich Tue, scheint das problem wenn ich
AsyncConfiguration
im Hinblick auf die DurchführungAsyncConfigurer
- Dann post, dass die Konfiguration statt, der nicht arbeitet. Bitte fügen Sie, was Sie versucht haben.
- Entfernen
@Bean
von der override-Methoden. - Aktualisiert. Ich hoffe die Frage ist klar jetzt
- Lassen Sie uns weiter, diese Diskussion im chat.
- Ich stehe vor den gleichen Fragen. Hat das einer schon gelöst?
Du musst angemeldet sein, um einen Kommentar abzugeben.
EDIT: ich eingereicht haben ein bug-report (SPR-14630).
Ich war am Rande der du einen bug-report zu Spring issue-tracker, aber wenn ich beschäftigt war, eine kleine app für die Reproduktion der Fehler, die ich gefunden und das problem behoben.
Zunächst alle, bei Verwendung
ThreadPoolTaskExecutor
, sollten Sie rufen Ihreinitialize()
Methode, bevor er es wieder:Auch aus irgendeinem Grund, wenn ich eine Bohne in ein
@PostConstruct
- Methode definiert, in der gleichen Konfiguration Klasse, es wird nicht laufen asynchron. Der Grund dafür ist, dass die@PostConstruct
Methode wird ausgeführt, bevorgetAsyncExecutor()
undgetAsyncUncaughtExceptionHandler()
ausgeführt werden:AsyncBean.java
:AsyncDemoApp.java
:Ausgabe:
Jedoch, wenn Sie Ihre Bohnen nach der Anwendungskontext ist gebrauchsfertig, es sollte alles wie erwartet funktionieren:
Weiteres komisches Verhalten ist, dass, wenn Sie autowire die asynchrone bean in der gleichen configuration-Klasse, das auto-Bordnetz ist passiert, bevor die benutzerdefinierten async Testamentsvollstrecker ist so konfiguriert, dass die Bohne nicht asynchron laufen soll und es läuft im Haupt-thread. Dies kann überprüft werden, indem ein
@PostConstruct
zuAsyncBean
und mit einemCommandLineRunner
zum ausführen der app (ich persönlich denke, das ist ein bug. Das Verhalten ist sehr verwunderlich, um das Mindeste zu sagen):AsyncBean
mit@PostConstruct
:AsyncDemoApp
UmsetzungCommandLineRunner
:Ausgabe:
Noch eins! 🙂 Wenn Sie
ThreadPoolTaskExecutor
je nach Ihren Anforderungen möchten Sie vielleicht, um Ihre daemon-Eigenschaft auf true, andernfalls wird Ihre app am laufen halten ewig (das ist nicht ein großes problem für Web/Worker-apps). Hier ist, was die JavaDoc vonsetDaemon(boolean)
sagt: