INT-4327: Optimize Bean Post Processors

JIRA: https://jira.spring.io/browse/INT-4327

To avoid reflection and annotation processing overhead on the bean classes
when we deal with non-singleton beans and there is really no any
messaging on the bean class, store bean classes to the local cache to skip
them in the future when `BPP` is applied for request/prototype beans

* Simple code style polishing

**Cherry-pick to 4.3.x**
This commit is contained in:
Rick Hogge
2017-08-10 23:18:48 -05:00
committed by Artem Bilan
parent 6dad473219
commit 9f4f07bcfd
2 changed files with 30 additions and 1 deletions

View File

@@ -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<Class<?>> nonApplicableCache =
Collections.newSetFromMap(new ConcurrentHashMap<Class<?>, 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;
}
}

View File

@@ -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<Class<?>> noAnnotationsCache =
Collections.newSetFromMap(new ConcurrentHashMap<Class<?>, 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<Class<? extends Annotation>, List<Annotation>> annotationChains = new HashMap<>();
for (Class<? extends Annotation> annotationType :
@@ -168,6 +177,10 @@ public class MessagingAnnotationPostProcessor implements BeanPostProcessor, Bean
List<Annotation> annotations = entry.getValue();
processAnnotationTypeOnMethod(bean, beanName, method, annotationType, annotations);
}
if (annotationChains.size() == 0) {
noAnnotationsCache.add(beanClass);
}
}, ReflectionUtils.USER_DECLARED_METHODS);
return bean;