spring boot @Configuration(proxyBeanMethods = false) 详解

Lite模式

当@Bean方法在没有使用@Configuration注释的类中声明时,它们被称为在Lite模式下处理。
它包括:

  1. 类上标注有@Component注解
  2. 类上标注有@ComponentScan注解
  3. 类上标注有@Import注解
  4. 类上标注有@ImportResource注解
  5. 若类上没有任何注解,但类内存在@Bean方法
  6. 标注有 @Configuration(proxyBeanMethods = false) ,注意:此值默认是true哦,需要显示改为false才算是Lite模式

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

优缺点
优点:
  • 运行时不再需要给对应类生成CGLIB子类,提高了运行性能,降低了启动时间
  • 可以该配置类当作一个普通类使用喽:也就是说@Bean方法 可以是private、可以是final
缺点:
  • 不能声明@Bean之间的依赖,也就是说不能通过方法调用来依赖其它Bean
  • 其实这个缺点还好,很容易用其它方式“弥补”,比如:把依赖Bean放进方法入参里即可)
总结
  • 该模式下,配置类本身不会被CGLIB增强,放进IoC容器内的就是本尊
  • 该模式下,对于内部类是没有限制的:可以是Full模式或者Lite模式
  • 该模式下,配置类内部不能通过方法调用来处理依赖,否则每次生成的都是一个新实例而并非IoC容器内的单例
  • 该模式下,配置类就是一普通类嘛,所以@Bean方法可以使用private/final等进行修饰(static自然也是阔仪的)

Full模式

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

标注有@Configuration或者@Configuration(proxyBeanMethods = true)的类被称为Full模式的配置类
(当然喽,proxyBeanMethods属性的默认值是true,所以一般需要Full模式我们只需要标个注解即可)

优缺点

优点:

可以支持通过常规Java调用相同类的@Bean方法而保证是容器内的Bean,这有效规避了在“Lite模式”下操作时难以跟踪的细微错误。特别对于萌新程序员,这个特点很有意义

缺点:

运行时会给该类生成一个CGLIB子类放进容器,有一定的性能、时间开销(这个开销在Spring Boot这种拥有大量配置类的情况下是不容忽视的,这也是为何Spring 5.2新增了proxyBeanMethods属性的最直接原因)
正因为被代理了,所以@Bean方法 不可以是private、不可以是final

总结

  • 该模式下,配置类会被CGLIB增强(生成代理对象),放进IoC容器内的是代理
  • 该模式下,对于内部类是没有限制的:可以是Full模式或者Lite模式
  • 该模式下,配置类内部可以通过方法调用来处理依赖,并且能够保证是同一个实例,都指向IoC内的- 那个单例
  • 该模式下,@Bean方法不能被private/final等进行修饰(很简单,因为方法需要被复写嘛,所以不能私有和final。defualt/protected/public都可以哦),否则启动报错(其实IDEA编译器在编译器就提示可以提示你了)

你可能感兴趣的:(java,spring,spring,boot)