@Configuration详解,功能:将想要的组件添加到容器中
首先,需要准备三个文件:
ps:完整代码片在文章最后,建议看完教程。
1.主程序类:
2.宠物类
3.用户类
对比以前原生spring添加组件的区别
如果是以前的原生spring,想要将组件添加到容器中
1.需要在resources目录下创建一个xml配置文件
2.创建bean标签
现在的Spring Boot已经不需要向以前一样了,有一个注解@Configuration(翻译:配置)可以供使用
1.创建一个类。
2.使用注解@Configuration,告诉Spring Boot这是一个配置类。
这个时候在类里边不能写bean标签了需要使用@bean注解,想要构建出user和pet对象需要自己将它创造出来。
@bean:给容器中添加组件,以方法名作为组件的id。返回类型为组件类型,返回的值,就是组件在容器中的实例
怎么验证创建这俩组件成功了呢?
首先来到主程序
运行主程序就能查到刚刚创建好的组件:
当然,如果不喜欢这个原本的名字是可以换的
给容器中注册的组件默认是单实例的。
就是说无论我们从容器中获取多少次,它们都是一样的
可以看到,返回的都是true,也就说明都是相等的 。
所以:配置类里面使用@Bean标注在方法上给容器注册组件,默认是单实例的。
同时还有一点,被@Configuration标注的类本身也是一个组件
可以从容器中取这个类来验证一下。
同时,在Spring Boot 5.2之后的@Configuration注解多了一个属性proxyBeanMethods,默认为true(翻译:代理bean的方法)
顾名思义,既然默认为true了,也就是默认代理。
代理就会保持组件的单实例。
也就是说,虽然写的Myconfig是在容器中注册组件用的,但是在注册组件之前会在容器中查找有没有该组件。如果有,则取该组件用于保证单实例,如果没有再注册一个新的组件。
这里可以调用两次注册组件的方法来确认是否使用了代理:
虽然是调用了两次,可它们两个是相等的,也就是说使用了代理,取的都是同一个值。
如果将@Configuration(proxyBeanMethods = true)改为false
再次运行就会发现这次取的不是代理对象,也就是每一个方法都新注册了一个组件,所以两个不相等。
因为改为false后久不会再保存代理对象了。
proxyBeanMethods:代理bean的方法
有两种模式:
1.Full:(proxyBeanMethods = true) //全模式
使用代理模式,保证组件的单实例,启动不如false快,但是重复利用率高,适用于会重复使用组件的场景。
2.lite:(proxyBeanMethods = false) //轻量级
不是用代理模式,不用保证组件的单实例,启动最快。单每次调用组件都会重新创建一个新的组件,组件可重复使用率低。适用于需要组件但不会重复使用的场景
总结:用于解决组件依赖
可有验证方法:
1.在User类加入Pet类,同时增加get和set方法
2.在Myconfig类使用user01调用pet01
3.在主程序中获取user01和pet01组件,并将user01组件中的Pet类和组件pet01组件进行对比。
4.对比结果:
当proxyBeanMethods = true时,两者是相等的,代表使用了代理模式没用重新创建pet01组件
当proxyBeanMethods = false时,两者对比不相等,表示重新创建了组件
最终程序代码片:
1.主程序类:
/**
* 这是一个主程序类
* @SpringBootApplication:表明这是一个SpringBoot应用
*/
@SpringBootApplication(scanBasePackages="com.shiyi")
public class MainApplication {
public static void main(String[] args) {
//1、返回我们ioc容器
ConfigurableApplicationContext run =
SpringApplication.run(MainApplication.class, args);
//2、查看容器里面的组件
String[] names = run.getBeanDefinitionNames();
for(String name : names){
System.out.println(name);//打印出所有的组件名称
}
//3、从容器中获取组件
// Pet pet01 = run.getBean("德玛西亚~",Pet.class);
//
// Pet pet02 = run.getBean("德玛西亚~",Pet.class);
// System.out.println("是否相等"+(pet01 == pet02));
// System.out.println("是否相同"+pet01.equals(pet02));
Myconfig bean = run.getBean(Myconfig.class);
System.out.println("配置类---"+bean);//进度08:15
User user = bean.user01();
User user1 = bean.user01();
System.out.println("验证是否使用代理:"+(user == user1));
User user01 = run.getBean("user01", User.class);
Pet pet011 = run.getBean("pet01", Pet.class);
System.out.println("用户的宠物:"+(user01.getPet() == pet011));
}
}
2.配置类
/**
* 1、配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的
* 2、配置类本身也是组件
* 3、proxyBeanMethods:代理bean的方法
* Full:(proxyBeanMethods = true) //全模式
* lite:(proxyBeanMethods = false) //轻量级
* 用于解决组件依赖
*/
@Configuration(proxyBeanMethods = true) //告诉springboot这是一个配置类 == 配置文件
public class Myconfig {
@Bean//给容器中添加组件,以方法名作为组件的id。
// 返回类型为组件类型,返回的值,就是组件在容器中的实例
public User user01(){
User wangcai = new User("wangcai",23);
//user组件依赖了pet组件
wangcai.setPet(pet01());
return wangcai;
}
@Bean
public Pet pet01(){
return new Pet("旺财");
}
}
3.User类
/**
* 用户
*/
public class User {
private String name;
private Integer age;
private Pet pet;
public User(){
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
public Pet getPet() {
return pet;
}
public void setPet(Pet pet) {
this.pet = pet;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
4.Pet类
/**
* 宠物
*/
public class Pet {
private String name;
public Pet() {
}
public Pet(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Pet{" +
"name='" + name + '\'' +
'}';
}
}