@SpringBootApplication
1,Spring Boot 应用启动,@SpringBootApplication标注的类就是启动类,它去实现配置类中的Bean的自动装配
@SpringBootApplication
public class SpringbootRedis01Application {
public static void main(String[] args) {
SpringApplication.run(SpringbootRedis01Application.class, args);
}
}
2,而@SpringBootApplicatiozn注解中包含了三个注解:
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
//以上四个都为元注解,以下三个才是去实现自动装配的注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
@SpringBootConfiguration
这个注解包含了@Configuration,@Configuration里面又包含了一个@Component注解,也就是
说,这个注解标注在哪个类上,就表示当前这个类是一个配置类,而配置类也是spring容器中的组
件,
@SpringBootConfiguration:对@Configuration 注解的封装,标注当前类是配置类,并会将当前类内声明的一个或多个以@Bean注解标记的方法的实例纳入到spring容器中。
@EnableAutoConfiguration
这个注解是开启自动配置的功能核心注解,里面包含了两个注解
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
@AutoConfigurationPackage:
将主启动类的所在包及包下面所有子包里面的所有组件扫描到Spring容器,这也就是为什么我们在利用springboot进行开发的时候,无论是Controller还是Service的路径都是与主配置类同级或者次级的原因。
@Import(AutoConfigurationImportSelector.class)
上一个注解我们把所有组件都加载到了容器里面,这个注解就是将需要自动装配的类以全类名的方
式返回
1、AutoConfigurationImportSelector这个类里面有一个方法selectImports(),如下
2、在selectImport()方法里调用了一个getAutoConfigurationEntry()方法,这个方法里面又调用
了一个getCandidateConfigurations()方法
3、在getCandidateConfigurations()方法里面调用了loadFactoryNames()方法、
4、loadFactoryNames()方法里面又调用了一个loadSpringFactories()方法
5、关键就在这个loadSpringFactories()方法里面,在这个方法里,它会查找所有在META-INF路
6、在META-INF/spring.factories这个文件里面的数据是以键=值的方式存储,然后解析这些文
件,找出以EnableAutoConfiguration为键的所有值,以列表的方式返回
@ComponentScan
这个注解的作用就是扫描当前包及子包的注解
@Condition注解就是在自动装配的时候如果这个类中有此注解而且满足其定义的逻辑,是否要注入容器。
定义自己的条件类,实现Condition口重写match方法
public class ClassCondition implements Condition {
//条件为是否导入相应坐标而且是单个条件
// @Override
// public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// boolean flag=true;
// try {
// Class<?> clas= Class.forName("redis.clients.jedis.Jedis");
// } catch (ClassNotFoundException e) {
//
// flag=false;
// }
//
// return flag;
// }
//条件为是否导入相应坐标而且是多个条件
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
boolean flag=true;
Map<String, Object> map = metadata.getAnnotationAttributes(ConditionOnClasss.class.getName());
String[] value = (String[]) map.get("value");
try {
for(String className :value) {
Class<?> clas = Class.forName(className);
}
} catch (ClassNotFoundException e) {
flag=false;
}
return flag;
}
}
定义配置类:@Condition(value属性指的就是条件类)
@Configuration
public class UserConfig {
@Bean
// @Conditional(value = ClassCondition.class)
@ConditionOnClasss(value={"com.alibaba.fastjson.JSON","redis.clients.jedis.Jedis"})
public Hotel hotel(){
return new Hotel();
}
@Bean
// @Conditional(value = ClassCondition.class)
// @ConditionOnClasss(value={"com.alibaba.fastjson.JSON","redis.clients.jedis.Jedis"})
@ConditionalOnProperty(value = "k1",havingValue = "k2")
public Hotel hotel2(){
return new Hotel();
}
}
Condition – 小结
自定义条件:
① 定义条件类:自定义类实现Condition接口,重写 matches 方法,在 matches 方法中进行逻辑判 断,返回 boolean值 。
matches 方法两个参数:
• context:上下文对象,可以获取属性值,获取类加载器,获取BeanFactory等。
• metadata:元数据对象,用于获取注解属性。
② 判断条件: 在初始化Bean时,使用 @Conditional(条件类.class)注解
SpringBoot 提供的常用条件注解:
以下注解在springBoot-autoconfigure的condition包下 :
ConditionalOnProperty:判断配置文件中是否有对应属性和值才初始化
Bean ConditionalOnClass:判断环境中是否有对应字节码文件才初始化Bean ConditionalOnMissingBean:判断环境中没有对应Bean才初始化Bean
ConditionalOnBean:判断环境中有对应Bean才初始化Bean 可以查看RedisAutoConfiguration类说明以上注解使用 距离演示ConditionalOnProperty