学习springboot2的第3天(2021-12-02)08-底层注解-@Configuration详解
为了后面深入理解Springboot的自动配置的原理。我们先学习几个注解。
先准备好两个java bean:
根据前面讲的:
因为启动类:com.rtl.boot.MainApplication在这里
所以其他组件应该在com.rtl.boot包下面或者子包下面。
所以:
我们在com.rtl.boot包下新建一个包bean
以前:需要把这两个bean类添加到容器里面的方式:
在resources里面新建配置文件bean.xml
然后再里面写bean标签进行注册:
现在springboot如何给容器中添加组件呢?
方式1:
使用注解@Configuration
在com.rtl.boot下面,写一个类叫做config.MyConfig
给这个类的类体上写@Configuration
@Configuration这个注解就是告诉Springboot这个类是一个配置类。
然后再这个配置类里面写方法:
方法的
1、方法名:就是组件的id
2、返回值类型:就是组件类型
3、返回值:就是组件在容器里面的实例对象。
和写配置文件效果一样:
然后再主程序里面打印我们目前容器里面的组件。
测试看看有没有生成User和Pet
运行之后就打印了非常多的组件名字:
搜索:user01,找到了:
搜索:cat
这个是默认使用方法名来作为组件id。
如果不想使用方法名作为组件id。
那你就需要添加@Bean注解的属性:
再次运行:
现在搜索cat就没有了。而要搜索tom:
默认这种方式配置的组件,都是单实例的。
总结:
1、配置类的类体加@Configuration注解,这个配置类里面的方法使用@Bean注解,这种方式就可以给容器注册这个组件了。默认都是单实例的。
2、配置类MyConfig本身也已经在容器里面了。也是组件。
3、在注解Configuration里面有一个属性是Springboot1里面没有的。
这个属性:proxyBeanMethods
默认值是true。
这是个什么呢?
代理bean的方法。
测试情况1:
通过配置类对象调用方法 获取组件,问:多次获取的组件是单实例的吗?
1、拿到配置类对象:
//1、这就是返回IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
//2、通过IOC容器拿到配置类对象
MyConfig myConfig = run.getBean(MyConfig.class);
2、通过配置类对象调用cat方法获取Pet的对象。
查看这种方式得到的myConfig对象和是否单实例?
配置对象是增强代理对象,也是单实例
通过配置类对象调用方法 获取组件,问:多次获取的组件是单实例的吗?答案是:同一个对象。
结论:这种方式获取容器里面的对象都是单实例的。
这种方式获取对象和之前是不一样的。虽然之前也是单实例的。
之前第一种获取的形式:
现在第2种获取:通过配置类对象调用方法获取。
第二种方式获取,之所以也是单实例的,就是因为@Configuration注解里面有参数proxyBeanMethods,且默认值为true。
那如果第二种方式获取对象,我们设置注解@Configuration的属性proxyBeanMethods为false呢?
测试情况2:
发现,如果:
@Configuration(proxyBeanMethods = false)
那么配置类就不是增强代理对象了。而就是本身。
同时,获取的对象也不是单实例的。
总结:
//单实例,全模式 Full
@Configuration(proxyBeanMethods = true)
//多实例,轻量级模式 Lite
@Configuration(proxyBeanMethods = false)
这两个模式就很好的解决了组件之间的依赖问题。
调成false的优点就是:
Springboot不会来检查方法user01返回的User对象在容器有没有,跳过检查,这样Springboot启动就会比较快。
如果是true的话:
每一个调用方法user01,都会检查容器中是否有,这样就很慢。
这个设置为true还是false的使用场景:
1、如果组件之间没有依赖关系,那就使用false,轻量级。
2、如果组件之间有依赖关系,比如User类里面有个属性是Pet,也就是User组件依赖Pet,那为了保证User拿属性值的时候就是从容器里面去拿,而不是去外面拿,所以需要使用true Full模式。去扫描组件。