springboot学习之五(自动配置)
一、@Conditional源码
springboot的自动配置是通过@Conditional注解(条件判断)实现的.
@Conditional是Spring4版本新提供的一种注解,它的作用是按照设定的条件进行判断,把满足判断条件的bean注册到Spring容器。
package org.springframework.context.annotation; 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; @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Conditional { Class<? extends Condition>[] value(); }
@Conditional
只有一个参数,并且这个参数要求是继承与Condition
类,并且参数是个数组,也就是可以 传多个的。
Condition
类是一个函数式接口(只有一个方法的接口被称为函数式接口)。matches
方法就是比较方法,如果为true
则注入,如果为false
则不注入。
@FunctionalInterface public interface Condition { boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata); }
二、@Conditional扩展注解
而除了@Conditional注解外,springboot通过@Conditional注解又扩展了很多注解出来,如下@ConditionalOnBean、@ConditionalOnClass等等…
三、@Conditional实战
需求:在spring的IOC容器中有一个User的Bean,先要求
1.导入Jedis坐标后,加载该Bean,没导入,则不加载。
2.将坐标类的判断设置成动态的,可以把Jedis随时当做参数替换成其他坐标。
------类似于ConditionalOnClass注解----
只要加了@Conditional注解,这个注解回传一个实现了Condition接口的实现类,这个类里面覆写一个matches方法返回值决定是否执行.
步骤:
1.写一个自己的注解@Mycondition,加上@Conditional注解,
@Target({ElementType.TYPE,ElementType.METHOD}) @Retention( RetentionPolicy.RUNTIME) @Documented @Conditional(MyAnnoCondition.class) public @interface Mycondition { public String [] name() default ""; } //这样有@Contitional的条件判断,也可以携带自己的属性name[]
2.加的@Conditional注解要实现Condition接口的实现类MyAnnoCondition
public class MyAnnoCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { //context:上下文对象,可以获取环境,IOC容器,classLoader对象 //metadata:注解元对象,可以获取注解定义的属性值 //1.获取注解属性值 Map<String, Object> map = metadata.getAnnotationAttributes(Mycondition.class.getName()); //System.out.println(map); String[] name = (String[]) map.get("name"); boolean flag = true; for (String className : name){ try { Class<?> cls = Class.forName(className); } catch (ClassNotFoundException e) { e.printStackTrace(); flag = false; } } return flag; } }
3.写一个User的实体类
@Data @AllArgsConstructor @NoArgsConstructor public class User { private int id; private String name; }
4.把User实体类以注解配置@Configuration形式交由IOC容器管理
@Configuration public class TestConfig { @Bean @Mycondition( name = "redis.clients.jedis.Jedis" ) public User user(){ System.out.println("User"); return new User(); } }
5.现在就实验,pom.xml有无 jedis 坐标,来判断user是否被容器创建
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency>
springboot 启动main()方法
@SpringBootApplication public class SpringbootRedisApplication { public static void main(String[] args) { ConfigurableApplicationContext applicationContext = SpringApplication.run(SpringbootRedisApplication.class, args); User user = (User) applicationContext.getBean("user"); System.out.println(user); } }
创建或不创建User,取决于Jedis坐标是否导入.
转 :https://blog.csdn.net/weixin_43888891/article/details/127503336
https://blog.csdn.net/baidu_37107022/article/details/88878703/
https://www.cnblogs.com/kaituorensheng/p/8024199.html