Spring

@Component

  • @Component注解表明⼀个类会作为组件类,并告知Spring要为这个类创建bean
  • @Component (@Controller、@Service、@Repository)通常是通过类路径扫描来⾃动侦测以及⾃动装配到Spring容器中。

@Bean

  • @Bean注解告诉Spring这个⽅法将会返回⼀个对象,这个对象要注册为Spring应⽤上下⽂中的bean。
  • 通常⽅法体中包含了最终产⽣bean实例的逻辑,并且实例名就是⽅法名。
  • @Bean则常和@Configuration注解搭配使⽤

使用逻辑

  1. 如果想将第三⽅的类变成组件,你⼜没有没有源代码,也就没办法使⽤@Component进⾏⾃动配置,这种时候使⽤@Bean就⽐较合适了。
  2. 不过同样的也可以通过xml⽅式来定义。
  3. 另外@Bean注解的⽅法返回值是对象,可以在⽅法中为对象设置属性。

@Configuration

  • @Configuration 标注的类, @Bean 标注的⽅法。
  • @Configuration 标注的类等同于⼀个xml⽂件, @Bean 标注的⽅法等同于xml⽂件⾥的⼀ 个标签

Full模式和Lite模式

  • Full模式和Lite模式均是针对于Spring配置类⽽⾔的,和xml配置⽂件⽆关。
  • 值得注意的是:判断是Full模式 or Lite模式的前提是,⾸先你得是个容器组件。
  • 如果是在公司的业务功能/服务上做开发,使⽤Full模式
  • 如果你是个容器开发者,或者你在开发中间件、通⽤组件等,那么使⽤Lite模式是⼀种更被推荐的⽅式,它对 Cloud Native更为友好

Lite模式

  • 官方定义为:在没有标注@Configuration的类里面有@Bean方法就称为Lite模式的配置。

  • 透过源码再看这个定义是不完全正确的,而应该是有如下case均认为是Lite模式的配置类:

    • 类上标注有@Component注解
    • 类上标注有@ComponentScan注解
    • 类上标注有@Import注解
    • 类上标注有@ImportResource注解
    • 若类上没有任何注解,但类内存在@Bean方法
    • 以上case的前提均是类上没有被标注@Configuration
    • 在Spring 5.2之后新增了一种case也算作Lite模式:
      • 标注有@Configuration(proxyBeanMethods = false),注意:此值默认是true哦,需要显示改为false才算是Lite模式
  • 细心的你会发现,自Spring5.2(对应Spring Boot 2.2.0)开始,内置的几乎所有的@Configuration配置类都被修改为了@Configuration(proxyBeanMethods = false),目的何为?答:以此来降低启动时间,为Cloud Native继续做准备。

  • Lite模式优缺点

    • 优点:

      • 运⾏时不再需要给对应类⽣成CGLIB⼦类,提⾼了运⾏性能,降低了启动时间,
      • 该配置类可以当作⼀个普通类使⽤:也就是说@Bean⽅法 可以是private、可以是final
    • 缺点:

      • 不能声明@Bean之间的依赖,也就是说不能通过⽅法调⽤来依赖其它Bean
      • 其实这个缺点还好,很容易⽤其它⽅式“弥补”,⽐如:把依赖Bean放进⽅法⼊参⾥即可
  • 总结:

    • Lite模式下,配置类本⾝不会被CGLIB增强,放进IoC容器内的就是本尊
    • 该模式下,对于内部类是没有限制的:可以是Full模式或者Lite模式
    • 该模式下,配置类内部不能通过⽅法调⽤来处理依赖,否则每次⽣成的都是⼀个新实例⽽并⾮IoC容器内的单例
    • 该模式下,配置类就是⼀普通类嘛,所以@Bean⽅法可以使⽤private/final等进⾏修饰(static⾃然也是阔仪 的)

