001/* 002 * Copyright 2002-2020 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.context.annotation; 018 019import java.util.function.Supplier; 020 021import org.springframework.beans.factory.config.BeanDefinitionCustomizer; 022import org.springframework.beans.factory.support.BeanNameGenerator; 023import org.springframework.beans.factory.support.DefaultListableBeanFactory; 024import org.springframework.context.support.GenericApplicationContext; 025import org.springframework.core.env.ConfigurableEnvironment; 026import org.springframework.lang.Nullable; 027import org.springframework.util.Assert; 028 029/** 030 * Standalone application context, accepting <em>component classes</em> as input — 031 * in particular {@link Configuration @Configuration}-annotated classes, but also plain 032 * {@link org.springframework.stereotype.Component @Component} types and JSR-330 compliant 033 * classes using {@code javax.inject} annotations. 034 * 035 * <p>Allows for registering classes one by one using {@link #register(Class...)} 036 * as well as for classpath scanning using {@link #scan(String...)}. 037 * 038 * <p>In case of multiple {@code @Configuration} classes, {@link Bean @Bean} methods 039 * defined in later classes will override those defined in earlier classes. This can 040 * be leveraged to deliberately override certain bean definitions via an extra 041 * {@code @Configuration} class. 042 * 043 * <p>See {@link Configuration @Configuration}'s javadoc for usage examples. 044 * 045 * @author Juergen Hoeller 046 * @author Chris Beams 047 * @since 3.0 048 * @see #register 049 * @see #scan 050 * @see AnnotatedBeanDefinitionReader 051 * @see ClassPathBeanDefinitionScanner 052 * @see org.springframework.context.support.GenericXmlApplicationContext 053 */ 054public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry { 055 056 private final AnnotatedBeanDefinitionReader reader; 057 058 private final ClassPathBeanDefinitionScanner scanner; 059 060 061 /** 062 * Create a new AnnotationConfigApplicationContext that needs to be populated 063 * through {@link #register} calls and then manually {@linkplain #refresh refreshed}. 064 */ 065 public AnnotationConfigApplicationContext() { 066 this.reader = new AnnotatedBeanDefinitionReader(this); 067 this.scanner = new ClassPathBeanDefinitionScanner(this); 068 } 069 070 /** 071 * Create a new AnnotationConfigApplicationContext with the given DefaultListableBeanFactory. 072 * @param beanFactory the DefaultListableBeanFactory instance to use for this context 073 */ 074 public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) { 075 super(beanFactory); 076 this.reader = new AnnotatedBeanDefinitionReader(this); 077 this.scanner = new ClassPathBeanDefinitionScanner(this); 078 } 079 080 /** 081 * Create a new AnnotationConfigApplicationContext, deriving bean definitions 082 * from the given component classes and automatically refreshing the context. 083 * @param componentClasses one or more component classes — for example, 084 * {@link Configuration @Configuration} classes 085 */ 086 public AnnotationConfigApplicationContext(Class<?>... componentClasses) { 087 this(); 088 register(componentClasses); 089 refresh(); 090 } 091 092 /** 093 * Create a new AnnotationConfigApplicationContext, scanning for components 094 * in the given packages, registering bean definitions for those components, 095 * and automatically refreshing the context. 096 * @param basePackages the packages to scan for component classes 097 */ 098 public AnnotationConfigApplicationContext(String... basePackages) { 099 this(); 100 scan(basePackages); 101 refresh(); 102 } 103 104 105 /** 106 * Propagate the given custom {@code Environment} to the underlying 107 * {@link AnnotatedBeanDefinitionReader} and {@link ClassPathBeanDefinitionScanner}. 108 */ 109 @Override 110 public void setEnvironment(ConfigurableEnvironment environment) { 111 super.setEnvironment(environment); 112 this.reader.setEnvironment(environment); 113 this.scanner.setEnvironment(environment); 114 } 115 116 /** 117 * Provide a custom {@link BeanNameGenerator} for use with {@link AnnotatedBeanDefinitionReader} 118 * and/or {@link ClassPathBeanDefinitionScanner}, if any. 119 * <p>Default is {@link AnnotationBeanNameGenerator}. 120 * <p>Any call to this method must occur prior to calls to {@link #register(Class...)} 121 * and/or {@link #scan(String...)}. 122 * @see AnnotatedBeanDefinitionReader#setBeanNameGenerator 123 * @see ClassPathBeanDefinitionScanner#setBeanNameGenerator 124 * @see AnnotationBeanNameGenerator 125 * @see FullyQualifiedAnnotationBeanNameGenerator 126 */ 127 public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) { 128 this.reader.setBeanNameGenerator(beanNameGenerator); 129 this.scanner.setBeanNameGenerator(beanNameGenerator); 130 getBeanFactory().registerSingleton( 131 AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator); 132 } 133 134 /** 135 * Set the {@link ScopeMetadataResolver} to use for registered component classes. 136 * <p>The default is an {@link AnnotationScopeMetadataResolver}. 137 * <p>Any call to this method must occur prior to calls to {@link #register(Class...)} 138 * and/or {@link #scan(String...)}. 139 */ 140 public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) { 141 this.reader.setScopeMetadataResolver(scopeMetadataResolver); 142 this.scanner.setScopeMetadataResolver(scopeMetadataResolver); 143 } 144 145 146 //--------------------------------------------------------------------- 147 // Implementation of AnnotationConfigRegistry 148 //--------------------------------------------------------------------- 149 150 /** 151 * Register one or more component classes to be processed. 152 * <p>Note that {@link #refresh()} must be called in order for the context 153 * to fully process the new classes. 154 * @param componentClasses one or more component classes — for example, 155 * {@link Configuration @Configuration} classes 156 * @see #scan(String...) 157 * @see #refresh() 158 */ 159 @Override 160 public void register(Class<?>... componentClasses) { 161 Assert.notEmpty(componentClasses, "At least one component class must be specified"); 162 this.reader.register(componentClasses); 163 } 164 165 /** 166 * Perform a scan within the specified base packages. 167 * <p>Note that {@link #refresh()} must be called in order for the context 168 * to fully process the new classes. 169 * @param basePackages the packages to scan for component classes 170 * @see #register(Class...) 171 * @see #refresh() 172 */ 173 @Override 174 public void scan(String... basePackages) { 175 Assert.notEmpty(basePackages, "At least one base package must be specified"); 176 this.scanner.scan(basePackages); 177 } 178 179 180 //--------------------------------------------------------------------- 181 // Adapt superclass registerBean calls to AnnotatedBeanDefinitionReader 182 //--------------------------------------------------------------------- 183 184 @Override 185 public <T> void registerBean(@Nullable String beanName, Class<T> beanClass, 186 @Nullable Supplier<T> supplier, BeanDefinitionCustomizer... customizers) { 187 188 this.reader.registerBean(beanClass, beanName, supplier, customizers); 189 } 190 191}