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

Posted

技术标签:

【中文标题】同一包中的 @Around @Aspect 仅适用于 @DependsOn【英文标题】:@Around @Aspect in the same package only works with @DependsOn 【发布时间】:2018-09-26 12:12:00 【问题描述】:

请查看下面的更新。


我有一个接受 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 
                    ...
                
            
    


现在这可以正常工作了。但是当我向myMethod介绍AspectJ时:

@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 未被调用,线程被阻塞。我错过了什么?

更新:

这就是交易:MyServiceMyServiceImplMyServiceAspect 都在同一个包中。将 MyServiceAspect 移动到另一个包中使其工作。

这是否为任何人敲响了警钟?很高兴将赏金奖励给任何解释这种行为的人。谢谢!

更新 2:

另一个解决方案:在MyServiceImpl 之上添加@DependsOn(value = "myServiceAspect") 再次解决了这个问题,但仍然想知道为什么。

【问题讨论】:

如果我能看到全貌,我或许可以解释一下:Maven 构建、Sporing 配置、方面和应用程序代码。我需要查看真实的包名和完整代码,而不是带有大量“...”的假包和不完整的方法。您介意在 GitHub 上发布 MCVE 来重现您的问题吗? 【参考方案1】:

实际问题

正如Alexander Paderin >> 在他对afterPropertiesSet() 中相关question >> 无限循环的回答中所描述的那样,线程阻塞器是线程阻止程序,因为在此控制没有返回到 Spring案例。

1。您的示例的工作示例(问题编辑后不实际)

您提供的代码示例不直接包含问题,AspectJ 声明很好。

首先,请让我分享一下工作示例:spring-aspectj-sockets。它基于 Spring 5.1.0AspectJ 1.9.1(当前最新版本)并使用您的示例,独立于 MyServiceAspect 的位置/包工作。


2。问题说明

2.1。简介

您的示例中最可能的线程阻止程序是对ServerSocket.accept() 的调用,该方法的javadocs 说:

侦听要与此套接字建立的连接并接受它。 该方法一直阻塞,直到建立连接。

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,如 question >> 中所述 并使用IDE连接到指定的调试端口(Eclipse的步骤在同一个问题中描述)

【讨论】:

P.S.:@hasan-can-saral,如果这没有帮助,您能否提供一些额外的信息/代码示例。 感谢您的回答,但我正在寻找针对我的具体问题的解决方案,而您的回答主要是ServerThread?所以这是非常无关紧要的。我正在尝试复制该问题并将其发布到 GitHub。你看到更新了吗?除此之外,我的套接字实现没有任何问题。 @HasanCanSaral,谢谢你的更新,但是信息还不够,不清楚你是如何从Socket socket = serverSocket.accept();这一行实例化你身边的serverSocket的,让我等一下然后是 MCVE。 到目前为止,我已经在示例中使用了您的所有代码示例,这些示例独立于 MyServiceAspect 的包。 再次更新问题。我在InitializingBeanafterPropertiesSet 方法中初始化ServerSocket

以上是关于同一包中的 @Around @Aspect 仅适用于 @DependsOn的主要内容,如果未能解决你的问题,请参考以下文章

Spring入门之AOP实践:@Aspect + @Pointcut + @Before / @Around / @After

为啥 Java 中的“protected”修饰符允许访问同一包中的其他类?

SPRING IN ACTION 第4版笔记-第四章ASPECT-ORIENTED SPRING-007-定义切面的around advice

同一包中的Matlab调用函数

定义只能从同一包中的后代访问的方法

从同一包中的过程返回特定事物的函数[关闭]