在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

SpringBootApplication是什么

科技綠洲 ? 來源:Java技術指北 ? 作者:Java技術指北 ? 2023-10-13 11:03 ? 次閱讀

概述

我們先來了解一下 @SpringBootApplication 是什么,以及如何在一個簡單的 Spring Boot 應用程序中使用它。我們先看看 Spring Team 在源碼中對它的定義是什么?

Indicates a configuration class that declares one or more @Bean methods and also triggers auto-configuration and component scanning. This is a convenience annotation that is equivalent to declaring @Configuration, @EnableAutoConfiguration and @ComponentScan.

表示一個配置類,它聲明了一個或多個@Bean方法,也觸發(fā)了自動配置和組件掃描。這是一個方便的注解,相當于聲明了@Configuration、@EnableAutoConfiguration和@ComponentScan。

從上面的定義我們可以看出,@SpringBootApplication 注解其實是一個組合注解。使用 @SpringBootApplication 相當于同時使用了 @Configuration@EnableAutoConfiguration@ComponentScan 。@SpringBootApplication 是在 Spring Boot 1.2.0 之后才開始有的,如何你的項目使用的 Spring Boot 1.2.0 之前的版本,那需要抱歉了,你不能使用這個注解,你只能完整的使用那 3 個注解來代替它。

那我們接下來看看,通過一個簡單的示例來看看怎么使用的。

@SpringBootApplication 示例

下面是一個簡單的例子,說明如何使用 @SpringBootApplication 注解來編寫 Spring Boot 應用程序。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Spring Boot 項目的啟動類非常的簡潔,沒有一行多余的代碼。@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 {
    @AliasFor(annotation = EnableAutoConfiguration.class)
    Class< ? >[] exclude() default {};
    
    @AliasFor(annotation = EnableAutoConfiguration.class)
    String[] excludeName() default {};
    @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
    String[] scanBasePackages() default {};
    @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
    Class< ? >[] scanBasePackageClasses() default {};
    @AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator")
    Class< ? extends BeanNameGenerator > nameGenerator() default BeanNameGenerator.class;
    @AliasFor(annotation = Configuration.class)
    boolean proxyBeanMethods() default true;
}

@SpringBootApplication 源碼可以看出 @SpringBootApplication = @SpringBootConfiguration + @ComponentScan+ @EnableAutoConfiguration

前面已經提過了,@SpringBootApplication 是3個注解的組合,下面分別介紹一下每個注解都有什么作用吧。

@SpringBootConfiguration

這個注解將一個類標記為基于 Java Config 的配置類。如果你喜歡基于 Java 的配置而不是基于 XML 的配置,這一點就特別重要。

@ComponentScan

該注解使組件掃描成為可能,這樣你創(chuàng)建的 Web 控制器類和其他組件將被自動發(fā)現(xiàn),并在 Spring 應用上下文中注冊為 Bean。你編寫的所有 @Controller 類將被該注解發(fā)現(xiàn)。

@EnableAutoConfiguration

這個注解可以啟用 Spring Boot 自動配置功能。

如果你仔細的話會發(fā)現(xiàn)和前面講的不一樣, @SpringBootConfiguration 是從那里冒出來的,不是應該是 @Configuration 嗎?下面就告訴你答案。

@SpringBootConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {
    @AliasFor(annotation = Configuration.class)
    boolean proxyBeanMethods() default true;
}

從源碼可以看出,@SpringBootConfiguration 繼承自 @Configuration,二者功能也一致,標注當前類是配置類,不過 @SpringBootConfiguration 是一個特殊的標記類,在項目中只能使用一次。

@ComponentScan

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
 @AliasFor("basePackages")
 String[] value() default {};
 @AliasFor("value")
 String[] basePackages() default {};
 Class< ? >[] basePackageClasses() default {};
 Class< ? extends BeanNameGenerator > nameGenerator() default BeanNameGenerator.class;
 Class< ? extends ScopeMetadataResolver > scopeResolver() default AnnotationScopeMetadataResolver.class;
 ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
    ...
}

@ComponentScan 不做過多的解釋了,使用過 Spring 的朋友都懂的。其他的朋友我就啰嗦一句吧, 可以通過該注解指定掃描某些包下包含如下注解的均自動注冊為 Spring beans@Component、@Service、 @Repository、 @Controller 等等注釋的類。Spring Boot 除了可以使用 @ComponentScan 注解來加載我們的bean,還可以使用 @Import 指定該類。

@EnableAutoConfiguration

@EnableAutoConfiguration 的作用啟動自動的配置,意思就是 Spring Boot 根據(jù)你添加的 jar 包來配置你項目的默認配置,比如根據(jù) spring-boot-starter-web ,來判斷你的項目是否需要添加了 web mvctomcat,就會自動的幫你配置 web 項目中所需要的默認配置。簡單點說就是它會根據(jù)定義在 classpath 下的類,自動的給你生成一些 Bean,并加載到 Spring 的上下文中。

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

