springboot注解原理学习
1. @Configuration与@Bean注解
@Configuration(proxyBeanMethods = false) 告诉SpringBoot这是一个配置类 == 配置文件
@Bean 给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
-
使用示例
#############################Configuration使用示例###################################################### /** * 1、配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的 * 2、配置类本身也是组件 * 3、proxyBeanMethods:代理bean的方法 * Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】 * Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】 * 组件依赖必须使用Full模式默认。其他默认是否Lite模式 */ @Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件 public class MyConfig { /** * Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象 * @return */ @Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例 public User user01(){ User zhangsan = new User("zhangsan", 18); //user组件依赖了Pet组件 zhangsan.setPet(tomcatPet()); return zhangsan; } @Bean("tom") public Pet tomcatPet(){ return new Pet("tomcat"); } }
-
重点: @Configuration表示是配置文件可以配置文件中通过@Bean向容器中注册组件
-
@Configuration注解中有@Component注解 表示通过@ComponentScan扫描也能成为容器中的组件 也表示加上这个注解的类也是容器的组件
-
2. @ComponentScan注解与@Component、@Controller、@Service、@Repository @Configuration
@ComponentScan注解扫描@Component @Controller @Service @Repository @Configuration才能将组件注册到容器中
如果扫描不到就不能将组件注册到容器中
-
@ComponentScan:扫描组件在注册到容器中
-
@ComponentScan(“com.xian.springboot”):可以指定扫描指定包下组件
-
@ComponentScan(“com.xian.springboot”)一般与@Configuration使用
-
测试:
如果包指定在com.xian.springboot.entity容器就没有这些组件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-88nFUDVq-1652441782396)(C:\Users\19845\AppData\Roaming\Typora\typora-user-images\image-20220513163119040.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jS9EgUpq-1652441782397)(C:\Users\19845\AppData\Roaming\Typora\typora-user-images\image-20220513163202611.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-92Fw5LxF-1652441782398)(C:\Users\19845\AppData\Roaming\Typora\typora-user-images\image-20220513163215098.png)]
-
重点: @ComponentScan注解扫描@Component @Controller @Service @Repository @Configuration才能将组件注册到容器中 如果扫描不到就不能将组件注册到容器中
-
@Configuration也需要扫描不然也注册不到容器
3.@Import
- @Import({User.class, DBHelper.class})
- 给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名
-
给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名
-
测试:
通过属性在容器获取存在的组件名字
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WzygFFSp-1652441782399)(C:\Users\19845\AppData\Roaming\Typora\typora-user-images\image-20220513164852813.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xUJczU5q-1652441782399)(C:\Users\19845\AppData\Roaming\Typora\typora-user-images\image-20220513164828831.png)]‘
4.@Conditional
条件装配:满足Conditional指定的条件,则进行组件注入
@ConditionalOnBean(name = “tom”) 存在名为tom的组件才执行
@ConditionalOnMissingBean(name = “tom”) 没有tom组件才执行
=====================测试条件装配==========================
@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
//@ConditionalOnBean(name = "tom")
@ConditionalOnMissingBean(name = "tom")
public class MyConfig {
/**
* Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
* @return
*/
@Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
public User user01(){
User zhangsan = new User("zhangsan", 18);
//user组件依赖了Pet组件
zhangsan.setPet(tomcatPet());
return zhangsan;
}
@Bean("tom22")
public Pet tomcatPet(){
return new Pet("tomcat");
}
}
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);
}
boolean tom = run.containsBean("tom");
System.out.println("容器中Tom组件:"+tom);
boolean user01 = run.containsBean("user01");
System.out.println("容器中user01组件:"+user01);
boolean tom22 = run.containsBean("tom22");
System.out.println("容器中tom22组件:"+tom22);
}
5.配置绑定 @ConfigurationProperties @EnableConfigurationProperties
重点:只有在容器中的组件,才会拥有SpringBoot提供的强大功能
@ConfigurationProperties 与@Component配合使用可以读取配置文件中的内容
@EnableConfigurationProperties与@ConfigurationProperties @Configuration使用可以读取配置文件中的内容
也不用在@ConfigurationProperties注解下加入@Component就可使用
-
@ConfigurationProperties 与@Component配合使用可以读取配置文件中的内容
-
1.读取配置的类
@Component @ConfigurationProperties(prefix = "car")//没有标记组件的注解 //只有在容器中的组件,才会拥有SpringBoot提供的强大功能 public class Car { private String name; private String age; public Car() { } public Car(String name, String age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } @Override public String toString() { return "Car{" + "name='" + name + '\'' + ", age='" + age + '\'' + '}'; } }
2.application.properties
car.name="小米" car.age=19
3.caontroller
@RestController("myController") public class MyController { @Autowired Car car; @GetMapping("/car") public Car car(){ return car; } }
-
测试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1tmIjYIQ-1652441782400)(C:\Users\19845\AppData\Roaming\Typora\typora-user-images\image-20220513173010336.png)]
6.在容器的组件都是被实例化的对象 所以可以通过@Autowired @Resource 注入
7.重点 @EnableAutoConfiguration
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
1、@AutoConfigurationPackage
自动配置包 指定了默认的包规则
@Import(AutoConfigurationPackages.Registrar.class) //给容器中导入一个组件
public @interface AutoConfigurationPackage {}
//利用Registrar给容器中导入一系列组件
//将指定的一个包下的所有组件导入进来?MainApplication 所在包下。
2、@Import(AutoConfigurationImportSelector.class)
1、利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件
2、调用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类
3、利用工厂加载 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);得到所有的组件
4、从META-INF/spring.factories位置来加载一个文件。
默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件
spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories
-
SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先
-
@Bean @ConditionalOnMissingBean public CharacterEncodingFilter characterEncodingFilter() { }
3.总结
-
SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
-
每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定
-
生效的配置类就会给容器中装配很多组件
-
只要容器中有这些组件,相当于这些功能就有了
-
定制化配置
-
- 用户直接自己@Bean替换底层的组件
- 用户去看这个组件是获取的配置文件什么值就去修改。
xxxxxAutoConfiguration —> 组件 —> xxxxProperties里面拿值 ----> application.properties
4. Profile功能
为了方便多环境适配,springboot简化了profile功能。
1、application-profile功能
-
默认配置文件 application.yaml;任何时候都会加载
-
指定环境配置文件 application-{env}.yaml
-
激活指定环境
-
- 配置文件激活
- 命令行激活:java -jar xxx.jar –spring.profiles.active=prod --person.name=haha
-
-
- 修改配置文件的任意值,命令行优先
-
-
默认配置与环境配置同时生效
-
同名配置项,profile配置优先
-
测试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BBxnLNLE-1652441782400)(C:\Users\19845\AppData\Roaming\Typora\typora-user-images\image-20220513192844812.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-REKjqvTM-1652441782400)(C:\Users\19845\AppData\Roaming\Typora\typora-user-images\image-20220513192929740.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K0ZIMIYB-1652441782401)(C:\Users\19845\AppData\Roaming\Typora\typora-user-images\image-20220513192901716.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-goKsdrYu-1652441782401)(C:\Users\19845\AppData\Roaming\Typora\typora-user-images\image-20220513192823621.png)]