springboot注解之@Configuration 和 @Bean

时间:2024-01-28 18:37:33

1.包结构

 

 

 

2.主程序类 

 1 /**
 2  * 主程序类
 3  * @SpringBootApplication:这是一个springboot应用
 4  *
 5  * @SpringBootApplication
 6  *
 7  * 等同于下面的三个包
 8  * @SpringBootConfiguration
 9  * @EnableAutoConfiguration
10  * @ComponentScan(com.atguigu.boot)  ---->默认组件扫描基础包是主程序类MainApplication所在包及其子包
11  *
12  *
13  */
14 @SpringBootApplication(scanBasePackages={"com.atguigu"})
15 public class MainApplication {
16     public static void main(String[] args) {
17         //1.返回IOC容器
18         ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
19         //2.获取容器内所有组件的名称
20         String[] names = run.getBeanDefinitionNames();
21         for (String name : names) {
22             System.out.println(name);
23         }
24 
25         //3.从容器中获取指定组件
26         User user01 = run.getBean("user01", User.class);
27         User user02 = run.getBean("user01", User.class);
28         System.out.println("使用同一个组件id,多次获取组件,是否是同一个组件实例:" + (user01 == user02));
29 
30         //配置类本身也是组件
31         Myconfig myConfig = run.getBean(Myconfig.class);
32         Myconfig myConfig2 = run.getBean(Myconfig.class);
33         System.out.println(myConfig == myConfig2);
34 
35         //4. 配置类默认情况下是@Configuration(proxyBeanMethods = true),代表配置类此时不是一个普通的类
36         //可以把它理解为代理bean,此时打印结果是 com.atguigu.boot.config.Myconfig$$EnhancerBySpringCGLIB$$a3f7b687@5b5caf08
37         //如果配置类上@Configuration(proxyBeanMethods = false),此时配置类就是一个普通类
38         //此时打印结果:com.atguigu.boot.config.Myconfig@6e28bb87
39         System.out.println(myConfig);
40 
41         //5.如果@Configuration(proxyBeanMethods = true) 开启代理bean调用方法
42         //则当配置类对象调用其注册组件方法去获取相应组件时,Springboot总会检查组件是否在容器中
43         //保持组件单实例
44         User user1 = myConfig.user01();
45         User user2 = myConfig.user01();
46         //默认情况下@Configuration(proxyBeanMethods = true),打印结果是 true
47         //如果@Configuration(proxyBeanMethods = false),则打印结果是 false
48         System.out.println("配置类是作为代理bean从容器中获取单例组件呢?还是作为普通类调用方法呢? " + (user1 == user2));
49 
50         User user3 = run.getBean("user01", User.class);
51         Pet tomcatPet = run.getBean("tomcatPet", Pet.class);
52         //如果@Configuration(proxyBeanMethods = true),
53         //此时容器中的user01组件依赖容器中的tomcatPet组件,返回 true
54         System.out.println("用户的宠物是否是容器中的那个单实例宠物组件? " + (user3.getPet() == tomcatPet));
55 
56     }
57 }

 

3.bean包下的两个实体类

User

 1 public class User {
 2     private String name;
 3     private Integer age;
 4 
 5     private Pet pet;
 6 
 7     public User() {
 8     }
 9 
10     public User(String name, Integer age) {
11         this.name = name;
12         this.age = age;
13     }
14 
15     public Pet getPet() {
16         return pet;
17     }
18 
19     public void setPet(Pet pet) {
20         this.pet = pet;
21     }
22 
23     public String getName() {
24         return name;
25     }
26 
27     public void setName(String name) {
28         this.name = name;
29     }
30 
31     public Integer getAge() {
32         return age;
33     }
34 
35     public void setAge(Integer age) {
36         this.age = age;
37     }
38 
39     @Override
40     public String toString() {
41         return "User{" +
42                 "name='" + name + '\'' +
43                 ", age=" + age +
44                 ", pet=" + pet +
45                 '}';
46     }
47 }

  Pet

 1 public class Pet {
 2     private String name;
 3 
 4     public Pet() {
 5     }
 6 
 7     public Pet(String name) {
 8         this.name = name;
 9     }
10 
11     public String getName() {
12         return name;
13     }
14 
15     public void setName(String name) {
16         this.name = name;
17     }
18 
19     @Override
20     public String toString() {
21         return "Pet{" +
22                 "name='" + name + '\'' +
23                 '}';
24     }
25 }

 

4.config包下的配置类 Myconfig

 1 /**
 2     1.配置类里面使用@Bean标注在方法上给容器注册组件,默认是单实例的
 3     2.配置类本身也是组件
 4     3.proxyBeanMethods:配置类是否作为代理bean来调用方法
 5         如果 proxyBeanMethods = true 则是Full模式(重量级模式)
 6             ---> 此模式下,配置类作为代理bean来调用方法,springboot都会去容器里面检查有没有这个组件,如果有,就使用容器中的组件,确保单实例,形成组件依赖
 7         如果 proxyBeanMethods = false 则是Lite模式(轻量级模式)
 8             ---> 此模式下,配置类是作为普通类调用方法,springboot不会去容器里面检查组件,不会形成组件依赖,项目启动运行快
 9 
10     4.最佳实战
11         配置类组件之间无依赖关系,用Lite模式加速容器启动过程,减少判断
12         配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式
13  */
14 @Configuration(proxyBeanMethods = false)  //告诉Springbooot这是一个配置类
15 public class Myconfig {
16 
17     /**
18      * 外部无论对配置类中的组件注册方法调用多少次,获取的都是之前注册在容器中的单实例对象
19      * @return
20      */
21 
22     @Bean   //给容器中添加组件,默认以方法名作为组件id(组件名)。返回类型就是组件类型,返回值就是组件在容器中的实例
23     public User user01() {
24         User user = new User("zhangsan", 20);
25         //如果@Configuration(proxyBeanMethods = true),
26         // 此时容器中的user01组件依赖容器中的tomcatPet组件
27         user.setPet(cat());
28         return user;
29     }
30 
31 
32     @Bean("tomcatPet") //此时组件名就是tomcatPet,而不是方法名了
33     public Pet cat() {
34         return new Pet("HelloKitty");
35     }
36 }