從上述源碼中可以看到 @Import 引入了 AutoConfigurationImportSelector 類。AutoConfigurationImportSelector 使用了 Spring Core 包的 SpringFactoriesLoader#loadFactoryNames() 方法。AutoConfigurationImportSelector 類實現(xiàn)了 DeferredImportSelector 接口,并實現(xiàn)了 selectImports 方法,用來導出 Configuration 類。

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
        ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }
    protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        }
        AnnotationAttributes attributes = getAttributes(annotationMetadata);
        List< String > configurations = getCandidateConfigurations(annotationMetadata, attributes);
        ...
        return new AutoConfigurationEntry(configurations, exclusions);
    }
    protected boolean isEnabled(AnnotationMetadata metadata) {
        if (getClass() == AutoConfigurationImportSelector.class) {
            return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class, true);
        }
        return true;
    }
    protected List< String > getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List< String > configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
                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;
    }
}

導出的類是通過 SpringFactoriesLoader#loadFactoryNames() 讀取了 classpath 下面的 META-INF/spring.factories 文件。

public final class SpringFactoriesLoader {
    public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
    public static List< String > loadFactoryNames(Class< ? > factoryType, @Nullable ClassLoader classLoader) {
        ClassLoader classLoaderToUse = classLoader;
        if (classLoaderToUse == null) {
            classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
        }
        String factoryTypeName = factoryType.getName();
        return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
    }
    private static Map< String, List< String >> loadSpringFactories(ClassLoader classLoader) {
        Map< String, List< String >> result = cache.get(classLoader);
        if (result != null) {
            return result;
        }
        result = new HashMap<  >();
        try {
            Enumeration< URL > urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                UrlResource resource = new UrlResource(url);
                Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                for (Map.Entry< ?, ? > entry : properties.entrySet()) {
                    String factoryTypeName = ((String) entry.getKey()).trim();
                    String[] factoryImplementationNames =
                            StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
                    for (String factoryImplementationName : factoryImplementationNames) {
                        result.computeIfAbsent(factoryTypeName, key - > new ArrayList<  >())
                                .add(factoryImplementationName.trim());
                    }
                }
            }
            // Replace all lists with unmodifiable lists containing unique elements
            result.replaceAll((factoryType, implementations) - > implementations.stream().distinct()
                    .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)));
            cache.put(classLoader, result);
        }
        catch (IOException ex) {
            throw new IllegalArgumentException("Unable to load factories from location [" +
                    FACTORIES_RESOURCE_LOCATION + "]", ex);
        }
        return result;
    }
}

META-INF/spring.factories 文件中一部分自動配置的內容:

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,

如果你發(fā)現(xiàn)自動裝配的 Bean 不是你想要的,你也可以 disable 它。比如說,我不想要自動裝配 Database 的那些Bean:

@EnableAutoConfiguration(exclude  = {DataSourceAutoConfiguration.class})

這也是一種為 Spring Boot 項目瘦身的方法。你可以看到網(wǎng)上一些為項目瘦身的方法都是通過這個注解來操作的。

@AutoConfigurationPackage

@EnableAutoConfiguration 又繼承了 @AutoConfigurationPackage ,@AutoConfigurationPackage 會引導類(@SpringBootApplication 標注的類)所在的包及下面所有子包里面的所有組件掃描到Spring容器。具體怎么實現(xiàn)的呢,我們來看代碼,原來它 import 了 AutoConfigurationPackages.Registrar.class, 我們來看看它做了什么?

@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
    String[] basePackages() default {};
    Class< ? >[] basePackageClasses() default {};
}
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
    }
    @Override
    public Set< Object > determineImports(AnnotationMetadata metadata) {
        return Collections.singleton(new PackageImports(metadata));
    }
}

看代碼就很容易理解,把注解掃描進來的 package 全部給注冊到 spring bean中。這樣 Spring Boot 的自動配置也就完成了。

總結

經過這樣的一番折騰,相信大家已經對 @SpringBootApplication 注解,有了一定的了解。也知道了 @SpringBootApplication 怎么實現(xiàn) Spring Boot 的自動配置功能。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 源碼
    +關注

    關注

    8

    文章

    652

    瀏覽量

    29454
  • 應用程序
    +關注

    關注

    38

    文章

    3292

    瀏覽量

    57914
  • 組件
    +關注

    關注

    1

    文章

    517

    瀏覽量

    17923
  • SpringBoot
    +關注

    關注

    0

    文章

    174

    瀏覽量

    201
