• java学习day41-Spring Boot入门(二)--@SpringBootApplication注解分析


    spring boot 入门(二)

    默认的主启动类分析

    //@SpringBootApplication 来标注一个主程序类
    //说明这是一个Spring Boot应用
    @SpringBootApplication
    public class SpringbootApplication {
    
       public static void main(String[] args) {
         //以为是启动了一个方法,没想到启动了一个服务
          SpringApplication.run(SpringbootApplication.class, args);
       }
    
    }
    

    下面分析该注解都干了什么?

    @SpringBootApplication

    作用:

    标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot就应该运行这个类的主要方法来启动SpringBoot应用;

    进入这个注解:可以看到上面还有很多其他注解!其中有三个最重要的注解,

    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan

    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan(
        excludeFilters = {@Filter(
        type = FilterType.CUSTOM,
        classes = {TypeExcludeFilter.class}
    ), @Filter(
        type = FilterType.CUSTOM,
        classes = {AutoConfigurationExcludeFilter.class}
    )}
    )
    public @interface SpringBootApplication {
        // ......
    }
    

    @ComponentScan

    这个注解在Spring中很重要,它对应XML配置中的元素。

    作用:自动扫描并加载符合条件的组件或者bean,将这个bean定义加载到IOC容器中

    @SpringBootConfiguration

    作用:SpringBoot的配置类,标注在某个类上,表示这是一个SpringBoot的配置类;

    我们继续进去这个注解查看

    // 点进去得到下面的 @Component
    @Configuration
    public @interface SpringBootConfiguration {}
    
    @Component
    public @interface Configuration {}
    

    这里的@Configuration,说明这是一个配置类,配置类就是对应Spring的xml配置文件;

    里面的@Component这就说明,启动类本身也是Spring中的一个组件而已,负责启动应用!

    我们回到SpringBootApplication注解中继续看。

    @EnableAutoConfiguration

    @AutoConfigurationPackage
    @Import(AutoConfigurationImportSelector.class)
    public @interface EnableAutoConfiguration {
    

    @EnableAutoConfiguration:开启自动配置功能

    以前我们需要自己配置的东西,而现在SpringBoot可以自动帮我们配置; @EnableAutoConfiguration告诉SpringBoot启动自动配置功能,这样自动配置才能实现;

    点进注解接续查看:

    @AutoConfigurationPackage:自动配置包

    @Import({Registrar.class})
    public @interface AutoConfigurationPackage {
    }
    

    @import:Spring剧烈注解@import,给容器中引入一个组件

    Registrar.class作用:将主启动类的所在包及包下面所有子包里面的所有组件扫描到Spring容器;

    这个分析完了,然后退回上一步.我们再看

    @Import({AutoConfigurationImportSelector.class}):给容器导入组件;

    AutoConfigurationImportSelector:自动配置导入选择器,那么它会引入该组件的选择器呢?

    1,这个类中有一个这样的方法

    // 获得候选的配置
    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        //这里的getSpringFactoriesLoaderFactoryClass()方法
        //返回的就是我们最开始看的启动自动导入配置文件的注解类;EnableAutoConfiguration
    		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;
    	}
    

    2,这个方法又调用了SpringFactoriesLoader类的静态方法!我们进入SpringFactoriesLoader类loadFactoryNames()方法

    public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
        String factoryClassName = factoryClass.getName();
        //这里它又调用了 loadSpringFactories 方法
        return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
    }
    

    3,我们继续点击查看loadSpringFactories方法

    private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
        //获得classLoader , 我们返回可以看到这里得到的就是EnableAutoConfiguration标注的类本身
        MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
        if (result != null) {
            return result;
        } else {
            try {
                //public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
                //去获取一个资源 "META-INF/spring.factories"
                Enumeration<URL> urls = classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION);
                LinkedMultiValueMap result = new LinkedMultiValueMap();
    
                //将读取到的资源遍历,封装成为一个Properties
                while(urls.hasMoreElements()) {
                    URL url = (URL)urls.nextElement();
                    UrlResource resource = new UrlResource(url);
                    Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                    Iterator var6 = properties.entrySet().iterator();
    
                    while(var6.hasNext()) {
                        Entry<?, ?> entry = (Entry)var6.next();
                        String factoryClassName = ((String)entry.getKey()).trim();
                        String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                        int var10 = var9.length;
    
                        for(int var11 = 0; var11 < var10; ++var11) {
                            String factoryName = var9[var11];
                            result.add(factoryClassName, factoryName.trim());
                        }
                    }
                }
    
                cache.put(classLoader, result);
                return result;
            } catch (IOException var13) {
                throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
            }
        }
    }
    

    4,发现一个多次出现的文件: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,
    org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,
    org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,
    org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,
    org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,
    org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,
    .......
    

    上边自动配置的类可以随便点进去,发现这些一个个的都是JavaConfig配置类,而且都都注入了一些Bean

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnClass({ RabbitTemplate.class, Channel.class })
    @EnableConfigurationProperties(RabbitProperties.class)
    @Import(RabbitAnnotationDrivenConfiguration.class)
    public class RabbitAutoConfiguration {
    
    	@Configuration(proxyBeanMethods = false)
    	@ConditionalOnMissingBean(ConnectionFactory.class)
    	protected static class RabbitConnectionFactoryCreator {
    
    		@Bean
    		public CachingConnectionFactory rabbitConnectionFactory(RabbitProperties properties,
    				ObjectProvider<ConnectionNameStrategy> connectionNameStrategy) throws Exception {
    			PropertyMapper map = PropertyMapper.get();
                ......
    

    所以,自动配置真正实现是从classpath中搜寻所有的META-INF / spring.factories配置文件,其中相互对应的org.springframework.boot.autoconfigure。包下的配置项,通过反射实例化为对应标注了@Configuration的JavaConfig形式的IOC容器配置类,然后将这些都汇总成为一个实例并加载到IOC容器中。

    总结:

    1 SpringBoot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值
    2 将这些值作为自动配置类引入容器,自动配置类就生效,帮我们进行自动配置工作;
    3 整个J2EE的整体解决方案和自动配置都在springboot-autoconfigure的jar包中;
    4 它会给容器中引入非常多的自动配置类(xxxAutoConfiguration),就是给容器中引入这个场景需要的所有组件,并配置好这些组件;
    5 有了自动配置类,无需去我们手动编写配置注入功能组件等的工作;
    
  • 相关阅读:
    区块链分布式云存储项目盘点
    区块链一定要知道的的七大认识误区
    以太坊“空块”数量激增有什么影响?
    区块链技术涉及哪些编程语言?
    一文读懂实用拜占庭容错(PBFT)算法
    清除浮动的影响
    滚动条
    分享侧栏例子
    最最最简单的轮播图(JQuery)
    3D动画
  • 原文地址:https://www.cnblogs.com/liqbk/p/13221468.html
Copyright © 2020-2023  润新知