根据以下春季文档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
谢谢,
亚伯拉罕
答案 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