Back to Javatutorial

@SpringBootApplication注解

docs/Spring全家桶/SpringBoot源码解析/@SpringBootApplication注解.md

1.0.011.3 KB
Original Source

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;

}

  1. @SpringBootApplication һע⣬ @SpringBootConfiguration``@EnableAutoConfiguration``@ComponentScan עĹܣ
  2. @SpringBootApplication ҲṩһЩԣЩע⡣

ע÷ֱʲô

1. @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 ע.

2. @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 {};

}

ӴпԿ

  1. ע @AutoConfigurationPackage עĹܣעָԶװİ
  2. עͨ @Import עһ AutoConfigurationImportSelectorԶװĹؼ
  3. עṩãųָԶװ࣬Ըų (Class )ҲԸ (.) ų

ע @AutoConfigurationPackage AutoConfigurationImportSelector

2.1 @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;
        }

        // ʡһЩ
        ...
    }

}

е㳤߼ӣ£

  1. AutoConfigurationPackages.Registrar ʵ ImportBeanDefinitionRegistrar``registerBeanDefinitions(...) spring ע BasePackagesע߼ AutoConfigurationPackages#register У
  2. AutoConfigurationPackages#register ע߼ΪжǷע BasePackagesעˣͽǰڵİӵ BasePackages Ĺ췽ֵУʹ BeanDefinitionù췽IJֵȻעᵽ spring У

2.2 AutoConfigurationImportSelector

AutoConfigurationImportSelector ǴԶõĹؼ£

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,

    ...

}

AutoConfigurationImportSelector ʵ DeferredImportSelectorһ ImportSelector ࣬ȼ ( @ComponentScan``@Component``@Bean``@Configuration @Import ע⴦֮ٴ) AutoConfigurationImportSelector лᴦԶļַ̣ͨʽԶ spring С

spring @Import ĴԲο ConfigurationClassPostProcessor ֮ @Import ע.

AutoConfigurationImportSelector ȡԶ̣ںоľͲչˡ

3. @ComponentScan

עشѾϤˣָ˰ɨ·ָɨİЩ ConfigurationClassPostProcessor ֮ @ComponentScan עһѾϸˣͲٷˡ

עʹõ 2 ࣺ

3.1 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(...) жƥ߼

3.1 AutoConfigurationExcludeFilter

AutoConfigurationExcludeFilter ųԶ࣬Ҳ˵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(...) ƥΪ

  1. @Configuration ǣ
  2. Զࡣ

spring Ͳɨ账

ʲôԶأ isAutoConfiguration(...) ԿжǷΪԶϣspringboot ʹ SpringFactoriesLoader ࣬ȻжϴǷΪ֮һԿԶಢаɨ

SpringFactoriesLoader μ࣬»ϸ

4. ܽ

Ҫ @SpringBootApplication Ĺܣܽ£

  1. @SpringBootApplication һע⣬ @SpringBootConfiguration``@EnableAutoConfiguration``@ComponentScan עĹܣͬʱṩһЩãҲ 3 ע⣻
  2. @SpringBootConfiguration Configuration עĹܣ
  3. @EnableAutoConfiguration ǿԶװĹؼע⣬б @AutoConfigurationPackage@SpringBootApplication ǵڵİװ BasePackagesȻעᵽ spring У@EnableAutoConfiguration ͨ @Import ע AutoConfigurationImportSelectorὫǰĿֵ֧Զӵ spring У
  4. @ComponentScan ˰ɨ· excludeFilters ֵųɨ裬springboot ָ TypeExcludeFilterǿԼ̳иų ͬʱҲָ AutoConfigurationExcludeFilter Filter ųԶ࣬Ҳ˵Զ಻а

ԭӣhttps://my.oschina.net/funcy/blog/4870882 ߸ˮƽд֮ӭָԭףҵתϵ߻Ȩҵתע