本文基于Spring 5.2.15-RELEASE

关于Spring配置类的Full模式和Lite模式,如果没有仔细阅读过源码或者官方文档的话,估计很多人都不知道这个概念。所以我们先来解释下这两个概念。

概念解释

@Configuration
public class DataSourceConfig { ...
@Bean
public DataSource dataSource() {
...
return dataSource;
}
@Bean(name = "transactionManager")
public DataSourceTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
...
}

DataSourceConfig就是一个在Spring中非常常见的配置类,这个配置类本身也会被注册成Spring容器中的一个Bean。上面这种配置方式默认的就是Full模式。为什么默认是Full模式呢?其实秘密就藏在@Configuration这个注解中。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration { @AliasFor(annotation = Component.class)
String value() default "";
// 默认会通过Cglib对产生Bean的方法进行增强
boolean proxyBeanMethods() default true;
}

这个注解有一个属性proxyBeanMethods。这个属性的值默认是true,会通过Cglib对这个配置类进行增强,增强后这个配置类就显得比较“重”,因此叫Full模式。如果我们将这个属性设置成false的话,这个配置类产生的Bean就是原始的对象,比较“轻量级”,叫Lite模式。因此,Full模式和Lite模式最本质的区别是:配置类本身的Bean对象会不会被Cglib增强。

这里再强调一个概念:Full模式和Lite模式都是说DataSourceConfig这个配置类是Full模式或者Lite模式。

Lite模式

上面提到,将@Configuration的proxyBeanMethods属性设置成false就Lite模式的配置类,其实还有很多其他的场景也属于Lite模式。整理下来,大致有以下这些场景:

  1. 类上标注有@Component注解
  2. 类上标注有@ComponentScan注解
  3. 类上标注有@Import注解
  4. 类上标注有@ImportResource注解
  5. 若类上没有任何注解,但类内存在@Bean方法
  6. 标注有@Configuration(***proxyBeanMethods = false***)

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

优点

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

缺点

  • 不能声明@Bean之间的依赖,也就是说不能通过方法调用来依赖其它Bean
@Configuration(proxyBeanMethods = false)
public class DataSourceConfig { ...
@Bean
public DataSource dataSource() {
...
return dataSource;
}
@Bean(name = "transactionManager")
public DataSourceTransactionManager transactionManager() {
// 此处的dataSource()调用就是一次普通的方法调用,不会引用Spring IOC容器中的单列Bean
return new DataSourceTransactionManager(dataSource());
}
...
}

这个问题可以这样解决

@Configuration(proxyBeanMethods = false)
public class DataSourceConfig { ...
@Bean
public DataSource dataSource() {
...
return dataSource;
}
@Bean(name = "transactionManager")
// 通过方法参数引用Spring容易中的Bean
public DataSourceTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource;
}
...
}

Full模式

标注有@Configuration或者@Configuration(***proxyBeanMethods = true***)的类被称为Full模式的配置类。

优点

  • 可以支持通过常规Java调用相同类的@Bean方法而保证是容器内的Bean;

缺点

  • 运行时会给该类生成一个CGLIB子类放进容器,有一定的性能、时间开销;
  • 正因为被代理了,所以@Bean方法 不可以是private、不可以是final

简单总结

Spring的配置类分成Full和Lite两种模式。

在Lite模式下

  • 配置类本身不会被CGLIB增强,放进IoC容器内的就是配置类本身;
  • 对于内部类是没有限制的:可以是Full模式或者Lite模式;
  • 配置类内部不能通过方法调用来处理依赖,否则每次生成的都是一个新实例而并非IoC容器内的单例
  • 配置类就是一普通类嘛,所以内部的@Bean方法可以使用private/final等进行修饰

在Full模式下

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

从上面的介绍可以看出来,Lite模式很大程度上是为了减少启动开销,提升程序的启动速度。所以如果你对程序的启动速度很敏感,就使用Lite模式,但是一定要记住此时的配置类已经不是经过Cglib增强过的类了。

参考

