Bean method metadata exposed through AnnotatedBeanDefinition

Issue: SPR-12232
This commit is contained in:
Juergen Hoeller 2014-09-26 14:46:09 +02:00
parent bf99d6a3b5
commit f46c706e44
5 changed files with 125 additions and 8 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 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.
@ -18,6 +18,7 @@ package org.springframework.beans.factory.annotation;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata;
/**
* Extended {@link org.springframework.beans.factory.config.BeanDefinition}
@ -38,4 +39,11 @@ public interface AnnotatedBeanDefinition extends BeanDefinition {
*/
AnnotationMetadata getMetadata();
/**
* Obtain metadata for this bean definition's factory method, if any.
* @return the factory method metadata, or {@code null} if none
* @since 4.1.1
*/
MethodMetadata getFactoryMethodMetadata();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 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.
@ -18,6 +18,7 @@ package org.springframework.beans.factory.annotation;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.StandardAnnotationMetadata;
import org.springframework.util.Assert;
@ -43,6 +44,8 @@ public class AnnotatedGenericBeanDefinition extends GenericBeanDefinition implem
private final AnnotationMetadata metadata;
private MethodMetadata factoryMethodMetadata;
/**
* Create a new AnnotatedGenericBeanDefinition for the given bean class.
@ -74,10 +77,29 @@ public class AnnotatedGenericBeanDefinition extends GenericBeanDefinition implem
this.metadata = metadata;
}
/**
* Create a new AnnotatedGenericBeanDefinition for the given annotation metadata,
* based on an annotated class and a factory method on that class.
* @param metadata the annotation metadata for the bean class in question
* @param factoryMethodMetadata metadata for the selected factory method
* @since 4.1.1
*/
public AnnotatedGenericBeanDefinition(AnnotationMetadata metadata, MethodMetadata factoryMethodMetadata) {
this(metadata);
Assert.notNull(factoryMethodMetadata, "MethodMetadata must not be null");
setFactoryMethodName(factoryMethodMetadata.getMethodName());
this.factoryMethodMetadata = factoryMethodMetadata;
}
@Override
public final AnnotationMetadata getMetadata() {
return this.metadata;
}
@Override
public final MethodMetadata getFactoryMethodMetadata() {
return this.factoryMethodMetadata;
}
}

View File

@ -181,7 +181,7 @@ class ConfigurationClassBeanDefinitionReader {
ConfigurationClass configClass = beanMethod.getConfigurationClass();
MethodMetadata metadata = beanMethod.getMetadata();
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass);
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
beanDef.setResource(configClass.getResource());
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
if (metadata.isStatic()) {
@ -243,8 +243,8 @@ class ConfigurationClassBeanDefinitionReader {
if (proxyMode != ScopedProxyMode.NO) {
BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
new BeanDefinitionHolder(beanDef, beanName), this.registry, proxyMode == ScopedProxyMode.TARGET_CLASS);
beanDefToRegister =
new ConfigurationClassBeanDefinition((RootBeanDefinition) proxyDef.getBeanDefinition(), configClass);
beanDefToRegister = new ConfigurationClassBeanDefinition(
(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata);
}
if (logger.isDebugEnabled()) {
@ -349,19 +349,25 @@ class ConfigurationClassBeanDefinitionReader {
private final AnnotationMetadata annotationMetadata;
public ConfigurationClassBeanDefinition(ConfigurationClass configClass) {
private final MethodMetadata factoryMethodMetadata;
public ConfigurationClassBeanDefinition(ConfigurationClass configClass, MethodMetadata beanMethodMetadata) {
this.annotationMetadata = configClass.getMetadata();
this.factoryMethodMetadata = beanMethodMetadata;
setLenientConstructorResolution(false);
}
public ConfigurationClassBeanDefinition(RootBeanDefinition original, ConfigurationClass configClass) {
public ConfigurationClassBeanDefinition(
RootBeanDefinition original, ConfigurationClass configClass, MethodMetadata beanMethodMetadata) {
super(original);
this.annotationMetadata = configClass.getMetadata();
this.factoryMethodMetadata = beanMethodMetadata;
}
private ConfigurationClassBeanDefinition(ConfigurationClassBeanDefinition original) {
super(original);
this.annotationMetadata = original.annotationMetadata;
this.factoryMethodMetadata = original.factoryMethodMetadata;
}
@Override
@ -369,6 +375,11 @@ class ConfigurationClassBeanDefinitionReader {
return this.annotationMetadata;
}
@Override
public MethodMetadata getFactoryMethodMetadata() {
return this.factoryMethodMetadata;
}
@Override
public boolean isFactoryMethod(Method candidate) {
return (super.isFactoryMethod(candidate) && BeanAnnotationHelper.isBeanAnnotated(candidate));

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 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.
@ -20,6 +20,7 @@ import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.util.Assert;
@ -66,4 +67,9 @@ public class ScannedGenericBeanDefinition extends GenericBeanDefinition implemen
return this.metadata;
}
@Override
public MethodMetadata getFactoryMethodMetadata() {
return null;
}
}

View File

@ -0,0 +1,70 @@
/*
* Copyright 2002-2014 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Map;
import org.junit.Test;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
/**
* @author Phillip Webb
* @author Juergen Hoeller
*/
public class BeanMethodMetadataTests {
@Test
public void providesBeanMethodBeanDefinition() throws Exception {
AnnotationConfigApplicationContext context= new AnnotationConfigApplicationContext(Conf.class);
BeanDefinition beanDefinition = context.getBeanDefinition("myBean");
assertThat("should provide AnnotatedBeanDefinition", beanDefinition, instanceOf(AnnotatedBeanDefinition.class));
Map<String, Object> annotationAttributes =
((AnnotatedBeanDefinition) beanDefinition).getFactoryMethodMetadata().getAnnotationAttributes(MyAnnotation.class.getName());
assertThat(annotationAttributes.get("value"), equalTo("test"));
context.close();
}
@Configuration
static class Conf {
@Bean
@MyAnnotation("test")
public MyBean myBean() {
return new MyBean();
}
}
static class MyBean {
}
@Retention(RetentionPolicy.RUNTIME)
public static @interface MyAnnotation {
String value();
}
}