Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 线程中未触发Spring AOP方面_Multithreading_Spring_Aop - Fatal编程技术网

Multithreading 线程中未触发Spring AOP方面

Multithreading 线程中未触发Spring AOP方面,multithreading,spring,aop,Multithreading,Spring,Aop,在线程运行之前调用的每个方法都可以正常工作,但在启动线程之后,它不会进入方面 我使用JDK动态代理对象来实现接口, 从其他线程而不是从对象本身调用的所有公共方法 我正在使用Spring3.0.6 请帮我理解我错过了什么 方面: @Aspect public class CabLoggingAspect { public void init() { System.out.println("CabLoggingAspect: init()"); } @P

在线程运行之前调用的每个方法都可以正常工作,但在启动线程之后,它不会进入方面

我使用JDK动态代理对象来实现接口, 从其他线程而不是从对象本身调用的所有公共方法

我正在使用Spring3.0.6

请帮我理解我错过了什么

方面:

@Aspect 
public class CabLoggingAspect {

    public void init() {
        System.out.println("CabLoggingAspect: init()");
    }

    @Pointcut("execution(* com.station.taxi.ICab.*(..))")
    public void anyCall() { }

    @Before("anyCall()")
    public void logAnyCall(JoinPoint joinPoint) {
        System.out.println("CabLoggingAspect: logAnyCall(): "+joinPoint.getSignature().getName());
    }
}
弹簧配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">

    <bean id="cab" class="com.station.taxi.Cab" scope="prototype" />    
    <aop:aspectj-autoproxy>
        <aop:include name="cabLoggingAspect"/>
    </aop:aspectj-autoproxy>
    <!-- AspectJ -->
    <bean id="cabLoggingAspect" class="com.station.taxi.aop.CabLoggingAspect" init-method="init"/>
</beans>
正在运行的线程:

// public interface ICab extends Runnable { ...
// ... 
// initCabs.add(mContext.createCab(Integer.valueOf(cabNum), whileWaiting));
// ...
for(ICab cab: initCabs) {
    cab.setMeter(createTaxiMeter());
    cab.setStationEventListener(this);
    mInitThreads.add(cab);
}
// ...
for(Runnable t: mInitThreads) {
    new Thread(t).start();
}
输出:

CabLoggingAspect: init()
CabLoggingAspect: logAnyCall(): setMeter
CabLoggingAspect: logAnyCall(): setStationEventListener
CabLoggingAspect: logAnyCall(): setMeter
CabLoggingAspect: logAnyCall(): setStationEventListener
CabLoggingAspect: logAnyCall(): run
CabLoggingAspect: logAnyCall(): run
调用了run()函数,但没有按方面打印其他内容。我正在修改现有的项目,所有线程都在运行,我可以看到线程的输出,和方面的实现无关

15/07/2012 23:19:05 Usjy - Passanger is ready and running...
15/07/2012 23:19:05 Usjy - Took cab starting transit
15/07/2012 23:19:06 MCMk - Passanger is ready and running...
15/07/2012 23:19:06 MCMk - Took cab starting transit
15/07/2012 23:19:08 Usjy - Arrived at TelAviv paid 5.8
15/07/2012 23:19:10 MCMk - Arrived at TelAviv paid 6.3
更新/解决方案

问题

正如Biju Kunjummen在他的回答中所描述的那样。当线程运行时,它会通知回调用方并传递self实例。以下所有调用都是直接绕过代理在此实例上执行的

公共类CabImpl实现ICab{ @凌驾 public void run(){
mStationListener.onCabReady(本); } }

解决方案

因为我在多个地方传递带有事件的原始对象的实例,所以快速解决方案是将对代理对象的引用存储在实例中并发送它。但更正确的解决方案是使用AspectJ,这将阐明不必要的代码修改和依赖关系

cab对象内部的修改

private ICab mAopProxy;
//...
public void setAopProxy(ICab proxy) {
    mAopProxy = proxy;
}

@Override
public void run() {
    mStationListener.onCabReady(mAopProxy);
    //...
}
cab的创建

Advised advised = (Advised)mApplicationContext.getBean("cab", num, whileWaiting);
Cab cab = (Cab) advised.getTargetSource().getTarget();
cab.setAopProxy((ICab)advised);

我看到您的Cab实现了Runnable接口,您正在使用Cab创建一个线程并启动该线程

我假设Cab中的run方法正在调用Cab公开的其他方法,如果是这种情况,那么它将完全绕过动态代理,您将看到这种行为

例如,如果客户端(非Cab)调用setMeter,则调用流将为:

client->CabDynamicProxy.setMeter()->cab.setMeter();

现在考虑CAB本身通过它的另一个方法(Sun())调用SETMICE的情况:

来自cab.run()的
this
不会解析为动态代理,而是解析为实际的cab本身,因此会完全绕过方面

有几个变通办法:

  • 不使用动态代理,而是使用完整的AspectJ-然后将 直接在Cab代码中,而不是在其周围使用代理
  • 不要从cab的run()方法内部调用此.setMeter(),而是在某处保留对代理的引用,并调用proxy.setMeter()

  • 你能澄清一下你的线程是如何获得Cab的引用的吗?在“running threads”代码示例中添加了更多信息。从xml文件读取参数,然后调用createCab。(ArrayList result=new ArrayList();…result.add(mContext.createCab(Integer.valueOf(cabNum),whileWaiting))谢谢,这正是原因,只是流程略有不同,这就是我感到困惑的原因。客户机将自己注册为侦听器,当Cab线程运行时,它将Cab实例发送回客户机。注意:需要记住,这是应用于spring AOP而不是AspectJ的加载时编织(LTW)。
    client->CabDynamicProxy.setMeter()->cab.setMeter();
    
    Thread.start()->CabDynamicProxy.run()->cab.run()->cab.setMeter();