diff --git a/pom.xml b/pom.xml index 2398553..7a94452 100644 --- a/pom.xml +++ b/pom.xml @@ -12,12 +12,12 @@ com.alibaba.spring spring-context-support - 1.0.11 + 1.0.12 1.6 1.6 - 3.2.18.RELEASE + 6.0.2 @@ -149,6 +149,13 @@ 5.2.9.RELEASE + + + spring-6.0.2 + + 5.2.9.RELEASE + + diff --git a/src/main/java/com/alibaba/spring/beans/factory/annotation/AbstractAnnotationBeanPostProcessor.java b/src/main/java/com/alibaba/spring/beans/factory/annotation/AbstractAnnotationBeanPostProcessor.java index 8c98065..b69b1ff 100644 --- a/src/main/java/com/alibaba/spring/beans/factory/annotation/AbstractAnnotationBeanPostProcessor.java +++ b/src/main/java/com/alibaba/spring/beans/factory/annotation/AbstractAnnotationBeanPostProcessor.java @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package com.alibaba.spring.beans.factory.annotation; import org.apache.commons.logging.Log; @@ -30,7 +31,7 @@ import org.springframework.beans.factory.annotation.InjectionMetadata; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; +import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor; import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.EnvironmentAware; @@ -73,65 +74,62 @@ * @since 1.0.3 */ @SuppressWarnings("unchecked") -public abstract class AbstractAnnotationBeanPostProcessor extends - InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, - BeanFactoryAware, BeanClassLoaderAware, EnvironmentAware, DisposableBean { - +public abstract class AbstractAnnotationBeanPostProcessor + implements MergedBeanDefinitionPostProcessor, PriorityOrdered, SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware, BeanClassLoaderAware, EnvironmentAware, DisposableBean { + private final static int CACHE_SIZE = Integer.getInteger("", 32); - + private final Log logger = LogFactory.getLog(getClass()); - + private final Class[] annotationTypes; - - private final ConcurrentMap injectionMetadataCache = - new ConcurrentHashMap(CACHE_SIZE); - - private final ConcurrentMap injectedObjectsCache = new ConcurrentHashMap(CACHE_SIZE); - + + private final ConcurrentMap injectionMetadataCache = new ConcurrentHashMap( + CACHE_SIZE); + + private final ConcurrentMap injectedObjectsCache = new ConcurrentHashMap( + CACHE_SIZE); + private ConfigurableListableBeanFactory beanFactory; - + private Environment environment; - + private ClassLoader classLoader; - + /** * make sure higher priority than {@link AutowiredAnnotationBeanPostProcessor} */ private int order = Ordered.LOWEST_PRECEDENCE - 3; - + /** - * whether to turn Class references into Strings (for - * compatibility with {@link org.springframework.core.type.AnnotationMetadata} or to - * preserve them as Class references + * whether to turn Class references into Strings (for compatibility with {@link + * org.springframework.core.type.AnnotationMetadata} or to preserve them as Class references * * @since 1.0.11 */ private boolean classValuesAsString; - + /** - * whether to turn nested Annotation instances into - * {@link AnnotationAttributes} maps (for compatibility with - * {@link org.springframework.core.type.AnnotationMetadata} or to preserve them as - * Annotation instances + * whether to turn nested Annotation instances into {@link AnnotationAttributes} maps (for compatibility with {@link + * org.springframework.core.type.AnnotationMetadata} or to preserve them as Annotation instances * * @since 1.0.11 */ private boolean nestedAnnotationsAsMap; - + /** * whether ignore default value or not * * @since 1.0.11 */ private boolean ignoreDefaultValue = true; - + /** * whether try merged annotation or not * * @since 1.0.11 */ private boolean tryMergedAnnotation = true; - + /** * @param annotationTypes the multiple types of {@link Annotation annotations} */ @@ -139,7 +137,7 @@ public AbstractAnnotationBeanPostProcessor(Class... annota Assert.notEmpty(annotationTypes, "The argument of annotations' types must not empty"); this.annotationTypes = annotationTypes; } - + private static Collection combine(Collection... elements) { List allElements = new ArrayList(); for (Collection e : elements) { @@ -147,7 +145,7 @@ private static Collection combine(Collection... elements) { } return allElements; } - + /** * Annotation type * @@ -158,108 +156,110 @@ private static Collection combine(Collection... elements) { public final Class getAnnotationType() { return annotationTypes[0]; } - + protected final Class[] getAnnotationTypes() { return annotationTypes; } - + @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { Assert.isInstanceOf(ConfigurableListableBeanFactory.class, beanFactory, "AnnotationInjectedBeanPostProcessor requires a ConfigurableListableBeanFactory"); this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; } - + @Override - public PropertyValues postProcessPropertyValues( - PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException { - + public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) + throws BeansException { InjectionMetadata metadata = findInjectionMetadata(beanName, bean.getClass(), pvs); try { metadata.inject(bean, beanName, pvs); } catch (BeanCreationException ex) { throw ex; } catch (Throwable ex) { - throw new BeanCreationException(beanName, "Injection of @" + getAnnotationType().getSimpleName() - + " dependencies is failed", ex); + throw new BeanCreationException(beanName, + "Injection of @" + getAnnotationType().getSimpleName() + " dependencies is failed", ex); } return pvs; } - - + + /** * Finds {@link InjectionMetadata.InjectedElement} Metadata from annotated fields * * @param beanClass The {@link Class} of Bean * @return non-null {@link List} */ - private List findFieldAnnotationMetadata(final Class beanClass) { - + private List findFieldAnnotationMetadata( + final Class beanClass) { + final List elements = new LinkedList(); - + ReflectionUtils.doWithFields(beanClass, new ReflectionUtils.FieldCallback() { @Override public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { - + for (Class annotationType : getAnnotationTypes()) { - + AnnotationAttributes attributes = doGetAnnotationAttributes(field, annotationType); - + if (attributes != null) { - + if (Modifier.isStatic(field.getModifiers())) { if (logger.isWarnEnabled()) { - logger.warn("@" + annotationType.getName() + " is not supported on static fields: " + field); + logger.warn("@" + annotationType.getName() + " is not supported on static fields: " + + field); } return; } - + elements.add(new AnnotatedFieldElement(field, attributes)); } } } }); - + return elements; - + } - + /** * Finds {@link InjectionMetadata.InjectedElement} Metadata from annotated methods * * @param beanClass The {@link Class} of Bean * @return non-null {@link List} */ - private List findAnnotatedMethodMetadata(final Class beanClass) { - + private List findAnnotatedMethodMetadata( + final Class beanClass) { + final List elements = new LinkedList(); - + ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() { @Override public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { - + Method bridgedMethod = findBridgedMethod(method); - + if (!isVisibilityBridgeMethodPair(method, bridgedMethod)) { return; } - - + for (Class annotationType : getAnnotationTypes()) { - + AnnotationAttributes attributes = doGetAnnotationAttributes(bridgedMethod, annotationType); - + if (attributes != null && method.equals(ClassUtils.getMostSpecificMethod(method, beanClass))) { if (Modifier.isStatic(method.getModifiers())) { if (logger.isWarnEnabled()) { - logger.warn("@" + annotationType.getName() + " annotation is not supported on static methods: " + method); + logger.warn("@" + annotationType.getName() + + " annotation is not supported on static methods: " + method); } return; } if (method.getParameterTypes().length == 0) { if (logger.isWarnEnabled()) { - logger.warn("@" + annotationType.getName() + " annotation should only be used on methods with parameters: " + - method); + logger.warn("@" + annotationType.getName() + + " annotation should only be used on methods with parameters: " + method); } } PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, beanClass); @@ -268,35 +268,41 @@ public void doWith(Method method) throws IllegalArgumentException, IllegalAccess } } }); - + return elements; } - + /** * Get {@link AnnotationAttributes} * * @param annotatedElement {@link AnnotatedElement the annotated element} * @param annotationType the {@link Class tyoe} pf {@link Annotation annotation} - * @return if annotatedElement can't be found in annotatedElement, return null + * @return if annotatedElement can't be found in annotatedElement, return + * null * @since 1.0.11 */ protected AnnotationAttributes doGetAnnotationAttributes(AnnotatedElement annotatedElement, - Class annotationType) { - return getAnnotationAttributes(annotatedElement, annotationType, getEnvironment(), - classValuesAsString, nestedAnnotationsAsMap, ignoreDefaultValue, tryMergedAnnotation); + Class annotationType) { + return getAnnotationAttributes(annotatedElement, annotationType, getEnvironment(), classValuesAsString, + nestedAnnotationsAsMap, ignoreDefaultValue, tryMergedAnnotation); } - - private AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata buildAnnotatedMetadata(final Class beanClass) { - Collection fieldElements = findFieldAnnotationMetadata(beanClass); - Collection methodElements = findAnnotatedMethodMetadata(beanClass); - return new AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata(beanClass, fieldElements, methodElements); + + private AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata buildAnnotatedMetadata( + final Class beanClass) { + Collection fieldElements = findFieldAnnotationMetadata( + beanClass); + Collection methodElements = findAnnotatedMethodMetadata( + beanClass); + return new AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata(beanClass, fieldElements, + methodElements); } - + private InjectionMetadata findInjectionMetadata(String beanName, Class clazz, PropertyValues pvs) { // Fall back to class name as cache key, for backwards compatibility with custom callers. String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); // Quick check on the concurrent map first, with minimal locking. - AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); + AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata metadata = this.injectionMetadataCache.get( + cacheKey); if (InjectionMetadata.needsRefresh(metadata, clazz)) { synchronized (this.injectionMetadataCache) { metadata = this.injectionMetadataCache.get(cacheKey); @@ -308,15 +314,15 @@ private InjectionMetadata findInjectionMetadata(String beanName, Class clazz, metadata = buildAnnotatedMetadata(clazz); this.injectionMetadataCache.put(cacheKey, metadata); } catch (NoClassDefFoundError err) { - throw new IllegalStateException("Failed to introspect object class [" + clazz.getName() + - "] for annotation metadata: could not find class that it depends on", err); + throw new IllegalStateException("Failed to introspect object class [" + clazz.getName() + + "] for annotation metadata: could not find class that it depends on", err); } } } } return metadata; } - + @Override public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) { if (beanType != null) { @@ -324,60 +330,60 @@ public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, C metadata.checkConfigMembers(beanDefinition); } } - + @Override public int getOrder() { return order; } - + public void setOrder(int order) { this.order = order; } - + @Override public void destroy() throws Exception { - + for (Object object : injectedObjectsCache.values()) { if (logger.isInfoEnabled()) { logger.info(object + " was destroying!"); } - + if (object instanceof DisposableBean) { ((DisposableBean) object).destroy(); } } - + injectionMetadataCache.clear(); injectedObjectsCache.clear(); - + if (logger.isInfoEnabled()) { logger.info(getClass() + " was destroying!"); } - + } - + @Override public void setBeanClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; } - + @Override public void setEnvironment(Environment environment) { this.environment = environment; } - + protected Environment getEnvironment() { return environment; } - + protected ClassLoader getClassLoader() { return classLoader; } - + protected ConfigurableListableBeanFactory getBeanFactory() { return beanFactory; } - + /** * Gets all injected-objects. * @@ -386,7 +392,7 @@ protected ConfigurableListableBeanFactory getBeanFactory() { protected Collection getInjectedObjects() { return this.injectedObjectsCache.values(); } - + /** * Get injected-object from specified {@link AnnotationAttributes annotation attributes} and Bean Class * @@ -398,23 +404,23 @@ protected Collection getInjectedObjects() { * @return An injected object * @throws Exception If getting is failed */ - protected Object getInjectedObject(AnnotationAttributes attributes, Object bean, String beanName, Class injectedType, - InjectionMetadata.InjectedElement injectedElement) throws Exception { - + protected Object getInjectedObject(AnnotationAttributes attributes, Object bean, String beanName, + Class injectedType, InjectionMetadata.InjectedElement injectedElement) throws Exception { + String cacheKey = buildInjectedObjectCacheKey(attributes, bean, beanName, injectedType, injectedElement); - + Object injectedObject = injectedObjectsCache.get(cacheKey); - + if (injectedObject == null) { injectedObject = doGetInjectedBean(attributes, bean, beanName, injectedType, injectedElement); // Customized inject-object if necessary injectedObjectsCache.putIfAbsent(cacheKey, injectedObject); } - + return injectedObject; - + } - + /** * Subclass must implement this method to get injected-object. The context objects could help this method if * necessary : @@ -432,12 +438,11 @@ protected Object getInjectedObject(AnnotationAttributes attributes, Object bean, * @return The injected object * @throws Exception If resolving an injected object is failed. */ - protected abstract Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class injectedType, - InjectionMetadata.InjectedElement injectedElement) throws Exception; - + protected abstract Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, + Class injectedType, InjectionMetadata.InjectedElement injectedElement) throws Exception; + /** - * Build a cache key for injected-object. The context objects could help this method if - * necessary : + * Build a cache key for injected-object. The context objects could help this method if necessary : *
    *
  • {@link #getBeanFactory() BeanFactory}
  • *
  • {@link #getClassLoader() ClassLoader}
  • @@ -452,82 +457,78 @@ protected abstract Object doGetInjectedBean(AnnotationAttributes attributes, Obj * @return Bean cache key */ protected abstract String buildInjectedObjectCacheKey(AnnotationAttributes attributes, Object bean, String beanName, - Class injectedType, - InjectionMetadata.InjectedElement injectedElement); - + Class injectedType, InjectionMetadata.InjectedElement injectedElement); + /** * Get {@link Map} in injected field. * * @return non-null ready-only {@link Map} */ protected Map getInjectedFieldObjectsMap() { - - Map injectedElementBeanMap = - new LinkedHashMap(); - + + Map injectedElementBeanMap = new LinkedHashMap(); + for (AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata metadata : injectionMetadataCache.values()) { - + Collection fieldElements = metadata.getFieldElements(); - + for (AbstractAnnotationBeanPostProcessor.AnnotatedFieldElement fieldElement : fieldElements) { - + injectedElementBeanMap.put(fieldElement, fieldElement.bean); - + } - + } - + return unmodifiableMap(injectedElementBeanMap); - + } - + /** * Get {@link Map} in injected method. * * @return non-null {@link Map} */ protected Map getInjectedMethodObjectsMap() { - - Map injectedElementBeanMap = - new LinkedHashMap(); - + + Map injectedElementBeanMap = new LinkedHashMap(); + for (AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata metadata : injectionMetadataCache.values()) { - + Collection methodElements = metadata.getMethodElements(); - + for (AbstractAnnotationBeanPostProcessor.AnnotatedMethodElement methodElement : methodElements) { - + injectedElementBeanMap.put(methodElement, methodElement.object); - + } - + } - + return unmodifiableMap(injectedElementBeanMap); - + } - + /** - * @param classValuesAsString whether to turn Class references into Strings (for - * compatibility with {@link org.springframework.core.type.AnnotationMetadata} or to - * preserve them as Class references + * @param classValuesAsString whether to turn Class references into Strings (for compatibility with {@link + * org.springframework.core.type.AnnotationMetadata} or to preserve them as Class + * references * @since 1.0.11 */ public void setClassValuesAsString(boolean classValuesAsString) { this.classValuesAsString = classValuesAsString; } - + /** - * @param nestedAnnotationsAsMap whether to turn nested Annotation instances into - * {@link AnnotationAttributes} maps (for compatibility with - * {@link org.springframework.core.type.AnnotationMetadata} or to preserve them as - * Annotation instances + * @param nestedAnnotationsAsMap whether to turn nested Annotation instances into {@link AnnotationAttributes} maps + * (for compatibility with {@link org.springframework.core.type.AnnotationMetadata} or + * to preserve them as Annotation instances * @since 1.0.11 */ public void setNestedAnnotationsAsMap(boolean nestedAnnotationsAsMap) { this.nestedAnnotationsAsMap = nestedAnnotationsAsMap; } - + /** * @param ignoreDefaultValue whether ignore default value or not * @since 1.0.11 @@ -535,7 +536,7 @@ public void setNestedAnnotationsAsMap(boolean nestedAnnotationsAsMap) { public void setIgnoreDefaultValue(boolean ignoreDefaultValue) { this.ignoreDefaultValue = ignoreDefaultValue; } - + /** * @param tryMergedAnnotation whether try merged annotation or not * @since 1.0.11 @@ -543,94 +544,95 @@ public void setIgnoreDefaultValue(boolean ignoreDefaultValue) { public void setTryMergedAnnotation(boolean tryMergedAnnotation) { this.tryMergedAnnotation = tryMergedAnnotation; } - + /** * {@link Annotation Annotated} {@link InjectionMetadata} implementation */ private class AnnotatedInjectionMetadata extends InjectionMetadata { - + private final Collection fieldElements; - + private final Collection methodElements; - - public AnnotatedInjectionMetadata(Class targetClass, Collection fieldElements, - Collection methodElements) { + + public AnnotatedInjectionMetadata(Class targetClass, + Collection fieldElements, + Collection methodElements) { super(targetClass, combine(fieldElements, methodElements)); this.fieldElements = fieldElements; this.methodElements = methodElements; } - + public Collection getFieldElements() { return fieldElements; } - + public Collection getMethodElements() { return methodElements; } } - + /** * {@link Annotation Annotated} {@link Method} {@link InjectionMetadata.InjectedElement} */ private class AnnotatedMethodElement extends InjectionMetadata.InjectedElement { - + private final Method method; - + private final AnnotationAttributes attributes; - + private volatile Object object; - + protected AnnotatedMethodElement(Method method, PropertyDescriptor pd, AnnotationAttributes attributes) { super(method, pd); this.method = method; this.attributes = attributes; } - + @Override protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable { - + Class injectedType = pd.getPropertyType(); - + Object injectedObject = getInjectedObject(attributes, bean, beanName, injectedType, this); - + ReflectionUtils.makeAccessible(method); - + method.invoke(bean, injectedObject); - + } - + } - + /** * {@link Annotation Annotated} {@link Field} {@link InjectionMetadata.InjectedElement} */ public class AnnotatedFieldElement extends InjectionMetadata.InjectedElement { - + private final Field field; - + private final AnnotationAttributes attributes; - + private volatile Object bean; - + protected AnnotatedFieldElement(Field field, AnnotationAttributes attributes) { super(field, null); this.field = field; this.attributes = attributes; } - + @Override protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable { - + Class injectedType = resolveInjectedType(bean, field); - + Object injectedObject = getInjectedObject(attributes, bean, beanName, injectedType, this); - + ReflectionUtils.makeAccessible(field); - + field.set(bean, injectedObject); - + } - + private Class resolveInjectedType(Object bean, Field field) { Type genericType = field.getGenericType(); if (genericType instanceof Class) { // Just a normal Class diff --git a/src/main/java/com/alibaba/spring/beans/factory/annotation/AnnotationInjectedBeanPostProcessor.java b/src/main/java/com/alibaba/spring/beans/factory/annotation/AnnotationInjectedBeanPostProcessor.java index fd573cf..ab9eca4 100644 --- a/src/main/java/com/alibaba/spring/beans/factory/annotation/AnnotationInjectedBeanPostProcessor.java +++ b/src/main/java/com/alibaba/spring/beans/factory/annotation/AnnotationInjectedBeanPostProcessor.java @@ -29,7 +29,7 @@ import org.springframework.beans.factory.annotation.InjectionMetadata; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; +import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor; import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.EnvironmentAware; @@ -72,8 +72,8 @@ */ @Deprecated @SuppressWarnings("unchecked") -public abstract class AnnotationInjectedBeanPostProcessor extends - InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, +public abstract class AnnotationInjectedBeanPostProcessor + implements SmartInstantiationAwareBeanPostProcessor,MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware, BeanClassLoaderAware, EnvironmentAware, DisposableBean { private final static int CACHE_SIZE = Integer.getInteger("", 32); @@ -121,11 +121,11 @@ public void setBeanFactory(BeanFactory beanFactory) throws BeansException { "AnnotationInjectedBeanPostProcessor requires a ConfigurableListableBeanFactory"); this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; } - + @Override - public PropertyValues postProcessPropertyValues( - PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException { - + public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) + throws BeansException { + InjectionMetadata metadata = findInjectionMetadata(beanName, bean.getClass(), pvs); try { metadata.inject(bean, beanName, pvs); @@ -137,8 +137,7 @@ public PropertyValues postProcessPropertyValues( } return pvs; } - - + /** * Finds {@link InjectionMetadata.InjectedElement} Metadata from annotated {@link A} fields *