Cache InjectionMetadata per bean name instead of per Class, if possible
Issue: SPR-11027
(cherry picked from commit 4675bc4)
This commit is contained in:
@@ -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<Class<?>, Constructor<?>[]> candidateConstructorsCache =
|
||||
new ConcurrentHashMap<Class<?>, Constructor<?>[]>(64);
|
||||
|
||||
private final Map<Class<?>, InjectionMetadata> injectionMetadataCache =
|
||||
new ConcurrentHashMap<Class<?>, InjectionMetadata>(64);
|
||||
private final Map<String, InjectionMetadata> injectionMetadataCache =
|
||||
new ConcurrentHashMap<String, InjectionMetadata>(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Class<?>, InjectionMetadata> injectionMetadataCache =
|
||||
new ConcurrentHashMap<Class<?>, InjectionMetadata>(64);
|
||||
private transient final Map<String, InjectionMetadata> injectionMetadataCache =
|
||||
new ConcurrentHashMap<String, InjectionMetadata>(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<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Class<?>, InjectionMetadata> injectionMetadataCache =
|
||||
new ConcurrentHashMap<Class<?>, InjectionMetadata>(64);
|
||||
private transient final Map<String, InjectionMetadata> injectionMetadataCache =
|
||||
new ConcurrentHashMap<String, InjectionMetadata>(64);
|
||||
|
||||
private final Map<Object, EntityManager> extendedEntityManagersToClose =
|
||||
new ConcurrentHashMap<Object, EntityManager>(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<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user