Skip to content

Commit ce001c2

Browse files
committed
Cache InjectionMetadata per bean name instead of per Class, if possible
Issue: SPR-11027 (cherry picked from commit 4675bc4)
1 parent 93405fb commit ce001c2

File tree

3 files changed

+35
-27
lines changed

3 files changed

+35
-27
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -59,6 +59,7 @@
5959
import org.springframework.util.Assert;
6060
import org.springframework.util.ClassUtils;
6161
import org.springframework.util.ReflectionUtils;
62+
import org.springframework.util.StringUtils;
6263

6364
/**
6465
* {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation
@@ -121,8 +122,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
121122
private final Map<Class<?>, Constructor<?>[]> candidateConstructorsCache =
122123
new ConcurrentHashMap<Class<?>, Constructor<?>[]>(64);
123124

124-
private final Map<Class<?>, InjectionMetadata> injectionMetadataCache =
125-
new ConcurrentHashMap<Class<?>, InjectionMetadata>(64);
125+
private final Map<String, InjectionMetadata> injectionMetadataCache =
126+
new ConcurrentHashMap<String, InjectionMetadata>(64);
126127

127128

128129
/**
@@ -214,7 +215,7 @@ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
214215

215216
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
216217
if (beanType != null) {
217-
InjectionMetadata metadata = findAutowiringMetadata(beanType);
218+
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType);
218219
metadata.checkConfigMembers(beanDefinition);
219220
}
220221
}
@@ -280,7 +281,7 @@ else if (candidate.getParameterTypes().length == 0) {
280281
public PropertyValues postProcessPropertyValues(
281282
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
282283

283-
InjectionMetadata metadata = findAutowiringMetadata(bean.getClass());
284+
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass());
284285
try {
285286
metadata.inject(bean, beanName, pvs);
286287
}
@@ -298,7 +299,7 @@ public PropertyValues postProcessPropertyValues(
298299
*/
299300
public void processInjection(Object bean) throws BeansException {
300301
Class<?> clazz = bean.getClass();
301-
InjectionMetadata metadata = findAutowiringMetadata(clazz);
302+
InjectionMetadata metadata = findAutowiringMetadata(clazz.getName(), clazz);
302303
try {
303304
metadata.inject(bean, null, null);
304305
}
@@ -308,15 +309,17 @@ public void processInjection(Object bean) throws BeansException {
308309
}
309310

310311

311-
private InjectionMetadata findAutowiringMetadata(Class<?> clazz) {
312+
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz) {
312313
// Quick check on the concurrent map first, with minimal locking.
313-
InjectionMetadata metadata = this.injectionMetadataCache.get(clazz);
314+
// Fall back to class name as cache key, for backwards compatibility with custom callers.
315+
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
316+
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
314317
if (metadata == null) {
315318
synchronized (this.injectionMetadataCache) {
316-
metadata = this.injectionMetadataCache.get(clazz);
319+
metadata = this.injectionMetadataCache.get(cacheKey);
317320
if (metadata == null) {
318321
metadata = buildAutowiringMetadata(clazz);
319-
this.injectionMetadataCache.put(clazz, metadata);
322+
this.injectionMetadataCache.put(cacheKey, metadata);
320323
}
321324
}
322325
}

spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -177,8 +177,8 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
177177

178178
private transient BeanFactory beanFactory;
179179

180-
private transient final Map<Class<?>, InjectionMetadata> injectionMetadataCache =
181-
new ConcurrentHashMap<Class<?>, InjectionMetadata>(64);
180+
private transient final Map<String, InjectionMetadata> injectionMetadataCache =
181+
new ConcurrentHashMap<String, InjectionMetadata>(64);
182182

183183

184184
/**
@@ -282,7 +282,7 @@ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
282282
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
283283
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
284284
if (beanType != null) {
285-
InjectionMetadata metadata = findResourceMetadata(beanType);
285+
InjectionMetadata metadata = findResourceMetadata(beanName, beanType);
286286
metadata.checkConfigMembers(beanDefinition);
287287
}
288288
}
@@ -298,7 +298,7 @@ public boolean postProcessAfterInstantiation(Object bean, String beanName) throw
298298
public PropertyValues postProcessPropertyValues(
299299
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
300300

301-
InjectionMetadata metadata = findResourceMetadata(bean.getClass());
301+
InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass());
302302
try {
303303
metadata.inject(bean, beanName, pvs);
304304
}
@@ -309,12 +309,14 @@ public PropertyValues postProcessPropertyValues(
309309
}
310310

311311

312-
private InjectionMetadata findResourceMetadata(final Class<?> clazz) {
312+
private InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz) {
313313
// Quick check on the concurrent map first, with minimal locking.
314-
InjectionMetadata metadata = this.injectionMetadataCache.get(clazz);
314+
// Fall back to class name as cache key, for backwards compatibility with custom callers.
315+
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
316+
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
315317
if (metadata == null) {
316318
synchronized (this.injectionMetadataCache) {
317-
metadata = this.injectionMetadataCache.get(clazz);
319+
metadata = this.injectionMetadataCache.get(cacheKey);
318320
if (metadata == null) {
319321
LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
320322
Class<?> targetClass = clazz;
@@ -388,7 +390,7 @@ else if (method.isAnnotationPresent(Resource.class)) {
388390
while (targetClass != null && targetClass != Object.class);
389391

390392
metadata = new InjectionMetadata(clazz, elements);
391-
this.injectionMetadataCache.put(clazz, metadata);
393+
this.injectionMetadataCache.put(cacheKey, metadata);
392394
}
393395
}
394396
}

spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
import org.springframework.orm.jpa.SharedEntityManagerCreator;
6262
import org.springframework.util.ClassUtils;
6363
import org.springframework.util.ObjectUtils;
64+
import org.springframework.util.StringUtils;
6465

6566
/**
6667
* BeanPostProcessor that processes {@link javax.persistence.PersistenceUnit}
@@ -181,8 +182,8 @@ public class PersistenceAnnotationBeanPostProcessor
181182

182183
private transient ListableBeanFactory beanFactory;
183184

184-
private transient final Map<Class<?>, InjectionMetadata> injectionMetadataCache =
185-
new ConcurrentHashMap<Class<?>, InjectionMetadata>(64);
185+
private transient final Map<String, InjectionMetadata> injectionMetadataCache =
186+
new ConcurrentHashMap<String, InjectionMetadata>(64);
186187

187188
private final Map<Object, EntityManager> extendedEntityManagersToClose =
188189
new ConcurrentHashMap<Object, EntityManager>(16);
@@ -319,7 +320,7 @@ public void setBeanFactory(BeanFactory beanFactory) {
319320

320321
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
321322
if (beanType != null) {
322-
InjectionMetadata metadata = findPersistenceMetadata(beanType);
323+
InjectionMetadata metadata = findPersistenceMetadata(beanName, beanType);
323324
metadata.checkConfigMembers(beanDefinition);
324325
}
325326
}
@@ -335,7 +336,7 @@ public boolean postProcessAfterInstantiation(Object bean, String beanName) throw
335336
public PropertyValues postProcessPropertyValues(
336337
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
337338

338-
InjectionMetadata metadata = findPersistenceMetadata(bean.getClass());
339+
InjectionMetadata metadata = findPersistenceMetadata(beanName, bean.getClass());
339340
try {
340341
metadata.inject(bean, beanName, pvs);
341342
}
@@ -359,12 +360,14 @@ public void postProcessBeforeDestruction(Object bean, String beanName) throws Be
359360
}
360361

361362

362-
private InjectionMetadata findPersistenceMetadata(final Class<?> clazz) {
363+
private InjectionMetadata findPersistenceMetadata(String beanName, final Class<?> clazz) {
363364
// Quick check on the concurrent map first, with minimal locking.
364-
InjectionMetadata metadata = this.injectionMetadataCache.get(clazz);
365+
// Fall back to class name as cache key, for backwards compatibility with custom callers.
366+
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
367+
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
365368
if (metadata == null) {
366369
synchronized (this.injectionMetadataCache) {
367-
metadata = this.injectionMetadataCache.get(clazz);
370+
metadata = this.injectionMetadataCache.get(cacheKey);
368371
if (metadata == null) {
369372
LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
370373
Class<?> targetClass = clazz;
@@ -402,7 +405,7 @@ private InjectionMetadata findPersistenceMetadata(final Class<?> clazz) {
402405
while (targetClass != null && targetClass != Object.class);
403406

404407
metadata = new InjectionMetadata(clazz, elements);
405-
this.injectionMetadataCache.put(clazz, metadata);
408+
this.injectionMetadataCache.put(cacheKey, metadata);
406409
}
407410
}
408411
}

0 commit comments

Comments
 (0)