diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aop/PublisherAnnotationBeanPostProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aop/PublisherAnnotationBeanPostProcessor.java index e461a6240d..bb1bc30f5a 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aop/PublisherAnnotationBeanPostProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aop/PublisherAnnotationBeanPostProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2017 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. @@ -16,6 +16,10 @@ package org.springframework.integration.aop; +import java.util.Collections; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + import org.springframework.aop.framework.Advised; import org.springframework.aop.framework.ProxyConfig; import org.springframework.aop.framework.ProxyFactory; @@ -37,6 +41,8 @@ import org.springframework.util.ClassUtils; * @author Mark Fisher * @author Gary Russell * @author Artem Bilan + * @author Rick Hogge + * * @since 2.0 */ @SuppressWarnings("serial") @@ -53,6 +59,9 @@ public class PublisherAnnotationBeanPostProcessor extends ProxyConfig private volatile ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader(); + private final Set> nonApplicableCache = + Collections.newSetFromMap(new ConcurrentHashMap, Boolean>(256)); + /** * Set the default channel where Messages should be sent if the annotation * itself does not provide a channel. @@ -101,6 +110,12 @@ public class PublisherAnnotationBeanPostProcessor extends ProxyConfig return bean; } + // the set will hold records of prior class scans and will contain the bean classes that can not + // be assigned to the Advisor interface and therefore can be short circuited + if (this.nonApplicableCache.contains(targetClass)) { + return bean; + } + if (AopUtils.canApply(this.advisor, targetClass)) { if (bean instanceof Advised) { ((Advised) bean).addAdvisor(this.advisor); @@ -116,6 +131,7 @@ public class PublisherAnnotationBeanPostProcessor extends ProxyConfig } else { // cannot apply advisor + nonApplicableCache.add(targetClass); return bean; } } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/MessagingAnnotationPostProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/MessagingAnnotationPostProcessor.java index 82c89121ff..755f30a868 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/MessagingAnnotationPostProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/MessagingAnnotationPostProcessor.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -71,6 +72,7 @@ import org.springframework.util.StringUtils; * @author Marius Bogoevici * @author Artem Bilan * @author Gary Russell + * @author Rick Hogge */ public class MessagingAnnotationPostProcessor implements BeanPostProcessor, BeanFactoryAware, InitializingBean, SmartInitializingSingleton { @@ -84,6 +86,8 @@ public class MessagingAnnotationPostProcessor implements BeanPostProcessor, Bean private ConfigurableListableBeanFactory beanFactory; + private final Set> noAnnotationsCache = + Collections.newSetFromMap(new ConcurrentHashMap, Boolean>(256)); @Override public void setBeanFactory(BeanFactory beanFactory) { @@ -151,6 +155,11 @@ public class MessagingAnnotationPostProcessor implements BeanPostProcessor, Bean Class beanClass = AopUtils.getTargetClass(bean); + // the set will hold records of prior class scans and indicate if no messaging annotations were found + if (this.noAnnotationsCache.contains(beanClass)) { + return bean; + } + ReflectionUtils.doWithMethods(beanClass, method -> { Map, List> annotationChains = new HashMap<>(); for (Class annotationType : @@ -168,6 +177,10 @@ public class MessagingAnnotationPostProcessor implements BeanPostProcessor, Bean List annotations = entry.getValue(); processAnnotationTypeOnMethod(bean, beanName, method, annotationType, annotations); } + + if (annotationChains.size() == 0) { + noAnnotationsCache.add(beanClass); + } }, ReflectionUtils.USER_DECLARED_METHODS); return bean;