同一包中的@Around @Aspect 仅适用于@DependsOn

请参阅下面的更新。


我有一个接受 TCP/IP 连接的 Spring Boot 应用程序:


   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再解决问题,仍然不知道为什么,虽然。


侃侃无极
浏览 189回答 1
1回答

杨魅力

实际问题正如亚历山大帕德林>>在他对相关问题的回答中所描述的那样>>无限循环afterPropertiesSet()是线程阻塞器,因为在这种情况下控制权不会返回到Spring。1. 样本的工作示例(问题编辑后不是实际的)您提供的代码示例不直接包含问题,AspectJ声明很好。首先,请让我分享工作示例:spring-aspectj-sockets。它基于Spring 5.1.0和AspectJ 1.9.1(当前最新版本)并使用您的示例,独立于MyServiceAspect.2. 问题说明2.1. 介绍您的示例中最可能的线程阻塞是调用ServerSocket.accept(), 此方法的 javadocs 说:侦听要与此套接字建立的连接并接受它。该方法阻塞,直到建立连接。有2种正确的处理方式accept():首先初始化连接,例如:serverSocket = new ServerSocket(18080);clientSocket = new Socket("127.0.0.1", 18080); // initializing connectionSocket socket = serverSocket.accept(); // then calling accept()设置超时等待接受:serverSocket = new ServerSocket(18080);serverSocket.setSoTimeout(5000); // 5 seconds timeoutSocket socket = serverSocket.accept(); // then calling accept()注意:如果在 5 秒内没有连接,accept()将抛出异常,但不会阻塞线程2.2. 假设我假设您使用的是第一种方法,并且在某处您有一条线来初始化连接,即clientSocket = new Socket("127.0.0.1", 18080);.但它被调用(例如,如果使用静态声明):之后serverSocket.accept()以防万一MyServiceAspect位于同一个包中并且之前 - 以防万一MyServiceAspect位于其他地方3.调试我不确定是否需要这样做,由于赏金的描述而有疑问,让我快速介绍一下以防万一。您可以使用远程调试来调试您的应用程序——它将涵盖方面、子线程、服务等——您只需要:使用此问题中描述的特定参数运行Java >>并使用 IDE 连接到指定的调试端口(Eclipse 的步骤在同一问题中描述)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java