zoukankan      html  css  js  c++  java
  • SpringBoot(二)原理剖析:AutoConfiguration原理

      AutoConfiguration(自动配置),是指springBoot项目启动时,将bean自动加载到IOC容器,其核心源码在【spring-boot-autoconfigure-**.jar】中。

      自动配置的核心注解是@EnableAutoConfiguration,该注解又引用了两个注解@Import(AutoConfigurationImportSelector.class)和@AutoConfigurationPackage。前者是从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableutoConfiguration对应的配置类加载到容器中;后者则是扫描项目中指定Package下定义的Bean加入到容器中。@EnableAutoConfiguration分析可见: SpringBoot(一)原理剖析:SpringApplication启动原理 

    @Conditional注解分析

      @Conditional表示仅当所有指定条件都匹配时,组件才有资格注册 。该@Conditional注释可以在以下任一方式使用:

    • 作为任何@Bean方法的方法级注释
    • 作为任何类的直接或间接注释的类型级别注释 @Component,包括@Configuration类
    • 作为元注释,目的是组成自定义构造型注释

      @Conditional注解下有多个派生注解,如下图所示,其中@Conditional的参数OnBeanCondition.class是条件校验逻辑处理类:

      @Conditional派生注解描述如下:

    注解名称 说明
    @ConditionalOnProperty 判断application.properties 或 application.yml 文件中的属性是否符合要求
    @ConditionalOnBean 判断应用上下文是否有某个bean
    @ConditionalOnMissingBean 判断应用上下文是否没有某个bean
    @ConditionalOnClass 判断某个类是否存在 classpath 中
    @ConditionalOnExpression 判断某个类是否不在 classpath 中
    @ConditionalOnExpression 多个配置属性一起判断
    @ConditionalOnResource 判断是否存在指定的资源文件。
    @ConditionalOnJava 判断是否符合指定的Java版本要求。
    @ConditionalOnWebApplication 判断是web 应用环境才加载bean
    @ConditionalOnNotWebApplication 判断不是web 应用环境才加载bean

    自定义@Conditional

       1.添加自定义注解

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ ElementType.TYPE, ElementType.METHOD })
    @Documented
    @Conditional(CustomCondition.class)
    public @interface CustomConditionalAnnotation {
        
        String[] value() default {};
    }

      2.编写条件处理器

    public class CustomCondition implements Condition {
    
        @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            Map<String, Object> annotationMap = metadata.getAnnotationAttributes(CustomConditionalAnnotation.class.getName());
            String[] properties = (String[]) annotationMap.get("value");
            for (String property : properties) {
                if (StringUtils.isEmpty(context.getEnvironment().getProperty(property))) {
                    return false;
                }
            }
            return true;
        }
    
    }

    Full模式和Lite模式

      Full模式和Lite模式均是针对于Spring配置类而言的,和xml配置文件无关。

      Full模式

      标注有@Configuration或者@Configuration(proxyBeanMethods = true)的类被称为Full模式的配置类,proxyBeanMethods默认为TRUE。在常见的场景中,@Bean方法都会在标注有@Configuration的类中声明,以确保总是使用“Full模式”,这么一来,交叉方法引用会被重定向到容器的生命周期管理,所以就可以更方便的管理Bean依赖。

      优点:可以支持通过常规Java调用相同类的@Bean方法而保证是容器内的Bean,这有效规避了在“Lite模式”下操作时难以跟踪的细微错误。

      缺点:1.运行时会给该类生成一个CGLIB子类放进容器,有一定的性能、时间开销(这个开销在Spring Boot这种拥有大量配置类的情况下是不容忽视的,这也是为何Spring 5.2新增了proxyBeanMethods属性的最直接原因)

         2.正因为被代理了,所以@Bean方法 不可以是private、不可以是final

      Lite模式

      当@Bean方法在没有使用@Configuration注释的类中声明时,它们被称为在Lite模式下处理。它包括:在@Component中声明的@Bean方法,甚至只是在一个非常普通的类中声明的Bean方法,都被认为是Lite版的配置类。@Bean方法是一种通用的工厂方法(factory-method)机制。

      和Full模式的@Configuration不同,Lite模式的@Bean方法不能声明Bean之间的依赖关系。因此,这样的@Bean方法不应该调用其他@Bean方法。每个这样的方法实际上只是一个特定Bean引用的工厂方法(factory-method),没有任何特殊的运行时语义。

      以下配置属于Lite模式:

    • 类上标注有@Component注解
    • 类上标注有@ComponentScan注解
    • 类上标注有@Import注解
    • 类上标注有@ImportResource注解
    • 若类上没有任何注解,但类内存在@Bean方法
    • 注有@Configuration(proxyBeanMethods = false)

      自Spring5.2(对应Spring Boot 2.2.0)开始,内置的几乎所有的@Configuration配置类都被修改为了@Configuration(proxyBeanMethods = false),目的是以此来降低启动时间,为Cloud Native继续做准备。

      优点:1.运行时不再需要给对应类生成CGLIB子类,提高了运行性能,降低了启动时间
            2.可以该配置类当作一个普通类使用喽:也就是说@Bean方法 可以是private、可以是final

      缺点:
            1.不能声明@Bean之间的依赖,也就是说不能通过方法调用来依赖其它Bean(可以用其它方式“弥补”,比如:把依赖Bean放进方法入参)

    参照:https://www.imooc.com/article/306578

  • 相关阅读:
    c# 判断一个ip通不通 能不能ping通
    C#二进制与字符串互转换,十六进制转换为字符串、float、int
    将datagridview数据保为xml或txt文件
    笨办法学Python(九)
    笨办法学Python(八)
    笨办法学Python(七)
    Linux安装 NTFS 支持
    Linux安装中文字体包
    Oracle VM VirtualBox 共享文件夹设置
    Verilog频率计设计
  • 原文地址:https://www.cnblogs.com/ryjJava/p/14427242.html
Copyright © 2011-2022 走看看