From 3192b926ea4c3f2edb3eb00ae38ac81ecaaa51a9 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Tue, 2 Jun 2009 16:58:43 +0000 Subject: [PATCH] Added support for the 'annotation-driven' element within the 'task' namespace to enable detection of the @Async annotation on Spring-managed objects. --- .../AnnotationDrivenBeanDefinitionParser.java | 85 +++++++++++++++++++ .../config/TaskNamespaceHandler.java | 1 + .../scheduling/config/spring-task-3.0.xsd | 20 +++++ 3 files changed, 106 insertions(+) create mode 100644 org.springframework.context/src/main/java/org/springframework/scheduling/config/AnnotationDrivenBeanDefinitionParser.java diff --git a/org.springframework.context/src/main/java/org/springframework/scheduling/config/AnnotationDrivenBeanDefinitionParser.java b/org.springframework.context/src/main/java/org/springframework/scheduling/config/AnnotationDrivenBeanDefinitionParser.java new file mode 100644 index 00000000000..928c77629ca --- /dev/null +++ b/org.springframework.context/src/main/java/org/springframework/scheduling/config/AnnotationDrivenBeanDefinitionParser.java @@ -0,0 +1,85 @@ +/* + * Copyright 2002-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.scheduling.config; + +import org.w3c.dom.Element; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.parsing.BeanComponentDefinition; +import org.springframework.beans.factory.parsing.CompositeComponentDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.xml.BeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.util.StringUtils; + +/** + * Parser for the 'annotation-driven' element of the 'task' namespace. + * + * @author Mark Fisher + * @since 3.0 + */ +public class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { + + /** + * The bean name of the internally managed async annotation processor. + */ + public static final String ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME = + "org.springframework.scheduling.annotation.internalAsyncAnnotationProcessor"; + + + public BeanDefinition parse(Element element, ParserContext parserContext) { + Object source = parserContext.extractSource(element); + + // Register component for the surrounding element. + CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source); + parserContext.pushContainingComponent(compDefinition); + + // Nest the concrete post-processor bean in the surrounding component. + BeanDefinitionRegistry registry = parserContext.getRegistry(); + if (registry.containsBeanDefinition(ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME)) { + parserContext.getReaderContext().error( + "Only one AsyncAnnotationBeanPostProcessor may exist within the context.", source); + } + else { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( + "org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor"); + builder.getRawBeanDefinition().setSource(source); + String executor = element.getAttribute("executor"); + if (StringUtils.hasText(executor)) { + builder.addPropertyReference("executor", executor); + } + BeanDefinitionHolder holder = registerPostProcessor(registry, builder, ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME); + parserContext.registerComponent(new BeanComponentDefinition(holder)); + } + + // Finally register the composite component. + parserContext.popAndRegisterContainingComponent(); + + return null; + } + + private static BeanDefinitionHolder registerPostProcessor( + BeanDefinitionRegistry registry, BeanDefinitionBuilder builder, String beanName) { + + builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + registry.registerBeanDefinition(beanName, builder.getBeanDefinition()); + return new BeanDefinitionHolder(builder.getBeanDefinition(), beanName); + } + +} diff --git a/org.springframework.context/src/main/java/org/springframework/scheduling/config/TaskNamespaceHandler.java b/org.springframework.context/src/main/java/org/springframework/scheduling/config/TaskNamespaceHandler.java index 849b36f57f3..07004dca052 100644 --- a/org.springframework.context/src/main/java/org/springframework/scheduling/config/TaskNamespaceHandler.java +++ b/org.springframework.context/src/main/java/org/springframework/scheduling/config/TaskNamespaceHandler.java @@ -27,6 +27,7 @@ import org.springframework.beans.factory.xml.NamespaceHandlerSupport; public class TaskNamespaceHandler extends NamespaceHandlerSupport { public void init() { + this.registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser()); this.registerBeanDefinitionParser("scheduled-tasks", new ScheduledTasksBeanDefinitionParser()); this.registerBeanDefinitionParser("scheduler", new SchedulerBeanDefinitionParser()); } diff --git a/org.springframework.context/src/main/resources/org/springframework/scheduling/config/spring-task-3.0.xsd b/org.springframework.context/src/main/resources/org/springframework/scheduling/config/spring-task-3.0.xsd index 79a52e28889..5d3a3c4df8c 100644 --- a/org.springframework.context/src/main/resources/org/springframework/scheduling/config/spring-task-3.0.xsd +++ b/org.springframework.context/src/main/resources/org/springframework/scheduling/config/spring-task-3.0.xsd @@ -17,6 +17,26 @@ + + + + + + + + + + + + +