springboot注解之@Configuration 和 @Bean
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 }