添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
  • @SpringBootConfiguration:复合注解,由@Configuration组成,任何一个标注了@Configuration的Java类定义,都是一个JavaConfig配置类。

  • @EnableAutoConfiguration:与其他@Enable开头的注解(例如,@EnableScheduling、@EnableCaching、@EnableMBeanExport等)功能一样,借助@Import的支持,收集和注册特定场景相关的Bean定义。例如: @EnableScheduling是通过@Import将Spring调度框架相关的Bean定义都加载到Spring IoC容器。 @EnableMBeanExport是通过@Import将JMX相关的Bean定义加载到Spring IoC容器。 而@EnableAutoConfiguration则是借助@Import的帮助,将所有符合自动配置条件的Bean定义加载到Spring IoC容器

    重点解析:从classpath中搜寻所有META-INF/spring.factories配置文件,并将其中org.spring.framework.boot.autoconfigure.EnableAutoConfiguration对应的配置项通过反射(Java Reflection)机制实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。
    
  • @ComponentScan

  • package org.springframework.boot.autoconfigure;
    import ...;
    @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 {
        @AliasFor(
            annotation = EnableAutoConfiguration.class,
            attribute = "exclude"
        Class<?>[] exclude() default {};
        @AliasFor(
            annotation = EnableAutoConfiguration.class,
            attribute = "excludeName"
        String[] excludeName() default {};
        @AliasFor(
            annotation = ComponentScan.class,
            attribute = "basePackages"
        String[] scanBasePackages() default {};
        @AliasFor(
            annotation = ComponentScan.class,
            attribute = "basePackageClasses"
        Class<?>[] scanBasePackageClasses() default {};
    

    探究@EnableAutoConfiguration注解

    @EnableAutoConfiguration注解追本溯源 @EnableAutoConfiguration -> EnableAutoConfigurationImportSelector(@Import注解) -> AutoConfigurationImportSelector(父类加载配置类时,指定getSpringFactoriesLoaderFactoryClass为EnableAutoConfiguration.class-也即@EnableAutoConfiguration ,并调用SpringFactoriesLoader.loadFactoryNames方法加载配置文件) –> SpringFactoriesLoader(加载”META-INF/spring.factories”中属性Key为EnableAutoConfiguration.class完整类名的配置类定义) -> “META-INF/spring.factories”;

    1、查看复合注解定义

    package org.springframework.boot.autoconfigure;
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Inherited;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    import org.springframework.boot.autoconfigure.AutoConfigurationPackage;
    import org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelector;
    import org.springframework.context.annotation.Import;
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage
    @Import({EnableAutoConfigurationImportSelector.class})
    public @interface EnableAutoConfiguration {
        String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
        Class<?>[] exclude() default {};
        String[] excludeName() default {};
    

    2、重点关注下Import注解

    package org.springframework.boot.autoconfigure;
    import org.springframework.boot.autoconfigure.AutoConfigurationImportSelector;
    import org.springframework.core.type.AnnotationMetadata;
    /** @deprecated */
    @Deprecated
    public class EnableAutoConfigurationImportSelector extends AutoConfigurationImportSelector {
        public EnableAutoConfigurationImportSelector() {
        protected boolean isEnabled(AnnotationMetadata metadata) {
            return this.getClass().equals(EnableAutoConfigurationImportSelector.class)?((Boolean)this.getEnvironment().getProperty("spring.boot.enableautoconfiguration", Boolean.class, Boolean.valueOf(true))).booleanValue():true;
    

    3、向上延伸查看父类

    // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) package org.springframework.boot.autoconfigure; import java.io.***; public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered { private static final String[] NO_IMPORTS = new String[0]; private static final Log logger = LogFactory.getLog(AutoConfigurationImportSelector.class); private ConfigurableListableBeanFactory beanFactory; private Environment environment; private ClassLoader beanClassLoader; private ResourceLoader resourceLoader; public AutoConfigurationImportSelector() { public String[] selectImports(AnnotationMetadata annotationMetadata) { if(!this.isEnabled(annotationMetadata)) { return NO_IMPORTS; } else { try { AutoConfigurationMetadata ex = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader); AnnotationAttributes attributes = this.getAttributes(annotationMetadata); List configurations = this.getCandidateConfigurations(annotationMetadata, attributes); configurations = this.removeDuplicates(configurations); configurations = this.sort(configurations, ex); Set exclusions = this.getExclusions(annotationMetadata, attributes); this.checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = this.filter(configurations, ex); this.fireAutoConfigurationImportEvents(configurations, exclusions); return (String[])configurations.toArray(new String[configurations.size()]); } catch (IOException var6) { throw new IllegalStateException(var6); protected boolean isEnabled(AnnotationMetadata metadata) { return true; protected AnnotationAttributes getAttributes(AnnotationMetadata metadata) { String name = this.getAnnotationClass().getName(); AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(name, true)); Assert.notNull(attributes, "No auto-configuration attributes found. Is " + metadata.getClassName() + " annotated with " + ClassUtils.getShortName(name) + "?"); return attributes; protected Class<?> getAnnotationClass() { return EnableAutoConfiguration.class; protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct."); return configurations; protected Class<?> getSpringFactoriesLoaderFactoryClass() { return EnableAutoConfiguration.class;

    4、查看SpringFactoriesLoader

    // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) package org.springframework.core.io.support; import ...; public abstract class SpringFactoriesLoader { private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class); public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"; public SpringFactoriesLoader() { public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) { Assert.notNull(factoryClass, "\'factoryClass\' must not be null"); ClassLoader classLoaderToUse = classLoader; if(classLoader == null) { classLoaderToUse = SpringFactoriesLoader.class.getClassLoader(); List factoryNames = loadFactoryNames(factoryClass, classLoaderToUse); if(logger.isTraceEnabled()) { logger.trace("Loaded [" + factoryClass.getName() + "] names: " + factoryNames); ArrayList result = new ArrayList(factoryNames.size()); Iterator var5 = factoryNames.iterator(); while(var5.hasNext()) { String factoryName = (String)var5.next(); result.add(instantiateFactory(factoryName, factoryClass, classLoaderToUse)); AnnotationAwareOrderComparator.sort(result); return result; public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); try { Enumeration ex = classLoader != null?classLoader.getResources("META-INF/spring.factories"):ClassLoader.getSystemResources("META-INF/spring.factories"); ArrayList result = new ArrayList(); while(ex.hasMoreElements()) { URL url = (URL)ex.nextElement(); Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url)); String factoryClassNames = properties.getProperty(factoryClassName); result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames))); return result; } catch (IOException var8) { throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + "META-INF/spring.factories" + "]", var8); private static <T> T instantiateFactory(String instanceClassName, Class<T> factoryClass, ClassLoader classLoader) { try { Class ex = ClassUtils.forName(instanceClassName, classLoader); if(!factoryClass.isAssignableFrom(ex)) { throw new IllegalArgumentException("Class [" + instanceClassName + "] is not assignable to [" + factoryClass.getName() + "]"); } else { Constructor constructor = ex.getDeclaredConstructor(new Class[0]); ReflectionUtils.makeAccessible(constructor); return constructor.newInstance(new Object[0]); } catch (Throwable var5) { throw new IllegalArgumentException("Unable to instantiate factory class: " + factoryClass.getName(), var5);
  •