@Around @Aspect в том же пакете работает только с @DependsOn - PullRequest
0 голосов
/ 26 сентября 2018

Пожалуйста, смотрите обновления ниже.


У меня есть приложение Spring Boot, где я принимаю соединения TCP / IP:

   public MyClass implements InitializingBean {
   @Override
    public void afterPropertiesSet() throws Exception {

        try (ServerSocket serverSocket = new ServerSocket(port)) {

            while (true) {

                Socket socket = serverSocket.accept();                   
                new ServerThread(socket).start();
            } 
        }
    }

    ...

    private class ServerThread extends Thread {
            @Override
            public void run() {
                try (InputStream input = socket.getInputStream();
                     OutputStream output = socket.getOutputStream()) {

                     // Read line from input and call a method from service:
                     service.myMethod(lineConvertedToMyObject);

                } catch {
                    ...
                }
            }
    }

}

Теперь это работаетхорошо, как оно есть.Но когда я представляю AspectJ для myMethod:

@Aspect
@Component
public class MyServiceAspect {

    private static final Logger logger = LoggerFactory.getLogger(MyServiceAspect.class);

    @Around(value = "execution(* com.package.to.MyService.myMethod(..))")
    public MyObject rules(ProceedingJoinPoint joinPoint) throws Throwable {

        long startTime = System.currentTimeMillis();

        MyObject obj = (MyObject) joinPoint.proceed();

        logger.debug("Took {} milliseconds", System.currentTimeMillis() - startTime);

        return obj;
    }
}

service.myMethod не вызывается и поток блокируется.Чего мне не хватает?

Обновление:

Итак, сделка: MyService, MyServiceImpl и MyServiceAspect все в одном пакете.Перемещение MyServiceAspect в другой пакет заставило его работать.

Это кому-нибудь звонит?Рад присуждать награду любому, кто объяснит это поведение.Спасибо!

Обновление 2:

Еще одно решение: добавление @DependsOn(value = {"myServiceAspect"}) поверх MyServiceImpl снова решает проблему, хотя все еще задается вопросом, почему.

1 Ответ

0 голосов
/ 30 сентября 2018

Фактическая проблема

Как это было описано Александр Падерин >> в своем ответе на связанный вопрос >> бесконечный цикл в afterPropertiesSet() былблокировщик потоков, так как в этом случае управление не вернулось к Spring .

1.Рабочий пример с вашими примерами (не актуален после редактирования вопроса)

Предоставленные вами примеры кода не содержат проблем напрямую, AspectJ объявление в порядке.

Прежде всегоПожалуйста, позвольте мне поделиться рабочим примером: spring-aspectj-sockets .Он основан на Spring 5.1.0 и AspectJ 1.9.1 (в настоящее время последние версии) и использует ваши образцы, работает независимо от местоположения / пакета MyServiceAspect.


2.Объяснение проблемы

2.1.Intro

Наиболее вероятным блокировщиком потоков в ваших примерах является вызов ServerSocket.accept(), javadocs для этого метода говорит:

Прослушивает подключение к этому сокету и принимаетЭто. Метод блокируется до установления соединения.

Существует 2 правильных способа обработки accept():

  1. Инициализация соединениясначала, например:

    serverSocket = new ServerSocket(18080);
    clientSocket = new Socket("127.0.0.1", 18080); // initializing connection
    Socket socket = serverSocket.accept(); // then calling accept()
    
  2. Установить тайм-аут для ожидания приема:

    serverSocket = new ServerSocket(18080);
    serverSocket.setSoTimeout(5000); // 5 seconds timeout
    Socket socket = serverSocket.accept(); // then calling accept()
    

    ПРИМЕЧАНИЕ : если в течение 5 секунд произойдетЕсли соединения отсутствуют, accept() выдаст исключение, но не заблокирует поток

2.2.Предположение

Я предполагаю, что вы используете 1-й подход, и где-то у вас есть строка, которая инициализирует соединение, т.е. clientSocket = new Socket("127.0.0.1", 18080);.

Но она вызывается (например, если используются статические объявления)):

  • После serverSocket.accept() в случае, если MyServiceAspect находится в той же упаковке и
  • До - в случае MyServiceAspect в другом месте

3.Отладка

Я не уверен, если это необходимо, есть сомнения из-за описания Баунти, на всякий случай позвольте мне рассказать об этом. - он будет охватывать аспекты, дочерние потоки, службы и т. Д. - вам потребуется только:

  1. Выполнить Java с конкретными аргументами, как описано в этом вопрос >>
  2. и подключение к указанному порту отладки с помощью IDE (шаги для Eclipse описаны в том же вопросе)
...