spring boot 学习二

spring boot

spring boot自动配置实现原理


1、SpringBoot自动配置-自动加载bean对象到ioc容器

   Condition是Spring4.0后引入的条件化配置接口,通过实现Condition接口可以完成有条件的加载相应的Bean

  Conditon是条件的意思,属于spring的一个接口,抽象方法为matches,返回值为boolean,两个参数分别为

     ConditionContext:上下文对象,可以获取属性值,获取类加载器,获取BeanFactory等

    AnnotatedTypeMetadata:元数据对象,用于获取注解属性  

  Conditon接口

1 @FunctionalInterface
2 public interface Condition {
3     boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
4 }

   Conditional注解

1 @Target({ElementType.TYPE, ElementType.METHOD})
2 @Retention(RetentionPolicy.RUNTIME)
3 @Documented
4 public @interface Conditional {
5     Class<? extends Condition>[] value();
6 }

  ConditionalOnClass注解

1 @Target({ElementType.TYPE, ElementType.METHOD})
2 @Retention(RetentionPolicy.RUNTIME)
3 @Documented
4 @Conditional({OnClassCondition.class})
5 public @interface ConditionalOnClass {
6     Class<?>[] value() default {};
7 
8     String[] name() default {};
9 }

通过在配置类上加ConditionalOnClass(“com.alibaba.fastjson.JSON”)就能实现满足导入Json包才能获取类这样的操作,即自动加载bean对象

springboot 提供的常用条件注解

  • ConditionalOnProperty:判断配置文件中是否有对应属性和值才初始化Bean
  • ConditionalOnClass:判断环境中是否有对应字节码文件才初始化Bean
  • ConditionalOnMissingBean:判断环境中没有对应Bean才初始化Bean

2、SpringBoot自动配置-切换内置web服务器tt

  SpringBoot内置了很多的web容器,有tomcat、jetty、Undertow、netty(nio)等,SpringBoot默认使用的是tomcat服务器,所以在使用其他的web服务器时,需要将默认的给关闭掉,方法是修改pom文件,方式如下

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!--排除tomcat依赖-->
            <exclusions>
                <exclusion>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <!--引入jetty的依赖-->
        <dependency>
            <artifactId>spring-boot-starter-jetty</artifactId>
            <groupId>org.springframework.boot</groupId>
        </dependency>

3、SpringBoot自动配置-Enable注解原理

  SpringBoot不能直接获取在其他工程中定义的Bean(我们定义的bean),spring管理的那些bean是可以的,那如何加载外部工程的bean呢?有以下3中方式

 1 /**
 2  * @ComponentScan 扫描范围:当前引导类所在包及其子包
 3  *
 4  * com.itheima.springbootenable
 5  * com.itheima.config
 6  * //1.使用@ComponentScan扫描com.itheima.config包
 7  * //2.可以使用@Import注解,加载类。这些类都会被Spring创建,并放入IOC容器
 8  * //3.可以对Import注解进行封装。
 9  */
10 
11 //@ComponentScan("com.itheima.config")
12 //@Import(UserConfig.class)
13 @EnableUser
14 @SpringBootApplication//组合注解,其中有个Configration注解为配置类
15 public class SpringbootEnableApplication {
16 
17     public static void main(String[] args) {
18         ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
19 
20      //获取Bean
21         Object user = context.getBean("user");
22         System.out.println(user);
23 
24     }
25 
26 }
  1. 使用@ComponentScan扫描外部类的配置类的包路径
  2. 使用@Import注解,加载类。这些类都会被Spring创建,并放入IOC容器
  3. Import注解进行封装,在外部工程中封装一个注解,在本工程引导类上加上该注解就可以进行使用该bean
    • 1 封装的Import注解
      2 @Target(ElementType.TYPE)
      3 @Retention(RetentionPolicy.RUNTIME)
      4 @Documented
      5 @Import(UserConfig.class)
      6 public @interface EnableUser {}
@Enable*这个注解的底层还是@import注解,所以使用@Import导入的类会被Spring加载到IOC容器中。
而@Import提供4中用法:
  1. 导入Bean 直接@Import(“user.class”)
  2. 导入配置类 直接导入其他工程中的配置类
  3. 导入 ImportSelector 实现类。一般用于加载配置文件中的类@Import(MyImportSelector.class)
    • 1 public class MyImportSelector implements ImportSelector {
      2       @Override
      3       public String[] selectImports(AnnotationMetadata importingClassMetadata) {
      4           return new String[]{"com.itheima.domain.User", "com.itheima.domain.Role"};
      5       }
      6   }

      其他工程定义一个类实现ImportSelector这个借口,重写selectImport方法,将需要的类作为返回值返回

  4. 导入 ImportBeanDefinitionRegistrar 实现类 @Import({MyImportBeanDefinitionRegistrar.class})
    • 1 public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
      2     @Override
      3     public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
      4         AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
      5         registry.registerBeanDefinition("user", beanDefinition);
      6     }
      7 }
那么springboot是如何加载管理的那些类呢?怎么样去判断那些类是需要被加载入ioc的呢?
  在定义引导类的时候,添加的@SpringBootApplication注解是一个组合注解包含了:
  • @SpringBootConfiguration 该注解表示此类是配置类
  • @EnableAutoConfiguration 该注解底层就是@import注解,而这个注解会加载AutoConfigurationImportSelector这个类,通过这个类去加载META-INF/spring.factories这个文件,文件在autoconfig下面,该配置文件中定义了大量的配置类,
    • 当 SpringBoot 应用启动时,会自动加载这些配置类,初始化Bean,但是有不是所有的类都会被注入ioc容器,这些被spring管理的类在他们的工程中进行了配置文件类,当只有在pom文件中导入了这个类的坐标,才会被注入ioc容器中


  

原文地址:https://www.cnblogs.com/luckysupermarket/p/13782665.html