@Override public String[] selectImports(AnnotationMetadata metadata) { try { AnnotationAttributes attributes = AnnotationAttributes.fromMap( metadata.getAnnotationAttributes(EnableAutoConfiguration.class.getName(), true)); Assert.notNull( attributes, "No auto-configuration attributes found. Is " + metadata.getClassName() + " annotated with @EnableAutoConfiguration?"); // Find all possible auto configuration classes, filtering duplicates List<String> factories = new ArrayList<String>( new LinkedHashSet<String>( SpringFactoriesLoader.loadFactoryNames( EnableAutoConfiguration.class, this.beanClassLoader))); // Remove those specifically excluded Set<String> excluded = new LinkedHashSet<String>(); excluded.addAll(Arrays.asList(attributes.getStringArray("exclude"))); excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName"))); factories.removeAll(excluded); ConditionEvaluationReport.get(this.beanFactory).recordExclusions(excluded); // Sort factories = new AutoConfigurationSorter(this.resourceLoader).getInPriorityOrder(factories); return factories.toArray(new String[factories.size()]); } catch (IOException ex) { throw new IllegalStateException(ex); } }
private void assertMetaAnnotationOverrides(AnnotationMetadata metadata) { AnnotationAttributes attributes = (AnnotationAttributes) metadata.getAnnotationAttributes(TestComponentScan.class.getName(), false); String[] basePackages = attributes.getStringArray("basePackages"); assertThat("length of basePackages[]", basePackages.length, is(1)); assertThat("basePackages[0]", basePackages[0], is("org.example.componentscan")); String[] value = attributes.getStringArray("value"); assertThat("length of value[]", value.length, is(0)); Class<?>[] basePackageClasses = attributes.getClassArray("basePackageClasses"); assertThat("length of basePackageClasses[]", basePackageClasses.length, is(0)); }
/** * Determine whether the given class does not match any exclude filter and does match at least one * include filter. * * @param metadataReader the ASM ClassReader for the class * @return whether the class qualifies as a candidate component */ protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException { for (TypeFilter tf : this.excludeFilters) { if (tf.match(metadataReader, this.metadataReaderFactory)) { return false; } } for (TypeFilter tf : this.includeFilters) { if (tf.match(metadataReader, this.metadataReaderFactory)) { AnnotationMetadata metadata = metadataReader.getAnnotationMetadata(); if (!metadata.isAnnotated(Profile.class.getName())) { return true; } AnnotationAttributes profile = MetadataUtils.attributesFor(metadata, Profile.class); return this.environment.acceptsProfiles(profile.getStringArray("value")); } } return false; }
@Test public void overriddenContextConfigurationLocationsAndInheritLocations() throws Exception { Class<?> declaringClass = OverriddenMetaLocationsConfigTestCase.class; AnnotationDescriptor<ContextConfiguration> descriptor = findAnnotationDescriptor(declaringClass, ContextConfiguration.class); assertNotNull(descriptor); assertEquals(declaringClass, descriptor.getRootDeclaringClass()); assertEquals(MetaLocationsConfig.class, descriptor.getComposedAnnotationType()); assertEquals(ContextConfiguration.class, descriptor.getAnnotationType()); assertNotNull(descriptor.getComposedAnnotation()); assertEquals(MetaLocationsConfig.class, descriptor.getComposedAnnotationType()); // direct access to annotation attributes: assertArrayEquals(new String[] {"foo.xml"}, descriptor.getAnnotation().locations()); assertFalse(descriptor.getAnnotation().inheritLocations()); // overridden attributes: AnnotationAttributes attributes = descriptor.getAnnotationAttributes(); assertArrayEquals(new String[] {"bar.xml"}, attributes.getStringArray("locations")); assertTrue(attributes.getBoolean("inheritLocations")); }
/** * Process the given <code>@PropertySource</code> annotation metadata. * * @param propertySource metadata for the <code>@PropertySource</code> annotation found * @throws IOException if loading a property source failed */ private void processPropertySource(AnnotationAttributes propertySource) throws IOException { String name = propertySource.getString("name"); String encoding = propertySource.getString("encoding"); String[] locations = propertySource.getStringArray("value"); boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound"); Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required"); for (String location : locations) { try { String resolvedLocation = this.environment.resolveRequiredPlaceholders(location); Resource resource = this.resourceLoader.getResource(resolvedLocation); addPropertySource(createPropertySource(name, encoding, resource)); } catch (IllegalArgumentException ex) { // from resolveRequiredPlaceholders if (!ignoreResourceNotFound) { throw ex; } } catch (FileNotFoundException ex) { // from ResourcePropertySource constructor if (!ignoreResourceNotFound) { throw ex; } } } }
@Test public void overriddenContextConfigurationValue() throws Exception { Class<?> declaringClass = OverriddenMetaValueConfigTestCase.class; AnnotationDescriptor<ContextConfiguration> descriptor = findAnnotationDescriptor(declaringClass, ContextConfiguration.class); assertNotNull(descriptor); assertEquals(declaringClass, descriptor.getRootDeclaringClass()); assertEquals(MetaValueConfig.class, descriptor.getComposedAnnotationType()); assertEquals(ContextConfiguration.class, descriptor.getAnnotationType()); assertNotNull(descriptor.getComposedAnnotation()); assertEquals(MetaValueConfig.class, descriptor.getComposedAnnotationType()); // direct access to annotation value: assertArrayEquals(new String[] {"foo.xml"}, descriptor.getAnnotation().value()); // overridden attribute: AnnotationAttributes attributes = descriptor.getAnnotationAttributes(); // NOTE: we would like to be able to override the 'value' attribute; however, // Spring currently does not allow overrides for the 'value' attribute. // TODO Determine if Spring should allow overrides for the 'value' attribute in // custom annotations. assertArrayEquals(new String[] {"foo.xml"}, attributes.getStringArray("value")); }
private void doTestAnnotationInfo(AnnotationMetadata metadata) { assertThat(metadata.getClassName(), is(AnnotatedComponent.class.getName())); assertThat(metadata.isInterface(), is(false)); assertThat(metadata.isAnnotation(), is(false)); assertThat(metadata.isAbstract(), is(false)); assertThat(metadata.isConcrete(), is(true)); assertThat(metadata.hasSuperClass(), is(true)); assertThat(metadata.getSuperClassName(), is(Object.class.getName())); assertThat(metadata.getInterfaceNames().length, is(1)); assertThat(metadata.getInterfaceNames()[0], is(Serializable.class.getName())); assertThat(metadata.hasAnnotation(Component.class.getName()), is(true)); assertThat(metadata.hasAnnotation(Scope.class.getName()), is(true)); assertThat(metadata.hasAnnotation(SpecialAttr.class.getName()), is(true)); assertThat(metadata.getAnnotationTypes().size(), is(6)); assertThat(metadata.getAnnotationTypes().contains(Component.class.getName()), is(true)); assertThat(metadata.getAnnotationTypes().contains(Scope.class.getName()), is(true)); assertThat(metadata.getAnnotationTypes().contains(SpecialAttr.class.getName()), is(true)); AnnotationAttributes compAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(Component.class.getName()); assertThat(compAttrs.size(), is(1)); assertThat(compAttrs.getString("value"), is("myName")); AnnotationAttributes scopeAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(Scope.class.getName()); assertThat(scopeAttrs.size(), is(1)); assertThat(scopeAttrs.getString("value"), is("myScope")); Set<MethodMetadata> methods = metadata.getAnnotatedMethods(DirectAnnotation.class.getName()); MethodMetadata method = methods.iterator().next(); assertEquals( "direct", method.getAnnotationAttributes(DirectAnnotation.class.getName()).get("value")); List<Object> allMeta = method.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("value"); assertThat( new HashSet<>(allMeta), is(equalTo(new HashSet<Object>(Arrays.asList("direct", "meta"))))); allMeta = method.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("additional"); assertThat(new HashSet<>(allMeta), is(equalTo(new HashSet<Object>(Arrays.asList("direct"))))); assertTrue(metadata.isAnnotated(IsAnnotatedAnnotation.class.getName())); { // perform tests with classValuesAsString = false (the default) AnnotationAttributes specialAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(SpecialAttr.class.getName()); assertThat(specialAttrs.size(), is(6)); assertTrue(String.class.isAssignableFrom(specialAttrs.getClass("clazz"))); assertTrue(specialAttrs.getEnum("state").equals(Thread.State.NEW)); AnnotationAttributes nestedAnno = specialAttrs.getAnnotation("nestedAnno"); assertThat("na", is(nestedAnno.getString("value"))); assertTrue(nestedAnno.getEnum("anEnum").equals(SomeEnum.LABEL1)); assertArrayEquals(new Class[] {String.class}, (Class[]) nestedAnno.get("classArray")); AnnotationAttributes[] nestedAnnoArray = specialAttrs.getAnnotationArray("nestedAnnoArray"); assertThat(nestedAnnoArray.length, is(2)); assertThat(nestedAnnoArray[0].getString("value"), is("default")); assertTrue(nestedAnnoArray[0].getEnum("anEnum").equals(SomeEnum.DEFAULT)); assertArrayEquals(new Class[] {Void.class}, (Class[]) nestedAnnoArray[0].get("classArray")); assertThat(nestedAnnoArray[1].getString("value"), is("na1")); assertTrue(nestedAnnoArray[1].getEnum("anEnum").equals(SomeEnum.LABEL2)); assertArrayEquals(new Class[] {Number.class}, (Class[]) nestedAnnoArray[1].get("classArray")); assertArrayEquals(new Class[] {Number.class}, nestedAnnoArray[1].getClassArray("classArray")); AnnotationAttributes optional = specialAttrs.getAnnotation("optional"); assertThat(optional.getString("value"), is("optional")); assertTrue(optional.getEnum("anEnum").equals(SomeEnum.DEFAULT)); assertArrayEquals(new Class[] {Void.class}, (Class[]) optional.get("classArray")); assertArrayEquals(new Class[] {Void.class}, optional.getClassArray("classArray")); AnnotationAttributes[] optionalArray = specialAttrs.getAnnotationArray("optionalArray"); assertThat(optionalArray.length, is(1)); assertThat(optionalArray[0].getString("value"), is("optional")); assertTrue(optionalArray[0].getEnum("anEnum").equals(SomeEnum.DEFAULT)); assertArrayEquals(new Class[] {Void.class}, (Class[]) optionalArray[0].get("classArray")); assertArrayEquals(new Class[] {Void.class}, optionalArray[0].getClassArray("classArray")); assertEquals( "direct", metadata.getAnnotationAttributes(DirectAnnotation.class.getName()).get("value")); allMeta = metadata.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("value"); assertThat( new HashSet<>(allMeta), is(equalTo(new HashSet<Object>(Arrays.asList("direct", "meta"))))); allMeta = metadata.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("additional"); assertThat(new HashSet<>(allMeta), is(equalTo(new HashSet<Object>(Arrays.asList("direct"))))); } { // perform tests with classValuesAsString = true AnnotationAttributes specialAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(SpecialAttr.class.getName(), true); assertThat(specialAttrs.size(), is(6)); assertThat(specialAttrs.get("clazz"), is((Object) String.class.getName())); assertThat(specialAttrs.getString("clazz"), is(String.class.getName())); AnnotationAttributes nestedAnno = specialAttrs.getAnnotation("nestedAnno"); assertArrayEquals( new String[] {String.class.getName()}, nestedAnno.getStringArray("classArray")); assertArrayEquals( new String[] {String.class.getName()}, nestedAnno.getStringArray("classArray")); AnnotationAttributes[] nestedAnnoArray = specialAttrs.getAnnotationArray("nestedAnnoArray"); assertArrayEquals( new String[] {Void.class.getName()}, (String[]) nestedAnnoArray[0].get("classArray")); assertArrayEquals( new String[] {Void.class.getName()}, nestedAnnoArray[0].getStringArray("classArray")); assertArrayEquals( new String[] {Number.class.getName()}, (String[]) nestedAnnoArray[1].get("classArray")); assertArrayEquals( new String[] {Number.class.getName()}, nestedAnnoArray[1].getStringArray("classArray")); AnnotationAttributes optional = specialAttrs.getAnnotation("optional"); assertArrayEquals(new String[] {Void.class.getName()}, (String[]) optional.get("classArray")); assertArrayEquals(new String[] {Void.class.getName()}, optional.getStringArray("classArray")); AnnotationAttributes[] optionalArray = specialAttrs.getAnnotationArray("optionalArray"); assertArrayEquals( new String[] {Void.class.getName()}, (String[]) optionalArray[0].get("classArray")); assertArrayEquals( new String[] {Void.class.getName()}, optionalArray[0].getStringArray("classArray")); assertEquals( metadata.getAnnotationAttributes(DirectAnnotation.class.getName()).get("value"), "direct"); allMeta = metadata.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("value"); assertThat( new HashSet<>(allMeta), is(equalTo(new HashSet<Object>(Arrays.asList("direct", "meta"))))); } }
/** * Read the given {@link BeanMethod}, registering bean definitions with the BeanDefinitionRegistry * based on its contents. */ private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) { ConfigurationClass configClass = beanMethod.getConfigurationClass(); MethodMetadata metadata = beanMethod.getMetadata(); String methodName = metadata.getMethodName(); // Do we need to mark the bean as skipped by its condition? if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) { configClass.skippedBeanMethods.add(methodName); return; } if (configClass.skippedBeanMethods.contains(methodName)) { return; } // Consider name and any aliases AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class); List<String> names = new ArrayList<String>(Arrays.asList(bean.getStringArray("name"))); String beanName = (names.size() > 0 ? names.remove(0) : methodName); // Register aliases even when overridden for (String alias : names) { this.registry.registerAlias(beanName, alias); } // Has this effectively been overridden before (e.g. via XML)? if (isOverriddenByExistingDefinition(beanMethod, beanName)) { return; } ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata); beanDef.setResource(configClass.getResource()); beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource())); if (metadata.isStatic()) { // static @Bean method beanDef.setBeanClassName(configClass.getMetadata().getClassName()); beanDef.setFactoryMethodName(methodName); } else { // instance @Bean method beanDef.setFactoryBeanName(configClass.getBeanName()); beanDef.setUniqueFactoryMethodName(methodName); } beanDef.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR); beanDef.setAttribute( RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE); AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata); Autowire autowire = bean.getEnum("autowire"); if (autowire.isAutowire()) { beanDef.setAutowireMode(autowire.value()); } String initMethodName = bean.getString("initMethod"); if (StringUtils.hasText(initMethodName)) { beanDef.setInitMethodName(initMethodName); } String destroyMethodName = bean.getString("destroyMethod"); if (destroyMethodName != null) { beanDef.setDestroyMethodName(destroyMethodName); } // Consider scoping ScopedProxyMode proxyMode = ScopedProxyMode.NO; // TODO Determine why type is hard coded to org.springframework.context.annotation.Scope, // since AnnotationScopeMetadataResolver supports a custom scope annotation type. AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class); if (attributes != null) { beanDef.setScope( attributes.getAliasedString("value", Scope.class, configClass.getResource())); proxyMode = attributes.getEnum("proxyMode"); if (proxyMode == ScopedProxyMode.DEFAULT) { proxyMode = ScopedProxyMode.NO; } } // Replace the original bean definition with the target one, if necessary BeanDefinition beanDefToRegister = beanDef; 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, metadata); } if (logger.isDebugEnabled()) { logger.debug( String.format( "Registering bean definition for @Bean method %s.%s()", configClass.getMetadata().getClassName(), beanName)); } this.registry.registerBeanDefinition(beanName, beanDefToRegister); }