我可以使用Grails的@Async注释吗?

时间:2011-05-25 05:45:55

标签: java spring grails concurrency

根据以下春季文档link,我可以使用 @Async 注释来使方法调用异步。我可以从我拥有的java src文件中使用Grails中的这个工具吗?

[更新] 这是我的java(netty)套接字处理程序类,它接收套接字数据包 公共类DefaultHandler扩展SimpleChannelUpstreamHandler {

private static final Logger LOG = LoggerFactory.getLogger(DefaultHandler.class);

private AggregateSocketData aggregateSocketData;

@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
        throws Exception {
    LOG.trace("In messageRecieved method with event: {}",e);
    IEvent event = Events.dataInEvent(e.getMessage());
    System.out.println(Thread.currentThread().getName());
    aggregateSocketData.receiveSocketData(event);
}


@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
        throws Exception {
    LOG.error("Exception occurred in Default Handler: " ,e.getCause());
}

public AggregateSocketData getAggregateSocketData() {
    return aggregateSocketData;
}

public void setAggregateSocketData(AggregateSocketData aggregateSocketData) {
    this.aggregateSocketData = aggregateSocketData;
}

}

我在grails-conf - resources.xml中创建了一个bean

<bean id="defaultECM1240Handler" class="com.appcapture.buildingmgr.netty.DefaultHandler"
        scope="prototype">
        <property name="aggregateSocketData" ref="binaryDataAggregatorService"></property>
</bean>

这是我的grails服务类,其方法我已使用@Async

进行了注释

class BinaryDataAggregatorService实现AggregateSocketData {

def rawDataService
static transactional = true

@Async
void receiveSocketData(IEvent event) {
    println Thread.currentThread().name
    log.debug("Going to decode netty packet in receiveSocketData");
    Map decodedPacket = decodePacket((INettyPacket)event.getSource())
    def rawData = saveRawData (decodedPacket);
    log.debug ("Saved raw data, id: ${rawData?.id}")
    rawDataService.saveHTTPData(decodedPacket);
}

}

[Update 2] 以下是方法调用的堆栈跟踪。 这是堆栈。 BinaryDataAggregatorService.receiveSocketData(INettyPacket)行:20 BinaryDataAggregatorService $$ FastClassByCGLIB $$ 82489f62.invoke(int,Object,Object [])line:not available
MethodProxy.invoke(Object,Object [])行:149
Cglib2AopProxy $ CglibMethodInvocation.invokeJoinpoint()行:688
Cglib2AopProxy $ CglibMethodInvocation(ReflectiveMethodInvocation).proceed()line:150
TransactionInterceptor.invoke(MethodInvocation)行:110
Cglib2AopProxy $ CglibMethodInvocation(ReflectiveMethodInvocation).proceed()line:172
Cglib2AopProxy $ DynamicAdvisedInterceptor.intercept(Object,Method,Object [],MethodProxy)行:621 BinaryDataAggregatorService $$ EnhancerByCGLIB $$ 1c96985c.receiveSocketData(INettyPacket)行:不可用
DefaultHandler.handlePacket(INettyPacket)行:50

[更新3] grails堆栈跟踪设置任务:注释驱动元素。

011-05-26 17:38:03,109 [main] ERROR context.GrailsContextLoader  - Error executing bootstraps: Error creating bean with name 'defaultECM1240Handler' defined in URL [file:./grails-app/conf/spring/resources.xml]: Cannot resolve reference to bean 'binaryDataAggregatorService' while setting bean property 'aggregateSocketData'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'binaryDataAggregatorService': Invocation of init method failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class $Proxy12]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class $Proxy12
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultECM1240Handler' defined in URL [file:./grails-app/conf/spring/resources.xml]: Cannot resolve reference to bean 'binaryDataAggregatorService' while setting bean property 'aggregateSocketData'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'binaryDataAggregatorService': Invocation of init method failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class $Proxy12]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class $Proxy12

谢谢,
亚伯拉罕

3 个答案:

答案 0 :(得分:2)

如果是春豆 - 是的,你可以。为此,您必须使用@Service对其进行注释,并使用<context:component-scan base-package="com.foo.bar" />

但是为了更容易,你可以使用放在grails-app/services中的groovy类 - 它将自动成为一个bean bean

为了使@Async正常工作,您需要在xml配置中使用<task:annotation-driven/>

答案 1 :(得分:1)

我在尝试做同样的事情时发现了这一点。我还没有尝试过,但也许它会起作用。

https://gist.github.com/tux2323/2758723

ETA:

我修改了我的Resources.groovy文件以匹配我在此处找到的内容(http://docs.spring.io/spring/docs/3.0.x/reference/scheduling.html):

        xmlns task:"http://www.springframework.org/schema/task"
        task.'annotation-driven'('executor':'myExecutor')
        task.'executor'('id':'myExecutor', 'pool-size':'5')  

@Async注释中的代码仍然使用相同的线程。

答案 2 :(得分:0)

我从Jason H回答了一步,这真的帮助我解决了为我的服务设置@Async的问题。

xmlns task:"http://www.springframework.org/schema/task"
task.'annotation-driven'('executor':'myUploadExecutor', 'proxy-target-class':true, 'mode':'proxy')
task.'executor'('id':'myUploadExecutor', 'pool-size':'5')

我已在resources.groovy中添加此代码,然后您可以在代码中开始使用@Async(不要忘记在您的类中导入org.springframework.scheduling.annotation.Async), 没有(&#39; proxy-target-class&#39;:true,&#39;模式&#39;:#39;代理&#39;)您将收到错误java.lang.ClassCastException:com.sun。代理。在转换&#34;服务名称&#34;。

时抛出$ Proxy

在我的情况下,我使用在不同线程上运行的@Async将内容添加到数据库中,如果您正在为域使用@ gorm.AuditStamp,则Spring Security上下文不会绑定到新线程,您将获得createdBy和updatedBy NULL。

要解决此问题,请添加: 初始化我的BootStrap.groovy中的SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL)

有关更多信息,请访问以下网站: http://www.ogrigas.eu/spring/2010/04/inherit-spring-security-context-in-child-threads