收藏 人收藏

    評論

    相關推薦

    Spring Boot如何實現(xiàn)異步任務

    @EnableAsync 注解啟用異步功能; 需要在異步方法上添加 @Async 注解。 示例代碼如下: @SpringBootApplication @EnableAsync public class Applicat
    的頭像 發(fā)表于 09-30 10:32 ?1475次閱讀

    結合場景談一談微服務配置

    @SpringBootApplication@NacosPropertySource(dataId = "mysql.properties")public class SpringBootMySQLApplication {public
    發(fā)表于 12-12 15:53

    結合實際場景談一談微服務配置

    的目的。添加 @NacosPropertySource 注解@SpringBootApplication@NacosPropertySource(dataId?=?"mysql.properties
    發(fā)表于 12-12 15:56 ?148次閱讀

    Spring Boot的注解原理是什么

    @SpringBootApplication來看,發(fā)現(xiàn)@SpringBootApplication是一個組合注解。 @Target(ElementType.TYPE) @Retention
    的頭像 發(fā)表于 08-27 09:24 ?2237次閱讀

    Java注解及其底層原理解析 1

    什么是注解? 當我們開發(fā)SpringBoot項目,我們只需對啟動類加上`@SpringBootApplication`,就能自動裝配,不需要編寫冗余的xml配置。當我們?yōu)轫椖刻砑觢ombok
    的頭像 發(fā)表于 02-09 14:18 ?799次閱讀
    Java注解及其底層原理解析 1

    Java注解及其底層原理解析2

    什么是注解? 當我們開發(fā)SpringBoot項目,我們只需對啟動類加上`@SpringBootApplication`,就能自動裝配,不需要編寫冗余的xml配置。當我們?yōu)轫椖刻砑觢ombok
    的頭像 發(fā)表于 02-09 14:18 ?540次閱讀
    Java注解及其底層原理解析2

    SpringBoot的核心注解1

    今天跟大家來探討下SpringBoot的核心注解@SpringBootApplication以及run方法,理解下springBoot為什么不需要XML,達到零配置
    的頭像 發(fā)表于 04-07 14:34 ?739次閱讀
    SpringBoot的核心注解1

    SpringBoot的核心注解2

    今天跟大家來探討下SpringBoot的核心注解@SpringBootApplication以及run方法,理解下springBoot為什么不需要XML,達到零配置
    的頭像 發(fā)表于 04-07 14:34 ?1994次閱讀
    SpringBoot的核心注解2

    Spring Boot啟動 Eureka流程

    流程 @SpringBootApplication @EnableEurekaServer public class EurekaServer { public static void main
    的頭像 發(fā)表于 10-10 11:40 ?930次閱讀
    Spring Boot啟動 Eureka流程

    springboot核心注解

    幫助開發(fā)者簡化開發(fā)過程,提高開發(fā)效率。本文將深入介紹 Spring Boot 的核心注解及其使用方法。 @SpringBootApplication @SpringBootApplication
    的頭像 發(fā)表于 11-23 09:23 ?559次閱讀

    SpringBoot核心注解由幾個注解組成

    簡化應用程序開發(fā)的注解,其中核心注解包括 @SpringBootApplication、@RestController、@RequestMapping、@Autowired、@ComponentScan
    的頭像 發(fā)表于 12-03 15:09 ?805次閱讀
    主站蜘蛛池模板: 天天躁日日躁狠狠躁中文字幕老牛 | 欧美深夜福利 | 精品一精品国产一级毛片 | 欧美特黄一区二区三区 | 123456成年免费视频 | 男人日女人的网站 | 日韩欧美中文字幕在线播放 | 高清一级做a爱免费视 | 好吊色37pao在线观看 | 男人午夜影院 | 午夜一级黄色片 | 一级毛片美国一级j毛片不卡 | 欧美一级特黄啪啪片免费看 | 午夜精品在线视频 | 久久精品国产亚洲综合色 | 国模一区二区三区私啪啪 | 在线精品国产第一页 | 99综合色 | 91成人免费视频 | 国产 日韩 欧美 高清 | 天天摸天天操天天爽 | 在线色网 | 亚洲伊人久久大香线蕉啊 | 男人的天堂视频网站清风阁 | 狠狠狠狠狠狠狠狠 | 老司机成人精品视频lsj | 久久99久久精品免费思思6 | 夜夜爱夜夜操 | 欧美一级高清片欧美国产欧美 | 免费看a| 国产一级做a爱免费观看 | 国产三级高清 | 亚洲bt欧美bt高清bt777 | 国产看片视频 | 亚洲一区二区福利视频 | 完整日本特级毛片 | 一级特黄高清完整大片 | 天天操天天干天天透 | 色内内免费视频播放 | 黄a毛片 | 天天躁日日躁狠狠躁一级毛片 |