Spring @Async - как протестировать? [Дубликат]

Вы можете использовать эту пользовательскую библиотеку (написанную с помощью Promise) для выполнения удаленного вызова.

function $http(apiConfig) {
    return new Promise(function (resolve, reject) {
        var client = new XMLHttpRequest();
        client.open(apiConfig.method, apiConfig.url);
        client.send();
        client.onload = function () {
            if (this.status >= 200 && this.status < 300) {
                // Performs the function "resolve" when this.status is equal to 2xx.
                // Your logic here.
                resolve(this.response);
            }
            else {
                // Performs the function "reject" when this.status is different than 2xx.
                reject(this.statusText);
            }
        };
        client.onerror = function () {
            reject(this.statusText);
        };
    });
}

Пример простого использования:

$http({
    method: 'get',
    url: 'google.com'
}).then(function(response) {
    console.log(response);
}, function(error) {
    console.log(error)
});
7
задан ilopezluna 2 February 2015 в 23:26
поделиться

1 ответ

Tricky.

Асинхронное поведение добавляется через проксирование.

Spring предоставляет вам прокси-сервер, который обертывает фактический объект и выполняет фактический вызов в отдельном потоке.

Это выглядит примерно так (за исключением того, что большинство из них выполняется динамически с помощью прокси-серверов CGLIB или JDK и обработчиков Spring)

class ProxyListener extends ActivityMessageListener {
    private ActivityMessageListener real;
    public ProxyListener(ActivityMessageListener real) {
        this.real = real;
    }
    TaskExecutor executor; // injected
    @Override
    public void doReceive(Message message) throws Exception {
        executor.submit(() -> real.doReceive(message)); // in another thread
    }
}

ActivityMessageListener real = new ActivityMessageListener();
ProxyListener proxy = new ProxyListener(real);

Теперь, в весеннем мире, у вас будет ссылка на объект proxy, а не на ActivityMessageListener. Это

ActivityMessageListener proxy = applicationContext.getBean(ActivityMessageListener.class);

вернет ссылку на ProxyListener. Затем через полиморфизм вызов doReceive перейдет к методу overriden Proxy#doReceive, который будет вызывать ActivityMessageListener#doReceive посредством делегирования, и вы получите свое асинхронное поведение.

Однако вы находитесь в половине Весенний мир.

Здесь

public ActivityMessageListener() {
    MessageBusUtil.addQueue(MKTDestinationNames.ACTIVITY_REGISTRY, this);
}

ссылка this на самом деле относится к реальному ActivityMessageListener, а не к прокси. Поэтому, когда, предположительно, вы отправляете свое сообщение на автобусе здесь

MessageBusUtil.sendMessage(MKTDestinationNames.ACTIVITY_REGISTRY,      message);

, вы отправляете его реальному объекту, который не имеет асинхронного поведения прокси.

Полное решение Spring будет состоять в том, чтобы MessabeBus (и / или его очередь) были Spring beans, в которые вы можете вводить полностью обработанные (проксированные, автоувещенные, инициализированные) bean-компоненты.


На самом деле, поскольку прокси-серверы CGLIB - это действительно просто подклассы ваших типов, поэтому ProxyListener выше действительно добавит себя к шине, так как будет вызываться конструктор super. Казалось бы, только один MessageListener может зарегистрировать себя с помощью ключа, например MKTDestinationNames.ACTIVITY_REGISTRY. Если это не так, вам нужно будет показать больше этого кода для объяснения.


В вашем тесте, если вы делаете

activityMessageListener.doReceive(message);

, вы должны см., что асинхронное поведение, поскольку activityMessageListener должно содержать ссылку на прокси.

3
ответ дан Sotirios Delimanolis 27 August 2018 в 02:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: