为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

侃侃无极 2021-10-13 10:57:12
请参阅下面的更新。我有一个接受 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@Componentpublic 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 回答

?
杨魅力

TA贡献1811条经验 获得超6个赞

实际问题

正如亚历山大帕德林>>在他对相关问题的回答中所描述的那样>>无限循环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 connection

Socket socket = serverSocket.accept(); // then calling accept()

设置超时等待接受:


serverSocket = new ServerSocket(18080);

serverSocket.setSoTimeout(5000); // 5 seconds timeout

Socket 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 的步骤在同一问题中描述)


查看完整回答
反对 回复 2021-10-13
  • 1 回答
  • 0 关注
  • 175 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信