2.3、配置绑定
就是实体类通过配置文件进行赋值
。
切记:任何一个注解都只对IOC容器生效,如果注解没有加入IOC容器中去,那么会爆红且报错
(1).@ConfigurationProperties (第一种)
前缀指的是 .属性 前面的那个单词就是前缀。 我们在使用@ConfigurationProperties注解的时候,指定的前缀就是 .属性前面的那个单词。
1.application.properties
server.port=8080 mycar.brand=BYD mycar.price=1200
2.进行配置绑定
package com.jsxs.bean; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Repository; /** * @Author Jsxs * @Date 2023/7/1 16:34 * @PackageName:com.jsxs.bean * @ClassName: Car * @Description: TODO 只会在IOC容器中的组件,才会拥有SprngBoot提供的强大功能 * @Version 1.0 */ @Data @Repository @AllArgsConstructor @NoArgsConstructor @ConfigurationProperties(prefix = "mycar") // 添加上前缀 public class Car { private String brand; private Integer price; }
3.注解的源码:
这里prefix与value互为别名
package org.springframework.boot.context.properties; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.core.annotation.AliasFor; @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ConfigurationProperties { @AliasFor("prefix") String value() default ""; @AliasFor("value") String prefix() default ""; boolean ignoreInvalidFields() default false; boolean ignoreUnknownFields() default true; }
4.controller进行测试
package com.jsxs.controller; import com.jsxs.bean.Car; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.ImportResource; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; /** * @Author Jsxs * @Date 2023/7/1 9:55 * @PackageName:com.jsxs.controller * @ClassName: IndexController * @Description: TODO * @Version 1.0 */ @RestController public class IndexController { @Resource Car car; @RequestMapping("/hello") public String hello(){ return "hello"; } @RequestMapping("/car") public Car car(){ return car; } }
(2).@EnableConfigurationProperties (第二种)
1. 前提条件 (1).实体类上可以不用加@Compont注入到IOC容器中 (2).实体类上需要指定配置绑定的前缀 @ConfigurationProperties(prefix = "mycar") // 添加上前缀 (3).@EnableConfigurationProperties(实体类.class) 需要放在任意IOC容器组件类上 2. @EnableConfigurationProperties(实体类.class) = 配置绑定 + @Component依赖注入 3.使用场景: 当我们引用第三方默认的配置时候,第三方在实体类上没有添加@Component注入到IOC容器的时候,我们需要使用第二种方式。
实体类
package com.jsxs.bean; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Repository; /** * @Author Jsxs * @Date 2023/7/1 16:34 * @PackageName:com.jsxs.bean * @ClassName: Car * @Description: TODO 只会在IOC容器中的组件,才会拥有SprngBoot提供的强大功能 * @Version 1.0 */ @Data //@Repository 这次把IOC容器组件给去掉 ⭐ @AllArgsConstructor @NoArgsConstructor @ConfigurationProperties(prefix = "mycar") // 添加上前缀 ⭐⭐ public class Car { private String brand; private Integer price; }
配置类上
package com.jsxs.config; import com.jsxs.bean.Car; import com.jsxs.bean.Pet; import com.jsxs.bean.User; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.*; /** * @Author Jsxs * @Date 2023/7/1 12:30 * @PackageName:com.config * @ClassName: MyConfig * @Description: TODO 1.配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实列的, * @Description: TODO 2.配置类(类名)本身也是一个组件,即在这个列子中有三个组件并不是俩个。 * @Description: TODO 3.@Configuration(proxyBeanMethods=true)代理bean,也就是无论外部调用多少次实列都是一样的即单列。否则不是单实列 * Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】 * Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】 * 组件依赖必须使用Full模式默认。其他默认是否Lite模式 * * @Version 1.0 */ @Import({User.class}) @Configuration(proxyBeanMethods=true) ⭐⭐⭐ // 告诉SpringBoot这是一个配置类,相当于以前的配置文件 beans.xml //@ConditionalOnMissingBean(name = "tom") // 当整个IOC容器中存在tom这个容器,我们就注册user01这个组件否则不注册 @ImportResource("classpath:beans.xml") @EnableConfigurationProperties(Car.class) ⭐⭐⭐⭐ // 1.开启配置绑定功能。 2.把Car这个属性自动注入到容器中 public class MyConfig { @Bean // 1. 这里相当于我们配置文件中的<bena></bean>标签 // 2. User对应的是我们配置文件的class非全限定名, user01对应我们配置文件的id public User user01() { // FULL模式人拥有宠物 return new User("李明",12,this.cat()); } @Bean("tom") // 相当于我们配置文件的bean标签 public Pet cat(){ // Pet指的是calss的非全限定名, cat指定的是id return new Pet("哈吉米"); } }
3.自动配置原理入门
3.1、引导加载自动配置类
@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication{} ======================
(1). @SpringBootConfiguration
- @Configuration。代表当前是一个配置类
(2). @ComponentScan
- 指定扫描哪些,Spring注解;
(3).@EnableAutoConfiguration
1.@EnableAutoConfiguration的合成
1.注解的合成: @EnableAutoConfiguration= @AutoConfigurationPackage + @Import(AutoConfigurationImportSelector.class) 2. @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration {}
(3.1).@AutoConfigurationPackage (自定义注入组件)
自动配置包?指定了默认的包规则 (即我们主启动类下的包)
@Import(AutoConfigurationPackages.Registrar.class) //给容器中导入一个组件 public @interface AutoConfigurationPackage {} //利用 Registrar 给容器中导入一系列组件 //将指定的一个包下的所有组件导入进来?MainApplication(主启动类) 所在包下。
- 我们点开Registar.class这个源代码发现里面存在两个方法
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { Registrar() { } public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { ⭐ AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0])); } public Set<Object> determineImports(AnnotationMetadata metadata) { return Collections.singleton(new AutoConfigurationPackages.PackageImports(metadata)); } }
在星星的位置打上断点,发现我们的元数据上的路径在主启动类上。
我们通过计算的到: 导入的是我们主启动类下所在的包中的组件。