Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何编写方面以适应不同的对象和方法参数_Java_Spring_Aop_Aspectj - Fatal编程技术网

Java 如何编写方面以适应不同的对象和方法参数

Java 如何编写方面以适应不同的对象和方法参数,java,spring,aop,aspectj,Java,Spring,Aop,Aspectj,我希望编写一个方面,它可以根据方法中传递的某些值来模拟数据。此模拟将替换实际的REST调用。如果值不匹配,则返回实际方法并调用REST端点 我已经编写了一个方面,它在生产环境中工作,但非常混乱,必须在其中实现多个不同的方法,以适应返回不同对象和处理不同方法参数的需要。是否有一种方法可以将其推广,这样我就可以像一个方法一样执行工作,并且能够在将来的情况下使用if,而不必担心对象类型和方法签名 目前的执行情况如下。我如何修改它,使之成为一种单一的方法,能够适应未来的方法和响应类型,而不必改变我的方面

我希望编写一个方面,它可以根据方法中传递的某些值来模拟数据。此模拟将替换实际的REST调用。如果值不匹配,则返回实际方法并调用REST端点

我已经编写了一个方面,它在生产环境中工作,但非常混乱,必须在其中实现多个不同的方法,以适应返回不同对象和处理不同方法参数的需要。是否有一种方法可以将其推广,这样我就可以像一个方法一样执行工作,并且能够在将来的情况下使用if,而不必担心对象类型和方法签名

目前的执行情况如下。我如何修改它,使之成为一种单一的方法,能够适应未来的方法和响应类型,而不必改变我的方面

为了澄清这一点,我有以下3种方法,我想用Aspect模拟它们。如您所见,我有一个自定义注释,它接受一个名称。该方法的参数都没有对齐

@MyMock(name = "ABC")
public AResponse getAResponse(ARequest aRequest){
    // make a REST call
}

@MyMock(name = "DEF")
public BResponse getBResponse(String fruit, BRequest bRequest){
    // make a REST call
}

@MyMock(name = "GHJ")
public CResponse getCResponse(String vehicle, CRequest cRequest, int id){
    // make a REST call
}
当前的方面类如下所示。我在注释中使用name值来确定调用哪个方法以及返回哪个值类型。正如您所看到的,这不是非常可伸缩的。每次实现新的mock时,我都需要编写一个新的方法和逻辑

@Around("@annotation(myMock)")
public Object getMockedData(ProceedingJoinPoint pjp, MyMock myMock) throws Throwable {
    String servName = performMocking.name();
    Object[] methodArguments = pjp.getArgs();
    MethodSignature signature = (MethodSignature) pjp.getSignature();
    Class returnType = signature.getReturnType();

    switch (myMock.name()) {
        case "ABC":
        getA(methodArguments[0]);
        break;
        case "DEF":
        getB(methodArguments[0]);
        break;
        case "GHJ":
        getC(methodArguments[2]);
        break;
    }
    return pjp.proceed(methodArguments);
}

private AResponse getA(ARequest aRequest){
     // I use methodArguments[0] (which is aRequest) to decide what value to return as a mock response here.
     // There is a getName value in that object which I use to reference  
}

private BResponse getB(BRequest bRequest){
     // I use methodArguments[0] (which is a String) to decide what value to return as a mock response here. 
}

private CResponse getC(CRequest cRequest){
     // I use methodArguments[2] (which is an int) to decide what value to return as a mock response here. 
}
上述所有get方法都会调用外部JSON文件来获取模拟数据。文件内容如下。如果键匹配,将给出模拟响应,否则返回实际的REST调用

{
    "ABC": {
        "enabled": "true",
        "responses": [
            {
                "a_name": "{some valid json response matching the AResponse Object structure}"
            }
        ]
    },
    "DEF": {
        "enabled": "true",
        "responses": [
            {
                "d_name": "{some valid json response matching the BResponse Object structure}"
            }
        ]
    },
    "GHJ": {
        "enabled": "true",
        "responses": [
            {
                "123": "{some valid json response matching the CResponse Object structure}"
            }
        ]
    }
}
编辑:添加了我的方面类,如下所示:

package com.company.a.b.mock;

