Spring AOP передает строковый аргумент метода контроллера

У меня есть класс контроллера с одним методом RequestMapping, который принимает строковые аргументы. Я хочу передать этот аргумент с помощью Spring AOP, но это не удается, я получаю нулевое значение, когда печатаю значение.

Пробовал с приведенным ниже решением, но он работает с картой, но не со строкой.

Аргумент передачи Spring AOP метода контроллера

@Controller
public class WelcomeController {
    @Autowired
    private FamilyService familyService;

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public ModelAndView welcomePage(String welcomeMessage) {
        FamilyVO allFamilyMembers = familyService.getAllFamilyMembers();
        ModelAndView modelAndView = new ModelAndView("Index", "family", allFamilyMembers);
        List<String> familyMemberAges = new ArrayList<String>();
        for (int i = 0; i <= 100; i++) {
            familyMemberAges.add("" + i);
        }
        modelAndView.addObject("familyMemberAges", familyMemberAges);
        System.out.println(welcomeMessage);
        return modelAndView;
    }
}
@Component
@Aspect
public class WelcomeControllerAspect {
    @Before("execution(* com.kalavakuri.webmvc.web.controller.WelcomeController.welcomePage(..))")
    public void beforeWelcomePage(JoinPoint joinPoint) {
        joinPoint.getArgs()[0] = "Hellow";
        System.out.println(joinPoint.getArgs().length);
        System.out.println("Before welcomepage");
    }
}

Я ожидаю значение «Привет», когда я печатаю его в классе контроллера, но печатаю ноль.


person user995656    schedule 14.05.2019    source источник


Ответы (2)


Совет @Before не предназначен для управления параметрами метода. В примере, который вы связали с ним, он работает только потому, что аргумент является изменяемым объектом, а именно Map. String неизменяем, но вы не можете его редактировать.

Сказав это, что вы должны делать? Используйте совет @Around, который был разработан для такого рода вещей. Там вы можете решить, как вы хотите действовать, например.

  • вызвать исходный метод с исходными параметрами,
  • вызвать исходный метод с измененными параметрами,
  • сделать что-то до и/или после вызова оригинала,
  • не вызывайте исходный метод, а вместо этого возвращайте другой результат,
  • обрабатывать исключения в исходном методе
  • или любое сочетание вышеперечисленного, которое имеет смысл (возможно, у вас есть несколько случаев и if-else или switch-case).

Я также предлагаю не работать напрямую с Object[] из JoinPoint.getArgs(), а связать соответствующий параметр(ы) метода с именованным и типобезопасным параметром совета через args(). Попробуй это:

package de.scrum_master.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class WelcomeControllerAspect {
  @Around(
    "execution(* com.kalavakuri.webmvc.web.controller.WelcomeController.welcomePage(..)) && " +
    "args(welcomeMessage)"
  )
  public Object beforeWelcomePage(ProceedingJoinPoint joinPoint, String welcomeMessage) throws Throwable {
    System.out.println(joinPoint + " -> " + welcomeMessage);
    return joinPoint.proceed(new Object[] { "Hello AOP!" });
  }
}
person kriegaex    schedule 15.05.2019

Вы должны использовать совет @Aroung вместо @Before. Подробнее см. этот ответ.

person Gustavo Passini    schedule 15.05.2019