001/* 002 * Copyright 2002-2015 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.scheduling.config; 018 019import org.w3c.dom.Element; 020 021import org.springframework.aop.config.AopNamespaceUtils; 022import org.springframework.beans.factory.config.BeanDefinition; 023import org.springframework.beans.factory.config.BeanDefinitionHolder; 024import org.springframework.beans.factory.parsing.BeanComponentDefinition; 025import org.springframework.beans.factory.parsing.CompositeComponentDefinition; 026import org.springframework.beans.factory.support.BeanDefinitionBuilder; 027import org.springframework.beans.factory.support.BeanDefinitionRegistry; 028import org.springframework.beans.factory.xml.BeanDefinitionParser; 029import org.springframework.beans.factory.xml.ParserContext; 030import org.springframework.util.StringUtils; 031 032/** 033 * Parser for the 'annotation-driven' element of the 'task' namespace. 034 * 035 * @author Mark Fisher 036 * @author Juergen Hoeller 037 * @author Ramnivas Laddad 038 * @author Chris Beams 039 * @author Stephane Nicoll 040 * @since 3.0 041 */ 042public class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { 043 044 private static final String ASYNC_EXECUTION_ASPECT_CLASS_NAME = 045 "org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect"; 046 047 048 @Override 049 public BeanDefinition parse(Element element, ParserContext parserContext) { 050 Object source = parserContext.extractSource(element); 051 052 // Register component for the surrounding <task:annotation-driven> element. 053 CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source); 054 parserContext.pushContainingComponent(compDefinition); 055 056 // Nest the concrete post-processor bean in the surrounding component. 057 BeanDefinitionRegistry registry = parserContext.getRegistry(); 058 059 String mode = element.getAttribute("mode"); 060 if ("aspectj".equals(mode)) { 061 // mode="aspectj" 062 registerAsyncExecutionAspect(element, parserContext); 063 } 064 else { 065 // mode="proxy" 066 if (registry.containsBeanDefinition(TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME)) { 067 parserContext.getReaderContext().error( 068 "Only one AsyncAnnotationBeanPostProcessor may exist within the context.", source); 069 } 070 else { 071 BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( 072 "org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor"); 073 builder.getRawBeanDefinition().setSource(source); 074 String executor = element.getAttribute("executor"); 075 if (StringUtils.hasText(executor)) { 076 builder.addPropertyReference("executor", executor); 077 } 078 String exceptionHandler = element.getAttribute("exception-handler"); 079 if (StringUtils.hasText(exceptionHandler)) { 080 builder.addPropertyReference("exceptionHandler", exceptionHandler); 081 } 082 if (Boolean.valueOf(element.getAttribute(AopNamespaceUtils.PROXY_TARGET_CLASS_ATTRIBUTE))) { 083 builder.addPropertyValue("proxyTargetClass", true); 084 } 085 registerPostProcessor(parserContext, builder, TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME); 086 } 087 } 088 089 if (registry.containsBeanDefinition(TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)) { 090 parserContext.getReaderContext().error( 091 "Only one ScheduledAnnotationBeanPostProcessor may exist within the context.", source); 092 } 093 else { 094 BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( 095 "org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor"); 096 builder.getRawBeanDefinition().setSource(source); 097 String scheduler = element.getAttribute("scheduler"); 098 if (StringUtils.hasText(scheduler)) { 099 builder.addPropertyReference("scheduler", scheduler); 100 } 101 registerPostProcessor(parserContext, builder, TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME); 102 } 103 104 // Finally register the composite component. 105 parserContext.popAndRegisterContainingComponent(); 106 107 return null; 108 } 109 110 private void registerAsyncExecutionAspect(Element element, ParserContext parserContext) { 111 if (!parserContext.getRegistry().containsBeanDefinition(TaskManagementConfigUtils.ASYNC_EXECUTION_ASPECT_BEAN_NAME)) { 112 BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(ASYNC_EXECUTION_ASPECT_CLASS_NAME); 113 builder.setFactoryMethod("aspectOf"); 114 String executor = element.getAttribute("executor"); 115 if (StringUtils.hasText(executor)) { 116 builder.addPropertyReference("executor", executor); 117 } 118 String exceptionHandler = element.getAttribute("exception-handler"); 119 if (StringUtils.hasText(exceptionHandler)) { 120 builder.addPropertyReference("exceptionHandler", exceptionHandler); 121 } 122 parserContext.registerBeanComponent(new BeanComponentDefinition(builder.getBeanDefinition(), 123 TaskManagementConfigUtils.ASYNC_EXECUTION_ASPECT_BEAN_NAME)); 124 } 125 } 126 127 private static void registerPostProcessor( 128 ParserContext parserContext, BeanDefinitionBuilder builder, String beanName) { 129 130 builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); 131 parserContext.getRegistry().registerBeanDefinition(beanName, builder.getBeanDefinition()); 132 BeanDefinitionHolder holder = new BeanDefinitionHolder(builder.getBeanDefinition(), beanName); 133 parserContext.registerComponent(new BeanComponentDefinition(holder)); 134 } 135 136}