import com.domain.abc.b.logging.util.MyLogger;
import com.domain.abc.a.util.generic.ConfigHelper;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

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

@Aspect
@Component
public class AspectMocking {

    private final ConfigHelper configHelper;
    private final MyLogger myLogger;

    public AspectMocking(ConfigHelper configHelper, MyLogger myLogger) {
        this.configHelper = configHelper;
        this.myLogger = myLogger;
    }

    @Around("@annotation(myMock)")
    public Object getMockedData(ProceedingJoinPoint pjp, MyMock myMock) throws Throwable {

        final String env = System.getProperty("spring.profiles.active");
        String response = null;
        Object returnObject = null;
        String logMessage = null;
        String servName = myMock.name();
        Object[] methodArguments = pjp.getArgs();
        try {
            if ("test_env1".equals(env) || "test_env2".equals(env)) {

                MethodSignature signature = (MethodSignature) pjp.getSignature();
                Class returnType = signature.getReturnType();

                Map allDataFromMockedFile = getMockedDataFromFile();
                Map getResultForKey = (Map) allDataFromMockedFile.get(myMock.name());

                List result = null;
                if(getResultForKey != null){
                    result  = (List) getResultForKey.get("responses");
                }

                switch (myMock.name()) {
                case "ABC":
                    response = fetchABCMockedData(result, (String) methodArguments[0]);
                    logMessage = "Fetching ABC mock data for ABC Response: " + response;
                    break;
                case "V2_ABC":
                    response = fetchABCMockedData(getIntlResult(myMock.name(), (String)methodArguments[2]), (String) methodArguments[0]);
                    logMessage = "Fetching V2 ABC mock data for V2 ABC Response: " + response;
                    break;
                case "DEF":
                    response = fetchDEFMockedData(result, (String) methodArguments[0]);
                    logMessage = "Fetching DEF mock data: " + response;
                    break;
                case "GHJ":
                    response = fetchGHJMockedOfferData(result, (String) methodArguments[0], (String) methodArguments[1], (String) methodArguments[2]);
                    logMessage = "Fetching GHJ mock data: " + response;
                    break;
                }

                ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
                returnObject = mapper.readValue(response, returnType);
            }
        } catch (Exception exp) {
            myLogger.addMessageAsWarning(String
                    .format("Exception occured for service %s while loading the mocked json, so hitting the actual service:"
                            + exp.getMessage(), servName));
        }

        if (returnObject == null) {
            returnObject = pjp.proceed(methodArguments);
        }

        myLogger.addMessage(logMessage);
        return returnObject;
    }


    private List getIntlResult(String name, String locale){
        Map localBasedMockFile = getMockedDataFromFile(locale.toLowerCase());
        Map localeSpecificMockedData = (Map) localBasedMockFile.get(name);
        return (List) localeSpecificMockedData.get("responses");
    }

    // had to add this recently as we needed locale values now to go to a diff file. 
    private Map getMockedDataFromFile(String countryCode){
        final String DATA_URL = String.format("/a/b/c/%s/data.json", countryCode);
        return configHelper.getMAVDataAsObject(DATA_URL, Map.class);
    }

    private Map getMockedDataFromFile() {
        final String DATA_URL = "/a/b/c/zh/mock.json";
        return configHelper.getMAVDataAsObject(DATA_URL, Map.class);
    }

    private String fetchABCMockedData(List<Map> allResponses, String vinNumber) throws IOException {
        String response = null;
        for (Map m : allResponses) {
            String mockedVinNumber = m.keySet().toString().replaceAll("[\\[\\]]", "");
            if (vinNumber.equals(mockedVinNumber)) {
                response = (String) m.get(mockedVinNumber);
            }
        }
        return response;
    }

    private String fetchDEFMockedData(List<String> allResponses, String vinNumber) {
        return allResponses.contains(vinNumber) ? "true" : "false";
    }