Full模式

  • 在常⻅的场景中, @Bean ⽅法都会在标注有 @Configuration 的类中声明,以确保总是使⽤“Full模式”,这么⼀来,交叉⽅法引⽤会被重定向到容器的⽣命周期管理,所以就可以更⽅便的管理Bean依赖。

  • 何时为Full模式

    1. 标注有@Configuration注解的类被称为full模式的配置类。
    2. ⾃Spring5.2后这句话改为下⾯这样我觉得更为精确些:
      • 标注有@Configuration或者@Configuration(proxyBeanMethods = true)的类被称为Full模式的配置类
      • 当然喽,proxyBeanMethods属性的默认值是true,所以⼀般需要Full模式我们只需要标@Configuration注解即可
  • Full模式优缺点

    • 优点:
      • 可以⽀持通过常规Java调⽤相同类的@Bean⽅法⽽保证是容器内的Bean,这有效规避了在“Lite模式”下操作时难以跟踪的细微错误。特别对于萌新程序员,这个特点很有意义
    • 缺点:
      • 运⾏时会给该类⽣成⼀个CGLIB⼦类放进容器,有⼀定的性能、时间开销(这个开销在Spring Boot这种拥有⼤量配置类的情况下是不容忽视的,这也是为何Spring 5.2新增了proxyBeanMethods属性的最直接原因)
      • 正因为被代理了,所以@Bean⽅法 不可以是private、不可以是final

SpringBoot

@ConfigurationProperties

  • @ConfigurationProperties是springboot提供读取配置⽂件的⼀个注解。

  • 其对应的bean的后置处理器为 ConfigurationPropertiesBindingPostProcessor

    1
    2
    public class ConfigurationPropertiesBindingPostProcessor
    implements BeanPostProcessor, PriorityOrdered, ApplicationContextAware, InitializingBean {}
  • 它是实现了BeanPostProcessor接⼝,在bean被实例化后,会调⽤后置处理,递归的查找属性,通过反射注⼊值

  • 对⼤多数属性⽽⾔强制需提供其setter和getter⽅法。 但是属性名称不要求⼀定相同,只需保证配置⽂件的属性和setter⽅法名相同即可。

  • 不过@ConfigurationProperties注解, 只可以把应⽤主配置⽂件的内容读取进来, 要想给Bean赋值, 只能读取主配置⽂件,就是application.properties或者application.yml⽂件

  • 若我们想⾃⼰写⼀个配置⽂件来给bean赋值,我们就可以使⽤该注解@PropertyResource

  • 我们在resource⾥边新建⼀个student.properties⽂件,并把之前主配置⽂件⾥的内容剪贴进来,并在bean上边加 上注解

    1
    2
    3
    4
    5
    6
    7
    @Component
    @ConfigurationProperties(prefix = "student")
    @PropertyResource(value = {"classpath:student.properties"},encoding = "UTF-8")
    // value可以添加多个配置⽂件,classpath指的是类路径,表⽰类路径下的student.properties⽂件
    public class Student {
    //......
    }

注⼊bean的三种⽅式

  • @ConfigurationProperties读取配置⽂件, 注⼊bean的⽅式

    1. 配合@Component注解直接进⾏注⼊(主要)

      1
      2
      3
      4
      5
      @Component
      @ConfigurationProperties(prefix = "student")
      public class Student {
      //......
      }
    2. 使⽤@EnableConfigurationProperties,通常配置在标有@Configuration的类上,当然其他@Component注 解的派⽣类也可以,不过不推荐.

      • @EnableConfigurationProperties的作⽤: 使@ConfigurationProperties注解的类⽣效,并将标注@ConfigurationProperties的类注册到spring容器中
      • @EnableConfigurationProperties({DocumentServerProperties.class}) 只是让DocumentServerProperties类生效,将其注入到spring容器中
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      @ConfigurationProperties(prefix = "doc")
      public class DocumentServerProperties {
      //代码...
      }


      @EnableConfigurationProperties
      @Configuration
      public class SomeConfiguration {
      }
    3. 使⽤@Bean⽅式在标有@Configuration的类进⾏注⼊,这种⽅式通常可以⽤在对第三⽅类进⾏配置属性注册

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      public class ThirdComponent {
      ...
      }

      @Configuration
      public class SomeConfiguration {
      @ConfigurationProperties("demo")
      @Bean
      public ThirdComponent thirdComponent(){
      return new ThirdComponent();
      }
      }

@ImportResource

  • 导⼊Spring的配置⽂件,让配置⽂件⾥边的内容⽣效.
  • 我们在使⽤spring的时候,通常会⽤xml去配置bean然后注⼊数据. 这对 Spring Boot 兼容⽼项⽬⾮常有⽤,因为有些配置⽆法通过 Java Config 的形式来配置就只能⽤这个注解来导⼊。