SpringBoot自动配置原理

SpringBoot自动配置原理:
    1. Condition接口:
        Condition接口是spring4.0之后提供的接口,增加条件判断功能,用于选择性的创建Bean对象到spring容器中。
    在Condition接口有一个方法:matches(),该方法用于判断,当加入了相关坐标依赖后,返回值为true,没有加入依赖,
    则返回值为false。
    
    2.相关注解说明:
        @Configuration:标记该类是一个配置类
        @Bean:用在方法上,将方法的返回值(一般是Bean)注册给spring容器管理
        @Conditional(OnCondition.class):用在方法上,用于判断,如果类OnCondition中的方法matches()返回值为true,
        则执行下面的代码,否则不执行
        @Import:
            import注解用于导入其他的配置,让spring容器进行加载和初始化。import的注解有以下的几种方式使用:
            1. @Import(User.class):
                直接导入Bean,注意使用该注解,类User要使用注解@Component注册给spring容器;
            2. @Import(UserConfig.class):
            3. @Import(MyImportSelector.class):导入ImportSelector接口的实现类,实现类中重写方法selectImports(),
                该方法返回要注册到spring容器中的Bean的全路径,即:
                    return new String[]{"com.itheima.pojo.Role", "com.itheima.pojo.User"};
            4. @Import(MyImportBeanDefinitionRegistrar.class):导入ImportBeanDefinitionRegistrar实现类,重写
            registerBeanDefinitions()方法:
                @Override
                public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
                    //创建BeanDefiniation
                    AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
                    //注册bean 目前只注册User
                    registry.registerBeanDefinition("user",beanDefinition);
                }
                        
        @SpringBootApplication:
            该注解由以下三个注解所组成:
            1. @SpringbootConfiguration:
                该注解等价于@Configuration,用于标记该类是一个配置类;
            2. @ComponentScan:
                该注解用于组件扫描(包扫描),类似于xml中的context-componet-scan,如果不指定扫描路径,
                那么就扫描该注解修饰的启动类所在的包以及子包。
            3. @EnableAutoConfiguration
                1.组合了@import注解,导入配置
                2.使用了@Import的第三种用法,导入ImportSelector接口的实现类,selectImports导入类中的方法中加载配置返回Bean定义的字符数组
                3.加载META-INF/spring.factories ,获取Bean定义的全路径名返回
                4.最终返回回去即可

                
    
    需求:
        当加入了jedis依赖后,自动创建User存入spring容器中;没有jedis依赖坐标,则不创建User;
        
    实现:
        1. 创建工程,导入坐标:
            <?xml version="1.0" encoding="UTF-8"?>
            <project xmlns="http://maven.apache.org/POM/4.0.0"
                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
                <modelVersion>4.0.0</modelVersion>

                <groupId>com.it</groupId>
                <artifactId>springboot-condition</artifactId>
                <version>1.0-SNAPSHOT</version>

                <parent>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-parent</artifactId>
                    <version>2.1.4.RELEASE</version>
                </parent>

                <dependencies>
                    <!--加入springboot的starter起步依赖-->
                    <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter</artifactId>
                    </dependency>

                    <dependency>
                        <groupId>redis.clients</groupId>
                        <artifactId>jedis</artifactId>
                        <version>3.2.0</version>
                    </dependency>

                </dependencies>


            </project>
        
        2. 创建pojo--User
            package com.it.pojo;

            /**
             * ToDo
             *
             * @author Lyle
             * @date 2020/4/1
             */
            public class User {
            
            }
        
        3. 创建启动类
            package com.it;

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

            /**
             * ToDo
             *
             * @author Lyle
             * @date 2020/4/1
             */
            @SpringBootApplication
            public class ConditionApplication {
                public static void main(String[] args) {
                    ConfigurableApplicationContext context = SpringApplication.run(ConditionApplication.class, args);
                    Object user = context.getBean("user");
                    System.out.println(user);
                }
            }
            
        4. 创建配置类,用于向spring容器中注册对象:
            package com.it.config;

            import com.it.condition.OnCondition;
            import com.it.pojo.User;
            import org.springframework.context.annotation.Bean;
            import org.springframework.context.annotation.Conditional;
            import org.springframework.context.annotation.Configuration;

            /**
             * ToDo
             *
             * @author Lyle
             * @date 2020/4/1
             */
            @Configuration//标记该类是一个配置类
            public class UserConfig {

                //注册Bean--User交给spring来管理
                //当导入了相关坐标依赖的时候
                @Bean
                @Conditional(OnCondition.class)//用于判断,如果OnCondition中的matches()返回值为true,则执行下面的代码,否则不执行
                public User user(){//注意方法名不能改

                    return new User();
                }
            }
            
        5. 创建类OnCondition,用于判断
            package com.it.condition;

            import org.springframework.context.annotation.Condition;
            import org.springframework.context.annotation.ConditionContext;
            import org.springframework.core.type.AnnotatedTypeMetadata;

            /**
             * ToDo
             *
             * @author Lyle
             * @date 2020/4/1
             */
            public class OnCondition implements Condition {
                //用于判断,符合条件,返回true,不符合条件,返回false
                @Override
                public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
                    //jedis坐标存在,返回true
                    try {
                        Class.forName("redis.clients.jedis.Jedis");//执行成功,说明类加载到了,类存在
                    } catch (ClassNotFoundException e) {//否则,说明类不存在
                        e.printStackTrace();
                        return false;
                    }
                    //jedis坐标不存在,返回false
                    return true;
                }
            }
            
    3. 切换内置的web容器Tomcat
        1. 排除Tomcat的起步依赖:
            <exclusions>
                <exclusion>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
            
        2. 加入其它web容器的依赖:例如:jetty,netty等
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jetty</artifactId>
            </dependency>
                    
                    
    


            


        
    
        
        
原文地址:https://www.cnblogs.com/lyle-liu/p/12618820.html