LoggingAspect - WebServiceTemplate.marshalSendAndReceive

问题描述

我正在尝试在调用 marshalSendAndReceive 时记录 Web 服务操作。这样我就可以记录任何使用 marshalSendAndReceive 的网络服务调用,如下所示。但不知何故下面的 logWebserviceOperation 没有被调用。我的@Before .. 有什么问题吗?或者我错过了什么。

package com.julia;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletinitializer;

@SpringBootApplication
public class Application extends SpringBootServletinitializer {
    
    public static void main(String[] args) {
        
        SpringApplication.run(Application.class,args);
        
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

}
package com.julia.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.ws.transport.http.HttpComponentsMessageSender;

import com.julia.service.soAPConnector;

import static com.julia.config.ApplicationConstants.CONTEXT_PATH_1;  //contstants to set the Jaxb context path
import static com.julia.config.ApplicationConstants.CONTEXT_PATH_2;
import static com.julia.config.ApplicationConstants.CONTEXT_PATH_3;

@Configuration
@RefreshScope
public class ParserConfig {
    
    @Value("${application.WSSessionTimeoutInMilliSec}")
    private int timeout;
    
    @Bean
    public Jaxb2Marshaller marshaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        marshaller.setPackagesToScan(CONTEXT_PATH_1,CONTEXT_PATH_2,CONTEXT_PATH_3);
        return marshaller;
    }

    @Bean
    public SOAPConnector soapConnector(Jaxb2Marshaller marshaller) {
        SOAPConnector client = new SOAPConnector();
        client.setMarshaller(marshaller);
        client.setUnmarshaller(marshaller);

        HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender();
        messageSender.setConnectionTimeout(timeout);

        client.setMessageSender(messageSender);
        
        return client;
    }
    
}
package com.julia.service;

import java.io.IOException;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.ws.client.core.WebServiceMessageCallback;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.transport.context.TransportContext;
import org.springframework.ws.transport.context.TransportContextHolder;
import org.springframework.ws.transport.http.HttpUrlConnection;

@Service
@RefreshScope
public class SOAPConnector extends WebServiceGatewaySupport {

    private static final Logger LOGGER = LogManager.getLogger(SOAPConnector.class);
    
    public Object callWebService(String url,Object request) {
        return getwebservicetemplate().marshalSendAndReceive(url,request);
    }
}
package com.julia.logging;

import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.sqlParameterValue;
import org.springframework.jdbc.core.namedparam.MapsqlParameterSource;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    private static final Logger LOGGER = LogManager.getLogger(LoggingAspect.class);

    public LoggingAspect() {
    }
    
    @Before("execution(* org.springframework.ws.client.core.webservicetemplate.marshalSendAndReceive(..))")
    public void logWebserviceOperation(JoinPoint jp) {
        Object[] methodArgs = jp.getArgs();
        String uri = methodArgs[0].toString();
        String payload = String.valueOf(methodArgs[1]);
        LOGGER.log("uri:" + uri);
        LOGGER.log("payload :" + payload);
    }

解决方法

Spring AOP 只能通知 Spring 容器管理的 bean。

从共享的代码来看,建议所针对的 WebServiceTemplate 实例不是 Spring bean。

public Object callWebService(String url,Object request) {
    return getWebServiceTemplate().marshalSendAndReceive(url,request);
}

WebServiceGatewaySupport.getWebServiceTemplate() 方法是从哪里获得 WebServiceTemplate 实例。默认逻辑是构造一个 new instanceWebServiceTemplate 类。

基于 reference documentation WebServiceTemplateBuilder 可用于创建 WebServiceTemplate bean。

WebServiceGatewaySupport.setWebServiceTempate() 然后可用于设置 bean。这样做时,请务必阅读 notes

或者,您可以建议 SOAPConnector.callWebService(..) 应该为您提供相同的日志。

@Before("execution(* com.julia.service.SOAPConnector.callWebService(..)) && args(url,request)")
    public void logWebserviceOperation(JoinPoint jp,String url,Object request) {
        LOGGER.log("uri:" + url);
        LOGGER.log("payload :" + request);
    }