docs/Spring全家桶/SpringBoot源码解析/@SpringBootApplication注解.md
springboot ϻעһע⣺@SpringBootApplication˽Դ עá
@SpringBootApplication £
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
/**
* ԶװҪų࣬ @EnableAutoConfiguration
*/
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};
/**
* ԶװҪų @EnableAutoConfiguration
*/
@AliasFor(annotation = EnableAutoConfiguration.class)
String[] excludeName() default {};
/**
* ɨİ @ComponentScan
*/
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
/**
* ɨclassclassڵİᱻɨ裬 @ComponentScan
*/
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
/**
* Ƿ @Bean @Configuration
*/
@AliasFor(annotation = Configuration.class)
boolean proxyBeanMethods() default true;
}
@SpringBootApplication һע⣬ @SpringBootConfiguration``@EnableAutoConfiguration``@ComponentScan עĹܣ@SpringBootApplication ҲṩһЩԣЩע⡣ע÷ֱʲô
@SpringBootConfiguration@SpringBootConfiguration£
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
@AliasFor(annotation = Configuration.class)
boolean proxyBeanMethods() default true;
}
עȽϼ @ConfigurationȻһ proxyBeanMethods() @Configurationˣ@SpringBootConfiguration ûʲôֻǽ @Configuration ʹ @Configuration Ĺܡ
@Configuration springܱ spring ʶΪ Component proxyBeanMethods != false ʱᱻ spring Ϊ Full ࣬ںе @Bean ʱ cglib ⷽݣɲο ConfigurationClassPostProcessor @Bean ע.
@EnableAutoConfiguration@EnableAutoConfiguration Ҫ Զװ书ܣ£
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
// Զװİ
@AutoConfigurationPackage
// Զװ
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
/**
* жųԶװ
*/
Class<?>[] exclude() default {};
/**
* жųԶװ
*/
String[] excludeName() default {};
}
ӴпԿ
@AutoConfigurationPackage עĹܣעָԶװİ@Import עһ AutoConfigurationImportSelectorԶװĹؼClass )ҲԸ (.) ųע @AutoConfigurationPackage AutoConfigurationImportSelector
@AutoConfigurationPackage@AutoConfigurationPackage ָԶװİ£
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
}
עݷdzʹ @Import ע AutoConfigurationPackages.Registrarݣ
public abstract class AutoConfigurationPackages {
private static final String BEAN = AutoConfigurationPackages.class.getName();
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
/**
* ImportBeanDefinitionRegistrar Ĵspring registerBeanDefinitions() ע
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
register(registry, new PackageImport(metadata).getPackageName());
}
@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImport(metadata));
}
}
/**
* ע
* 1\. beanFacotry а BEANİӵ BEAN Ӧ BeanDefinition Ĺ췽ֵϣ
* 2\. beanFacotry в BEAN beanDefinitionòֵȻעᵽ beanFacotry
* עᵽbeanFacotryеbeanΪBasePackages
*/
public static void register(BeanDefinitionRegistry registry, String... packageNames) {
if (registry.containsBeanDefinition(BEAN)) {
BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);
// bean BasePackages췽 BasePackages(String... names)ȡԭĹֵ
ConstructorArgumentValues constructorArguments
= beanDefinition.getConstructorArgumentValues();
// ԭĹֵԼ packageNames ͳһӵ췽ĵ0ֵ
constructorArguments.addIndexedArgumentValue(0,
addBasePackages(constructorArguments, packageNames));
}
else {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
// BeanClassΪBasePackages.class
beanDefinition.setBeanClass(BasePackages.class);
// ù췽IJֵ
beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, packageNames);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(BEAN, beanDefinition);
}
}
/**
* packageName İװ
* packageName ǴڵİPackageImportĹ췽лȡ
*/
private static final class PackageImport {
private final String packageName;
PackageImport(AnnotationMetadata metadata) {
// ȡڰ
this.packageName = ClassUtils.getPackageName(metadata.getClassName());
}
String getPackageName() {
return this.packageName;
}
// ʡ equals/toString/hashCode
...
}
/**
* ע beanFactory е
* һListṹɨ·
*/
static final class BasePackages {
// ɨ·ﱣ
private final List<String> packages;
private boolean loggedBasePackageInfo;
BasePackages(String... names) {
List<String> packages = new ArrayList<>();
for (String name : names) {
if (StringUtils.hasText(name)) {
packages.add(name);
}
}
this.packages = packages;
}
// ʡһЩ
...
}
}
е㳤ӣ£
AutoConfigurationPackages.Registrar ʵ ImportBeanDefinitionRegistrar``registerBeanDefinitions(...) spring ע BasePackagesע AutoConfigurationPackages#register УAutoConfigurationPackages#register עΪжǷע BasePackagesעˣͽǰڵİӵ BasePackages Ĺ췽ֵУʹ BeanDefinitionù췽IJֵȻעᵽ spring УAutoConfigurationImportSelectorAutoConfigurationImportSelector ǴԶõĹؼ£
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
...
}
AutoConfigurationImportSelector ʵ DeferredImportSelectorһ ImportSelector ࣬ȼ ( @ComponentScan``@Component``@Bean``@Configuration @Import ע֮ٴ) AutoConfigurationImportSelector лᴦԶļַ̣ͨʽԶ spring С
spring @Import ĴԲο ConfigurationClassPostProcessor ֮ @Import ע.
AutoConfigurationImportSelector ȡԶ̣ںоľͲչˡ
@ComponentScanעشѾϤˣָ˰ɨ·ָɨİЩ ConfigurationClassPostProcessor ֮ @ComponentScan עһѾϸˣͲٷˡ
עʹõ 2 ࣺ
TypeExcludeFilterʾڽаɨʱųһЩ࣬£
public class TypeExcludeFilter implements TypeFilter, BeanFactoryAware {
private BeanFactory beanFactory;
private Collection<TypeExcludeFilter> delegates;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Override
public boolean match(MetadataReader metadataReader,
MetadataReaderFactory metadataReaderFactory) throws IOException {
if (this.beanFactory instanceof ListableBeanFactory
&& getClass() == TypeExcludeFilter.class) {
// getDelegates() ȡǰе TypeExcludeFilter ʵ
// ̳ TypeExcludeFilterԶƥ
for (TypeExcludeFilter delegate : getDelegates()) {
if (delegate.match(metadataReader, metadataReaderFactory)) {
return true;
}
}
}
return false;
}
private Collection<TypeExcludeFilter> getDelegates() {
Collection<TypeExcludeFilter> delegates = this.delegates;
if (delegates == null) {
delegates = ((ListableBeanFactory) this.beanFactory)
.getBeansOfType(TypeExcludeFilter.class).values();
this.delegates = delegates;
}
return delegates;
}
....
ӴҪųһЩ ࣬ǿ̳ TypeExcludeFilter ࣬Ȼд match(...) жƥ
AutoConfigurationExcludeFilterAutoConfigurationExcludeFilter ųԶ࣬Ҳ˵spring ڽаɨʱɨԶ࣬£
public class AutoConfigurationExcludeFilter implements TypeFilter, BeanClassLoaderAware {
private ClassLoader beanClassLoader;
private volatile List<String> autoConfigurations;
@Override
public void setBeanClassLoader(ClassLoader beanClassLoader) {
this.beanClassLoader = beanClassLoader;
}
@Override
public boolean match(MetadataReader metadataReader,
MetadataReaderFactory metadataReaderFactory) throws IOException {
// isConfiguration(...)ǰǷ @Configuration
// isAutoConfiguration(...)ǰǷΪԶ
return isConfiguration(metadataReader) && isAutoConfiguration(metadataReader);
}
private boolean isConfiguration(MetadataReader metadataReader) {
return metadataReader.getAnnotationMetadata().isAnnotated(Configuration.class.getName());
}
private boolean isAutoConfiguration(MetadataReader metadataReader) {
// ȡеԶ࣬ȻжϵǰǷ
return getAutoConfigurations().contains(metadataReader.getClassMetadata().getClassName());
}
protected List<String> getAutoConfigurations() {
if (this.autoConfigurations == null) {
this.autoConfigurations = SpringFactoriesLoader
.loadFactoryNames(EnableAutoConfiguration.class, this.beanClassLoader);
}
return this.autoConfigurations;
}
}
Ҫ match(...) ƥΪ
@Configuration ǣspring Ͳɨ账
ʲôԶأ isAutoConfiguration(...) ԿжǷΪԶϣspringboot ʹ SpringFactoriesLoader ࣬ȻжϴǷΪ֮һԿԶಢаɨ
SpringFactoriesLoader μ࣬»ϸ
Ҫ @SpringBootApplication Ĺܣܽ£
@SpringBootApplication һע⣬ @SpringBootConfiguration``@EnableAutoConfiguration``@ComponentScan עĹܣͬʱṩһЩãҲ 3 ע⣻@SpringBootConfiguration Configuration עĹܣ@EnableAutoConfiguration ǿԶװĹؼע⣬б @AutoConfigurationPackageὫ @SpringBootApplication ǵڵİװ BasePackagesȻעᵽ spring У@EnableAutoConfiguration ͨ @Import ע AutoConfigurationImportSelectorὫǰĿֵ֧Զӵ spring У@ComponentScan ˰ɨ· excludeFilters ֵųɨ裬springboot ָ TypeExcludeFilterǿԼ̳иų ͬʱҲָ AutoConfigurationExcludeFilter Filter ųԶ࣬Ҳ˵Զаԭӣhttps://my.oschina.net/funcy/blog/4870882 ߸ˮƽд֮ӭָԭףҵתϵȨҵתע