springboot注解之@Import @Conditional @ImportResource @ConfigurationProperties @EnableConfigurationProperties
1.包结构
2.主程序类
1 @SpringBootApplication(scanBasePackages={"com.atguigu"}) 2 public class MainApplication { 3 public static void main(String[] args) { 4 //1.返回IOC容器 5 ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args); 6 //2.获取容器内所有组件的名称 7 String[] names = run.getBeanDefinitionNames(); 8 for (String name : names) { 9 System.out.println(name); 10 } 11 12 13 //获取指定组件类型的所有组件名称 14 String[] beanNamesForType = run.getBeanNamesForType(User.class); 15 //com.atguigu.boot.bean.User --->通过@Import({User.class})在容器中自动创建的组件,默认组件名是全类名 16 //user01 --->配置类中通过@Bean给容器注册组件,组件名默认是方法名 17 //haha --->从spring配置文件beans.xml导入添加到容器中的haha组件 18 for (String bean : beanNamesForType) { 19 System.out.println(bean); 20 } 21 22 boolean tomcatPet = run.containsBean("tomcatPet"); 23 System.out.println("容器中是否有tomcatPet组件? " + tomcatPet); 24 25 boolean user01 = run.containsBean("user01"); 26 System.out.println("容器中是否有user01组件? " + user01); 27 28 //spring配置文件beans.xml只有导入到了容器中, 29 //这个配置文件中配置的bean才能添加到容器中 30 //导入方式:一般在配置类上加上@ImportResource("classpath:beans.xml"), 31 // 括号内指定xml的文件路径 32 boolean haha = run.containsBean("haha"); 33 boolean hehe = run.containsBean("hehe"); 34 System.out.println(haha); 35 System.out.println(hehe); 36 37 Car car = run.getBean(Car.class); 38 System.out.println(car); 39 40 } 41 }
3.资源文件
application.properties
1 #每一个key都是某个类的属性,而且都有默认值,可以修改 2 server.port=8888 3 4 #默认文件上传的最大文件大小是1MB,修改为10MB 5 #spring.servlet.multipart.max-file-size=10MB 6 7 mycar.brand=BYD 8 mycar.price=100000
beans.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- spring使用<bean>标签给容器添加组件--> <bean id="haha" class="com.atguigu.boot.bean.User"> <property name="name" value="张三"/> <property name="age" value="18"/> </bean> <bean id="hehe" class="com.atguigu.boot.bean.Pet"> <property name="name" value="helloKitty"/> </bean> </beans>
4.config包下配置类
1 package com.atguigu.boot.config; 2 3 import com.atguigu.boot.bean.Car; 4 import com.atguigu.boot.bean.Pet; 5 import com.atguigu.boot.bean.User; 6 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; 7 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 8 import org.springframework.boot.context.properties.EnableConfigurationProperties; 9 import org.springframework.context.annotation.*; 10 11 /** 12 1.配置类里面使用@Bean标注在方法上给容器注册组件,默认是单实例的 13 2.配置类本身也是组件 14 3.proxyBeanMethods:配置类是否作为代理bean来调用方法 15 如果 proxyBeanMethods = true 则是Full模式(重量级模式) 16 ---> 此模式下,配置类作为代理bean来调用方法,springboot都会去容器里面检查有没有这个组件,如果有,就使用容器中的组件,确保单实例,形成组件依赖 17 如果 proxyBeanMethods = false 则是Lite模式(轻量级模式) 18 ---> 此模式下,配置类是作为普通类调用方法,springboot不会去容器里面检查组件,不会形成组件依赖,项目启动运行快 19 20 4.最佳实战 21 配置类组件之间无依赖关系,用Lite模式加速容器启动过程,减少判断 22 配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式 23 24 5.@Import({User.class}) 25 给容器中自动创建出这个类型的组件,默认组件名是其全类名 26 27 6.@Conditional 条件装配:满足Conditional指定的条件,组件才会被添加到容器中 28 @ConditionalOnBean(name="user01") 29 @ConditionalOnMissingBean(name = "user01") 30 31 7.@ImportResource("classpath:beans.xml") 将spring配置文件导入到容器中 32 33 8.配置绑定(属性)的两种方式 34 第一种方式:目标bean上加上如下两个注解 35 @Component //将目标bean作为组件添加到容器中 36 @ConfigurationProperties("mycar") //配置属性:将配置文件中指定前缀的属性值映射到对象的属性 37 注意:由于只有在容器中的组件,才能拥有SpringBoot提供的强大功能,所以这两个注解一般配合使用 38 第二种方式 39 在目标bean上加上@ConfigurationProperties("mycar") 40 在配置类上加上@ConfigurationProperties(Car.class) //1.开启Car的属性绑定功能 2.将Car组件自动注册到容器中 41 注:这种方法比较适合用于目标bean是第三方jar包里的类,因为没法使用第一种方法在它上面标注@Component 42 43 */ 44 45 @Import({User.class}) 46 @Configuration(proxyBeanMethods = false) //告诉Springbooot这是一个配置类 47 //@ConditionalOnBean(name="user01") //条件装配:当满足容器中有user01组件这个条件,该配置类中带有@Bean的组件方法才能添加组件到容器中 48 //@ConditionalOnMissingBean(name = "user01") //条件装配:当容器中没有user01组件时,该配置类中带有@Bean的组件方法才能添加组件到容器中 49 @ImportResource("classpath:beans.xml") 50 @EnableConfigurationProperties(Car.class) 51 public class Myconfig { 52 53 /** 54 * 外部无论对配置类中的组件注册方法调用多少次,获取的都是之前注册在容器中的单实例对象 55 * @return 56 */ 57 //执行此语句会判断容器中是否有tomcatPet组件,由于程序代码顺序执行,所以容器里面此时没有tomcatPet组件 58 //因此user01组件的条件不满足,容器不会添加user01组件 59 // @ConditionalOnBean(name="tomcatPet") //条件装配:只有当容器中有tomcatPet组件时,user01组件才能添加到容器中 60 @Bean //给容器中添加组件,默认以方法名作为组件id(组件名)。返回类型就是组件类型,返回值就是组件在容器中的实例 61 public User user01() { 62 User user = new User("zhangsan", 20); 63 //如果@Configuration(proxyBeanMethods = true), 64 // 此时容器中的user01组件依赖容器中的tomcatPet组件 65 user.setPet(cat()); 66 return user; 67 } 68 69 70 @Bean("tomcatPet") //此时组件名就是tomcatPet,而不是方法名了 71 public Pet cat() { 72 return new Pet("HelloKitty"); 73 } 74 }
5.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 }
Car
1 /** 2 * 只有在容器中的组件,才能拥有SpringBoot提供的强大功能, 3 * 所以在使用@ConfigurationProperties("mycar")配置属性的前提是此bean为组件 4 */ 5 6 //@Component //将此bean作为组件添加到容器中 7 @ConfigurationProperties("mycar") 8 //配置属性:将配置文件application.properties中指定前缀mycar的属性值映射到对象中相应的属性 9 public class Car { 10 private String brand;//品牌 11 private Double price;//价格 12 13 public Car() { 14 } 15 16 public Car(String brand, Double price) { 17 this.brand = brand; 18 this.price = price; 19 } 20 21 public String getBrand() { 22 return brand; 23 } 24 25 public void setBrand(String brand) { 26 this.brand = brand; 27 } 28 29 public Double getPrice() { 30 return price; 31 } 32 33 public void setPrice(Double price) { 34 this.price = price; 35 } 36 37 @Override 38 public String toString() { 39 return "Car{" + 40 "brand='" + brand + '\'' + 41 ", price=" + price + 42 '}'; 43 } 44 }
6.controller包下控制类
1 /** 2 * 3 * 默认包 4 * springboot会将主程序所在包及其所有子包下的组件扫描进IOC容器 5 * 6 * 如果组件不在主程序所在包或者其子包下,比如WorldController组件,则必须将此组件所在全包名com.atguigu, 7 * 声明在主程序类的@SpringBootApplication注解后面, 8 * @SpringBootApplication(scanBasePackages={"com.atguigu"}),如果多个以字符串数组的形式 9 * 这样此组件才能被扫描进IOC容器 10 */ 11 12 13 //@ResponseBody 方法直接返回字符串给浏览器 14 //@Controller 15 // @RestController = @ResponseBody + @Controller 16 @RestController 17 public class HelloController { 18 @Autowired //自动注入组件 19 Car car; 20 21 @RequestMapping("/car") 22 public Car car() { 23 return car; 24 } 25 26 @RequestMapping("/hello") 27 public String handle01() { 28 return "hello,Spring boot 2!" + " 你好"; 29 } 30 }