diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java index 4b6d08df967..6a46d4e961a 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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.junit.Test; import org.springframework.aop.scope.ScopedObject; import org.springframework.aop.scope.ScopedProxyUtils; +import org.springframework.aop.support.AopUtils; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.NoSuchBeanDefinitionException; @@ -280,6 +281,7 @@ public class ConfigurationClassPostProcessorTests { beanFactory.registerBeanDefinition("consumer", new RootBeanDefinition(ScopedProxyConsumer.class)); ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); pp.postProcessBeanFactory(beanFactory); + ITestBean injected = beanFactory.getBean("consumer", ScopedProxyConsumer.class).testBean; assertTrue(injected instanceof ScopedObject); assertSame(beanFactory.getBean("scopedClass"), injected); @@ -357,6 +359,28 @@ public class ConfigurationClassPostProcessorTests { RepositoryInjectionBean bean = (RepositoryInjectionBean) beanFactory.getBean("annotatedBean"); assertEquals("Repository", bean.stringRepository.toString()); assertEquals("Repository", bean.integerRepository.toString()); + assertTrue(AopUtils.isCglibProxy(bean.stringRepository)); + assertTrue(AopUtils.isCglibProxy(bean.integerRepository)); + } + + @Test + public void genericsBasedInjectionWithScopedProxyUsingAsm() { + AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); + bpp.setBeanFactory(beanFactory); + beanFactory.addBeanPostProcessor(bpp); + RootBeanDefinition bd = new RootBeanDefinition(RepositoryInjectionBean.class.getName()); + bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE); + beanFactory.registerBeanDefinition("annotatedBean", bd); + beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(ScopedProxyRepositoryConfiguration.class.getName())); + ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); + pp.postProcessBeanFactory(beanFactory); + beanFactory.freezeConfiguration(); + + RepositoryInjectionBean bean = (RepositoryInjectionBean) beanFactory.getBean("annotatedBean"); + assertEquals("Repository", bean.stringRepository.toString()); + assertEquals("Repository", bean.integerRepository.toString()); + assertTrue(AopUtils.isCglibProxy(bean.stringRepository)); + assertTrue(AopUtils.isCglibProxy(bean.integerRepository)); } @Test @@ -487,13 +511,11 @@ public class ConfigurationClassPostProcessorTests { @Configuration static class SingletonBeanConfig { - public @Bean - Foo foo() { + public @Bean Foo foo() { return new Foo(); } - public @Bean - Bar bar() { + public @Bean Bar bar() { return new Bar(foo()); } } @@ -650,6 +672,13 @@ public class ConfigurationClassPostProcessorTests { } } + @Retention(RetentionPolicy.RUNTIME) + @Scope(value = "prototype") + public @interface PrototypeScoped { + + ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS; + } + @Configuration public static class ScopedProxyRepositoryConfiguration { @@ -665,7 +694,7 @@ public class ConfigurationClassPostProcessorTests { } @Bean - @Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS) + @PrototypeScoped public Repository integerRepo() { return new Repository() { @Override diff --git a/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java b/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java index 62ceb04d7cb..ea03d3d5740 100644 --- a/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java +++ b/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -58,7 +58,8 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito * to ensure that the hierarchical ordering of the entries is preserved. * @see AnnotationReadingVisitorUtils#getMergedAnnotationAttributes */ - protected final LinkedMultiValueMap attributesMap = new LinkedMultiValueMap(4); + protected final LinkedMultiValueMap attributesMap = + new LinkedMultiValueMap(4); protected final Set methodMetadataSet = new LinkedHashSet(4); @@ -75,14 +76,16 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito if ((access & Opcodes.ACC_BRIDGE) != 0) { return super.visitMethod(access, name, desc, signature, exceptions); } - return new MethodMetadataReadingVisitor(name, access, getClassName(), this.classLoader, this.methodMetadataSet); + return new MethodMetadataReadingVisitor( + name, access, getClassName(), this.classLoader, this.methodMetadataSet); } @Override public AnnotationVisitor visitAnnotation(final String desc, boolean visible) { String className = Type.getType(desc).getClassName(); this.annotationSet.add(className); - return new AnnotationAttributesReadingVisitor(className, this.attributesMap, this.metaAnnotationMap, this.classLoader); + return new AnnotationAttributesReadingVisitor( + className, this.attributesMap, this.metaAnnotationMap, this.classLoader); } @@ -142,8 +145,8 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito return null; } for (AnnotationAttributes raw : attributes) { - for (Map.Entry entry : - AnnotationReadingVisitorUtils.convertClassValues(this.classLoader, raw, classValuesAsString).entrySet()) { + for (Map.Entry entry : AnnotationReadingVisitorUtils.convertClassValues( + this.classLoader, raw, classValuesAsString).entrySet()) { allAttributes.add(entry.getKey(), entry.getValue()); } } diff --git a/spring-core/src/main/java/org/springframework/core/type/classreading/MethodMetadataReadingVisitor.java b/spring-core/src/main/java/org/springframework/core/type/classreading/MethodMetadataReadingVisitor.java index f88b57b0d07..3d77d4c3618 100644 --- a/spring-core/src/main/java/org/springframework/core/type/classreading/MethodMetadataReadingVisitor.java +++ b/spring-core/src/main/java/org/springframework/core/type/classreading/MethodMetadataReadingVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2015 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. @@ -16,7 +16,7 @@ package org.springframework.core.type.classreading; -import java.util.List; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; @@ -31,7 +31,7 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; /** - * ASM method visitor which looks for the annotations defined on the method, + * ASM method visitor which looks for the annotations defined on a method, * exposing them through the {@link org.springframework.core.type.MethodMetadata} * interface. * @@ -54,7 +54,9 @@ public class MethodMetadataReadingVisitor extends MethodVisitor implements Metho protected final Set methodMetadataSet; - protected final MultiValueMap attributeMap = + protected final Map> metaAnnotationMap = new LinkedHashMap>(4); + + protected final LinkedMultiValueMap attributesMap = new LinkedMultiValueMap(4); @@ -74,7 +76,8 @@ public class MethodMetadataReadingVisitor extends MethodVisitor implements Metho public AnnotationVisitor visitAnnotation(final String desc, boolean visible) { String className = Type.getType(desc).getClassName(); this.methodMetadataSet.add(this); - return new AnnotationAttributesReadingVisitor(className, this.attributeMap, null, this.classLoader); + return new AnnotationAttributesReadingVisitor( + className, this.attributesMap, this.metaAnnotationMap, this.classLoader); } @Override @@ -99,7 +102,7 @@ public class MethodMetadataReadingVisitor extends MethodVisitor implements Metho @Override public boolean isAnnotated(String annotationType) { - return this.attributeMap.containsKey(annotationType); + return this.attributesMap.containsKey(annotationType); } @Override @@ -109,9 +112,9 @@ public class MethodMetadataReadingVisitor extends MethodVisitor implements Metho @Override public Map getAnnotationAttributes(String annotationType, boolean classValuesAsString) { - List attributes = this.attributeMap.get(annotationType); - return (attributes == null ? null : AnnotationReadingVisitorUtils.convertClassValues( - this.classLoader, attributes.get(0), classValuesAsString)); + AnnotationAttributes raw = AnnotationReadingVisitorUtils.getMergedAnnotationAttributes( + this.attributesMap, this.metaAnnotationMap, annotationType); + return AnnotationReadingVisitorUtils.convertClassValues(this.classLoader, raw, classValuesAsString); } @Override @@ -121,11 +124,11 @@ public class MethodMetadataReadingVisitor extends MethodVisitor implements Metho @Override public MultiValueMap getAllAnnotationAttributes(String annotationType, boolean classValuesAsString) { - if (!this.attributeMap.containsKey(annotationType)) { + if (!this.attributesMap.containsKey(annotationType)) { return null; } MultiValueMap allAttributes = new LinkedMultiValueMap(); - for (AnnotationAttributes annotationAttributes : this.attributeMap.get(annotationType)) { + for (AnnotationAttributes annotationAttributes : this.attributesMap.get(annotationType)) { for (Map.Entry entry : AnnotationReadingVisitorUtils.convertClassValues( this.classLoader, annotationAttributes, classValuesAsString).entrySet()) { allAttributes.add(entry.getKey(), entry.getValue());