Spring配置类为什么要分Full和Lite模式的更多相关文章

  1. 使用spring配置类代替xml配置文件注册bean类

    spring配置类,即在类上加@Configuration注解,使用这种配置类来注册bean,效果与xml文件是完全一样的,只是创建springIOC容器的方式不同: //通过xml文件创建sprin ...

  2. 521我发誓读完本文,再也不会担心Spring配置类问题了

    当大潮退去,才知道谁在裸泳.关注公众号[BAT的乌托邦]开启专栏式学习,拒绝浅尝辄止.本文 https://www.yourbatman.cn 已收录,里面一并有Spring技术栈.MyBatis.中 ...

  3. Spring配置类深度剖析-总结篇(手绘流程图,可白嫖)

    生命太短暂,不要去做一些根本没有人想要的东西.本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以免费学习 ...

  4. Spring配置类理解(Lite模式和Full模式)

    Spring中的注解大家在开发中都常常用到,但是如果我说我们常常用的注解修饰了一个类,表示这个类就是一个配置类很多开发者都会有点迷糊了.具体配置类在开发中有什么样的用途我就不多说了,相信很多人都知道, ...

  5. Spring(九):Spring配置Bean(二)自动装配的模式、Bean之间的关系

    XML配置里的Bean自动装配 Spring IOC容器可以自动装配Bean,需要做的仅仅是在<bean>的autowire属性里指定自动装配的模式,模式包含:byType,byName, ...

  6. 使用配置类而不使用XML文件(代替bean.xml)对spring进行配置

    以下类是一个配置类,它的作用和bean.xml是一样的注解: @Configuration 作用: 用于指定当前类是一个spring配置类,当创建容器时会从该类上加载注解. 获取容器时需要使用Anno ...

  7. 【Spring】简述@Configuration配置类注册BeanDefinition到Spring容器的过程

    概述 本文以SpringBoot应用为基础,尝试分析基于注解@Configuration的配置类是如何向Spring容器注册BeanDefinition的过程 其中主要分析了 Configuratio ...

  8. 真懂Spring的@Configuration配置类?你可能自我感觉太良好

    当大潮退去,才知道谁在裸泳.关注公众号[BAT的乌托邦]开启专栏式学习,拒绝浅尝辄止.本文 https://www.yourbatman.cn 已收录,里面一并有Spring技术栈.MyBatis.中 ...

  9. 配置类需要标注@Configuration却不知原因?那这次就不能给你涨薪喽

    专注Java领域分享.成长,拒绝浅尝辄止.关注公众号[BAT的乌托邦]开启专栏式学习,拒绝浅尝辄止.本文 https://www.yourbatman.cn 已收录,里面一并有Spring技术栈.My ...

  10. 脱离xml使用JavaConfig实现Spring配置

    总结 情况一: 配置类中类名添加 @Configuration 注解,同时提供一个方法返回一个Bean实例,且这个方法添加注解 @Bean ,就可以由Spring管理此对象 如下所示: User.ja ...

随机推荐

  1. bzoj 4817

    LCT好题 首先我们考虑实际询问的是什么: 从LCT的角度考虑,如果我们认为一开始树上每一条边都是虚边,把一次涂色看作一次access操作,那么询问的实际就是两个节点间的虚边数量+1和子树中的最大虚边 ...

  2. 西瓜书3.4 解题报告(python 多分类学习 十折交叉法)

    偷懒找了UCI上最小的一个数据集,数据大约是集装箱起重机的转动速度.角度,判断其力量大小(我不懂起重机啊啊啊) 虽然不懂但并不妨碍写代码分类,显然标记就是力量,分为0.3.0.5.0.7三种.具体的模 ...

  3. OO课程第二阶段(实验和期中试题)总结Blog2

    OO课程第二阶段(实验和期中试题)总结Blog2 前言:学习OOP课程的第二阶段已经结束了,在此进行对于知识点,题量,难度的个人看法. 学习OOP课程的第二阶段已经结束了,较第一次阶段学习难度加大,学 ...

  4. Linux_Tomcat实战

    Tomcat实战 tomcat简述 tomcat安装 部署jspgou项目 tomcat简述 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,Tomcat是Apache 软件基金会(A ...

  5. java接口自动化需要的技术

    1.testNG需要了解的知识 ITestContext这个类可以直接在方法参数里使用,主要作用是可以通过它的context.getSuite()直接获取suite的相关信息.还可以通过它的 cont ...

  6. 08 分布式计算MapReduce--词频统计

    def getText(): txt=open("D:\\test.txt","r").read() txt=txt.lower() punctuation = ...

  7. virtualvm2 观察者模式

    <template> <div id="app"> <input type="text" v-model='msg'> &l ...

  8. Q:su命令切换用户无法使用,被拒绝

    su命令切换用户无法使用,被拒绝 问题描述 su 命令报错 su: Permission denied 如下图: su 命令 报错 su: Permission denied,不管是su普通用户还是r ...

  9. alia linux

    alias lrt='ls -lrt'

  10. 什么是js柯里化(curry)?

    在数学和计算机科学中,柯里化是一种将使用多个参数的一个函数转换成一系列使用一个参数的函数的技术. 举例来说,一个接收3个参数的普通函数,在进行柯里化后,柯里化版本的函数接收一个参数并返回接收下一个参数 ...