Consistent support for SpEL next to placeholders in annotation attributes

Issue: SPR-13625
This commit is contained in:
Juergen Hoeller
2016-02-17 23:00:07 +01:00
parent e0d7c6be00
commit ea4a766df7
8 changed files with 157 additions and 57 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2016 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.
@@ -29,7 +29,9 @@ import org.springframework.util.StringValueResolver;
* @author Juergen Hoeller
* @author Chris Beams
* @since 3.0.3
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#resolveEmbeddedValue
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#resolveEmbeddedValue(String)
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#getBeanExpressionResolver()
* @see org.springframework.beans.factory.config.EmbeddedValueResolver
*/
public interface EmbeddedValueResolverAware extends Aware {

View File

@@ -58,6 +58,7 @@ import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.config.EmbeddedValueResolver;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.BridgeMethodResolver;
@@ -68,6 +69,7 @@ import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.StringValueResolver;
/**
* {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation
@@ -181,6 +183,8 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
private transient BeanFactory beanFactory;
private transient StringValueResolver embeddedValueResolver;
private transient final Map<String, InjectionMetadata> injectionMetadataCache =
new ConcurrentHashMap<String, InjectionMetadata>(256);
@@ -274,12 +278,15 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
public void setBeanFactory(BeanFactory beanFactory) {
Assert.notNull(beanFactory, "BeanFactory must not be null");
this.beanFactory = beanFactory;
if (this.resourceFactory == null) {
this.resourceFactory = beanFactory;
}
if (beanFactory instanceof ConfigurableBeanFactory) {
this.embeddedValueResolver = new EmbeddedValueResolver((ConfigurableBeanFactory) beanFactory);
}
}
@@ -595,8 +602,8 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
resourceName = Introspector.decapitalize(resourceName.substring(3));
}
}
else if (beanFactory instanceof ConfigurableBeanFactory){
resourceName = ((ConfigurableBeanFactory) beanFactory).resolveEmbeddedValue(resourceName);
else if (embeddedValueResolver != null) {
resourceName = embeddedValueResolver.resolveStringValue(resourceName);
}
if (resourceType != null && Object.class != resourceType) {
checkResourceType(resourceType);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
@@ -23,7 +23,7 @@ import java.security.PrivilegedAction;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.Aware;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.EmbeddedValueResolver;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.ConfigurableApplicationContext;
@@ -61,12 +61,15 @@ class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ConfigurableApplicationContext applicationContext;
private final StringValueResolver embeddedValueResolver;
/**
* Create a new ApplicationContextAwareProcessor for the given context.
*/
public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
}
@@ -103,8 +106,7 @@ class ApplicationContextAwareProcessor implements BeanPostProcessor {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
@@ -126,19 +128,4 @@ class ApplicationContextAwareProcessor implements BeanPostProcessor {
return bean;
}
private static class EmbeddedValueResolver implements StringValueResolver {
private final ConfigurableBeanFactory beanFactory;
public EmbeddedValueResolver(ConfigurableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Override
public String resolveStringValue(String strVal) {
return this.beanFactory.resolveEmbeddedValue(strVal);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -27,6 +27,7 @@ import org.springframework.beans.annotation.AnnotationBeanUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.EmbeddedValueResolver;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.jmx.export.metadata.InvalidMetadataException;
import org.springframework.jmx.export.metadata.JmxAttributeSource;
@@ -50,19 +51,13 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource, BeanFac
@Override
public void setBeanFactory(final BeanFactory beanFactory) {
public void setBeanFactory(BeanFactory beanFactory) {
if (beanFactory instanceof ConfigurableBeanFactory) {
// Not using EmbeddedValueResolverAware in order to avoid a spring-context dependency:
// ConfigurableBeanFactory and its resolveEmbeddedValue live in the spring-beans module.
this.embeddedValueResolver = new StringValueResolver() {
@Override
public String resolveStringValue(String strVal) {
return ((ConfigurableBeanFactory) beanFactory).resolveEmbeddedValue(strVal);
}
};
this.embeddedValueResolver = new EmbeddedValueResolver((ConfigurableBeanFactory) beanFactory);
}
}
@Override
public org.springframework.jmx.export.metadata.ManagedResource getManagedResource(Class<?> beanClass) throws InvalidMetadataException {
ManagedResource ann = AnnotationUtils.findAnnotation(beanClass, ManagedResource.class);