    private String fetchGHJMockedOfferData(List<Map> allResponses, String journey, String name, String pin) {
        String response = null;
        String key = journey+"_"+name + "_" + pin;

        for (Map m : allResponses) {
            String mockedKey = m.keySet().toString().replaceAll("[\\[\\]]", "");
            if (mockedKey.equals(key)) {
                response = (String) m.get(mockedKey);
            }
        }

        return response;
    }
}
package com.company.a.b.mock;
导入com.domain.abc.b.logging.util.MyLogger;
导入com.domain.abc.a.util.generic.ConfigHelper;
导入com.fasterxml.jackson.databind.DeserializationFeature;
导入com.fasterxml.jackson.databind.ObjectMapper;
导入org.aspectj.lang.ProceedingJoinPoint;
导入org.aspectj.lang.annotation.Around;
导入org.aspectj.lang.annotation.Aspect;
导入org.aspectj.lang.reflect.MethodSignature;
导入org.springframework.stereotype.Component;
导入java.io.IOException;
导入java.util.List;
导入java.util.Map;
@面貌
@组成部分
公共类AspectMocking{
私有最终ConfigHelper ConfigHelper;
私人最终MyLogger MyLogger;
公共AspectMocking(ConfigHelper ConfigHelper、MyLogger MyLogger){
this.configHelper=configHelper;
this.myLogger=myLogger;
}
@周围(“@annotation(myMock)”)
公共对象getMockedData(ProceedingJoinPoint pjp,MyMock MyMock)抛出可丢弃的{
最终字符串env=System.getProperty(“spring.profiles.active”);
字符串响应=null;
objectreturnobject=null;
字符串logMessage=null;
字符串servName=myMock.name();
Object[]methodArguments=pjp.getArgs();
试一试{
if(“test_env1.equals(env)| |“test_env2.equals(env)){
MethodSignature=(MethodSignature)pjp.getSignature();
类returnType=signature.getReturnType();
Map allDataFromMockedFile=getMockedDataFromFile();
Map GetResultWorkey=(Map)allDataFromMockedFile.get(myMock.name());
列表结果=空;
if(GetResultWorkey!=null){
结果=(列表)getResultWorkey.get(“响应”);
}
开关(myMock.name()){
案例“ABC”:
response=fetchABCMockedData(result,(String)methodArguments[0]);
logMessage=“为ABC响应获取ABC模拟数据:”+响应;
打破
案例“V2_ABC”:
response=fetchABCMockedData(getIntlResult(myMock.name(),(String)methodArguments[2]),(String)methodArguments[0]);
logMessage=“为V2 ABC响应获取V2 ABC模拟数据:”+响应;
打破
案例“DEF”:
response=fetchDEFMockedData(result,(String)methodArguments[0]);
logMessage=“获取DEF模拟数据:”+响应;
打破
案例“GHJ”:
response=fetchGHJMockedOfferData(result,(String)methodArguments[0],(String)methodArguments[1],(String)methodArguments[2]);
logMessage=“获取GHJ模拟数据:”+响应;
打破
}
ObjectMapper mapper=new ObjectMapper().configure(UNKNOWN属性上的反序列化feature.FAIL,false);
returnObject=mapper.readValue(响应,returnType);
}
}捕获(异常扩展){
myLogger.addMessageAsWarning(字符串
.format(“加载模拟json时服务%s发生异常,因此命中实际服务:”
+exp.getMessage(),servName));
}
if(returnObject==null){
returnObject=pjp.procedure(methodArguments);
}
myLogger.addMessage(日志消息);
返回对象;
}
私有列表getIntlResult(字符串名称、字符串区域设置){
Map localBasedMockFile=getMockedDataFromFile(locale.toLowerCase());
Map localspecificmockeddata=(Map)localBasedMockFile.get(name);
返回(列表)localspecificmockeddata.get(“响应”);
}
//最近不得不添加这个,因为我们现在需要区域设置值才能转到diff文件。
私有映射getMockedDataFromFile(字符串countryCode){
最终字符串数据\u URL=String.format(“/a/b/c/%s/DATA.json”,countryCode);
返回configHelper.getMAVDataAsObject(数据URL,Map.class);
}
私有映射getMockedDataFromFile(){
最终字符串DATA_URL=“/a/b/c/zh/mock.json”;
返回configHelper.getMAVDataAsObject(数据URL,Map.class);
}
私有字符串fetchABCMo