From ce001c23f728b2cc0e9db29c9e59a24958461a6a Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Sat, 26 Oct 2013 15:18:34 +0200 Subject: [PATCH] Cache InjectionMetadata per bean name instead of per Class, if possible Issue: SPR-11027 (cherry picked from commit 4675bc4) --- .../AutowiredAnnotationBeanPostProcessor.java | 23 +++++++++++-------- .../CommonAnnotationBeanPostProcessor.java | 20 ++++++++-------- ...ersistenceAnnotationBeanPostProcessor.java | 19 ++++++++------- 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java index 6775dd78ed..ecf5044f04 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -59,6 +59,7 @@ import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; +import org.springframework.util.StringUtils; /** * {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation @@ -121,8 +122,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean private final Map, Constructor[]> candidateConstructorsCache = new ConcurrentHashMap, Constructor[]>(64); - private final Map, InjectionMetadata> injectionMetadataCache = - new ConcurrentHashMap, InjectionMetadata>(64); + private final Map injectionMetadataCache = + new ConcurrentHashMap(64); /** @@ -214,7 +215,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) { if (beanType != null) { - InjectionMetadata metadata = findAutowiringMetadata(beanType); + InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType); metadata.checkConfigMembers(beanDefinition); } } @@ -280,7 +281,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean public PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { - InjectionMetadata metadata = findAutowiringMetadata(bean.getClass()); + InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass()); try { metadata.inject(bean, beanName, pvs); } @@ -298,7 +299,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean */ public void processInjection(Object bean) throws BeansException { Class clazz = bean.getClass(); - InjectionMetadata metadata = findAutowiringMetadata(clazz); + InjectionMetadata metadata = findAutowiringMetadata(clazz.getName(), clazz); try { metadata.inject(bean, null, null); } @@ -308,15 +309,17 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean } - private InjectionMetadata findAutowiringMetadata(Class clazz) { + private InjectionMetadata findAutowiringMetadata(String beanName, Class clazz) { // Quick check on the concurrent map first, with minimal locking. - InjectionMetadata metadata = this.injectionMetadataCache.get(clazz); + // Fall back to class name as cache key, for backwards compatibility with custom callers. + String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); + InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); if (metadata == null) { synchronized (this.injectionMetadataCache) { - metadata = this.injectionMetadataCache.get(clazz); + metadata = this.injectionMetadataCache.get(cacheKey); if (metadata == null) { metadata = buildAutowiringMetadata(clazz); - this.injectionMetadataCache.put(clazz, metadata); + this.injectionMetadataCache.put(cacheKey, metadata); } } } diff --git a/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java b/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java index 7149d9bdb1..cbb1ee2110 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -177,8 +177,8 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean private transient BeanFactory beanFactory; - private transient final Map, InjectionMetadata> injectionMetadataCache = - new ConcurrentHashMap, InjectionMetadata>(64); + private transient final Map injectionMetadataCache = + new ConcurrentHashMap(64); /** @@ -282,7 +282,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) { super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName); if (beanType != null) { - InjectionMetadata metadata = findResourceMetadata(beanType); + InjectionMetadata metadata = findResourceMetadata(beanName, beanType); metadata.checkConfigMembers(beanDefinition); } } @@ -298,7 +298,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean public PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { - InjectionMetadata metadata = findResourceMetadata(bean.getClass()); + InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass()); try { metadata.inject(bean, beanName, pvs); } @@ -309,12 +309,14 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean } - private InjectionMetadata findResourceMetadata(final Class clazz) { + private InjectionMetadata findResourceMetadata(String beanName, final Class clazz) { // Quick check on the concurrent map first, with minimal locking. - InjectionMetadata metadata = this.injectionMetadataCache.get(clazz); + // Fall back to class name as cache key, for backwards compatibility with custom callers. + String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); + InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); if (metadata == null) { synchronized (this.injectionMetadataCache) { - metadata = this.injectionMetadataCache.get(clazz); + metadata = this.injectionMetadataCache.get(cacheKey); if (metadata == null) { LinkedList elements = new LinkedList(); Class targetClass = clazz; @@ -388,7 +390,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean while (targetClass != null && targetClass != Object.class); metadata = new InjectionMetadata(clazz, elements); - this.injectionMetadataCache.put(clazz, metadata); + this.injectionMetadataCache.put(cacheKey, metadata); } } } diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java b/spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java index 39c437e8cd..fe1ab5bc76 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java @@ -61,6 +61,7 @@ import org.springframework.orm.jpa.ExtendedEntityManagerCreator; import org.springframework.orm.jpa.SharedEntityManagerCreator; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; /** * BeanPostProcessor that processes {@link javax.persistence.PersistenceUnit} @@ -181,8 +182,8 @@ public class PersistenceAnnotationBeanPostProcessor private transient ListableBeanFactory beanFactory; - private transient final Map, InjectionMetadata> injectionMetadataCache = - new ConcurrentHashMap, InjectionMetadata>(64); + private transient final Map injectionMetadataCache = + new ConcurrentHashMap(64); private final Map extendedEntityManagersToClose = new ConcurrentHashMap(16); @@ -319,7 +320,7 @@ public class PersistenceAnnotationBeanPostProcessor public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) { if (beanType != null) { - InjectionMetadata metadata = findPersistenceMetadata(beanType); + InjectionMetadata metadata = findPersistenceMetadata(beanName, beanType); metadata.checkConfigMembers(beanDefinition); } } @@ -335,7 +336,7 @@ public class PersistenceAnnotationBeanPostProcessor public PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { - InjectionMetadata metadata = findPersistenceMetadata(bean.getClass()); + InjectionMetadata metadata = findPersistenceMetadata(beanName, bean.getClass()); try { metadata.inject(bean, beanName, pvs); } @@ -359,12 +360,14 @@ public class PersistenceAnnotationBeanPostProcessor } - private InjectionMetadata findPersistenceMetadata(final Class clazz) { + private InjectionMetadata findPersistenceMetadata(String beanName, final Class clazz) { // Quick check on the concurrent map first, with minimal locking. - InjectionMetadata metadata = this.injectionMetadataCache.get(clazz); + // Fall back to class name as cache key, for backwards compatibility with custom callers. + String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); + InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); if (metadata == null) { synchronized (this.injectionMetadataCache) { - metadata = this.injectionMetadataCache.get(clazz); + metadata = this.injectionMetadataCache.get(cacheKey); if (metadata == null) { LinkedList elements = new LinkedList(); Class targetClass = clazz; @@ -402,7 +405,7 @@ public class PersistenceAnnotationBeanPostProcessor while (targetClass != null && targetClass != Object.class); metadata = new InjectionMetadata(clazz, elements); - this.injectionMetadataCache.put(clazz, metadata); + this.injectionMetadataCache.put(cacheKey, metadata); } } }