SpringBoot(二)
springboot 原理
ⅤⅠⅠ auto config
1.1 Condition: 选择性的创建bean
注入一个Bean:@Configuration Class 下
@Bean 方法返回一个User,就获得name = "user"的Bean
@Conditional(实现类.class) => 决定Spring是否创建这个Bean
【需求1】导入Jedis坐标后才能创建Bean,否则失败
Condition实现类:
@Override 方法中:
boolean flag = true;
try{
Class<?> cls = Class.forName("redis.clients.jedis.Jedis");
}catch{
flag = false;
}
return flag; // 必须返回true才会创建这个class
【实验】导入Jedis dependency,测试成功;否则失败
【需求2】判断有动态坐标才能创建Bean
@Bean
@自定义Condition注解("任意坐标")
方法返回一个User
创建自定义注解=> 加上 @Conditional(实现类.class)、元注解
加上attr String[] value() 接受注解传参
=> 这样param传递到metadata里的map里,"value":[...]
=> 到Condition实现类中获取metadata.getAnnotationAttributes拿到Map
---
@ConditionalOnProperty(name = "A", havingValue = "B")
在配置文件中有key为A,值为B的时候...
Condition小结:
切换内置web服务器
内置tomcat,可以有4种切换
切换:pom中exclude tomcat依赖,加入jetty依赖,(可以使用右键diagrams操作)
@Enable* 动态启用功能,使用@Import注入配置,动态加载Bean
【思考】springboot是否可以直接获取jar包中定义的Bean
不能!因为@ComponentScan扫描范围:当前Boot class所在包和子包
【解决】
1. @ComponentScan("指定包")
2.@Import(类.class) 这些类都会被创建,加入IOC容器
3.封装@Import:
自定义注解类:3个元注解+ @Import(类.class)
@自定义注解类
@Import用途
1. 导入Bean
@Import(User.class)
获得对象:User user = context.getBean(User.class);
获得name:context.getBeansOfType(User.class)
2. 导入配置类
@Import(UserConfig.class)获取UserConfig中定义的Bean
UserConfig has @Configuration[这种情况可以不加] @Bean
3. 导入ImportSelector实现类,用于加载配置文件中的类:@Import(ImportSelector实现类.class)
@Override selectImports方法,返回加上User和Role全路径
4. 导入ImportBeanDefinitionRegistrar实现类,注册进入IOC容器
@Override registerBeanOfDefinitions
使用BeanDefinitionBuilder建立User的definition
=> registry.registerBeanOfDefinitions("beanName",definition)
@EnableAutoConfiguration
内部使用@Import(AutoConfigurationImportSelector.class)加载配置类
配置文件位置:META-INF/spring.factories 定义了大量初始化应该加载的配置类,初始化Bean
只有满足condition的Bean会被初始化
【需求】自定义redis-starter,导入redis坐标时,自动创建Jedis Bean
redis-autoconfigure模块:引入Jedis坐标,
创建Properties类:@ConfigurationProperties(prefix = "redis") // 识别配置中redis开头的
attr: host;port;
创建RedisAutoConfiguration类:
@Configuration @EnableConfigurationProperties(Properties.class)
可以加@ConditionalOnClass(Jedis.class)
@Bean
@ConditionalOnMissingBean(name="jedis") // 当没有jedis name Bean的时候会被加载
param:Properties; return Jedis(host,port)
resources下创建META-INF/spring.factories: autoconfig全路径替换成RedisAutoConfig
redis-starter模块:引入redis-autoconfigure坐标
那么测试模块test中引入redis-starter坐标就行
test模块的application.properties定义redis.host=6666, 就会被读取到,初始化Jedis就会失败
or 直接@Bean 返回一个Jedis,此时@ConditionalOnMissingBean会生效,不加载redis-autoconfigure模块中的Bean
ⅤⅠⅠⅠ 监听机制
是对Java事件监听的封装
1. event
2. source
3. listener
META/INF/spring.factories 在运行时一定会执行到
ApplicationContextInitializer
// 让自己impl的这个生效可以在META/INF/spring.factories里面写KV
SpringApplicationRunListener
CommandLineRunner
ApplicationRunner // 项目启动后。可用来预热缓存
program args => 进入入口时传递的参数
SpringBoot启动流程分析
---
java -jar 启动是在用内置的tomcat
war包是要部署到外部的tomcat里