导入:
SpringBoot是如何知道要创建哪个Bean的?比如Spring Boot是如何知道要创建RedisTemplate的?
Condition:
Condition是在Spring4.0增加的条件判断功能,通过这个可以实现选择性的创建Bean操作。
- 自定义条件:
① 定义条件类:自定义类实现Condition接口,重写 matches 方法,在 matches 方法中进行逻辑判断,返回 boolean值 。 matches 方法两个参数:
• context:上下文对象,可以获取属性值,获取类加载器,获取BeanFactory等。
• metadata:元数据对象,用于获取注解属性。
② 判断条件: 在初始化Bean时,使用 @Conditional ( 条件类 . class ) 注解
- SpringBoot 提供的常用条件注解:
• ConditionalOnProperty : 判断配置文件中是否有对应属性和值才初始化Bean
• ConditionalOnClass : 判断环境中是否有对应字节码文件才初始化Bean
• ConditionalOnMissingBean : 判断环境中没有对应Bean才初始化Bean
创建模块:
需求一:
在Spring的IOC容器中有一个User的Bean,现要求:
导入Jedis坐标后,加载该Bean,没导入,则不加载。
新建domain软件包,User 类:
package com.itheima.springbootcondition.domain;public class User {
}
新建config软件包,UserConfig 类:
package com.itheima.springbootcondition.config;import com.itheima.springbootcondition.condition.ClassCondition;
import com.itheima.springbootcondition.domain.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;@Configuration
public class UserConfig {@Bean@Conditional(ClassCondition.class)public User user(){return new User();}
}
新建condition软件包:ClassCondition类:
package com.itheima.springbootcondition.condition;import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;public class ClassCondition implements Condition {/**** @param context 上下文对象。用于获取环境,ioc容器,classloader对象* @param metadata 注解元对象。用于获取注解定义的属性值。* @return*/@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {//需求1: 导入Jedis坐标后,加载该Bean,没导入,则不加载。try {Class<?> cls = Class.forName("redis.clients.jedis.Jedis");} catch (ClassNotFoundException e) {e.printStackTrace();return false;}return true;}
}
SpringbootConditionApplication类:
package com.itheima.springbootcondition;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplication
public class SpringbootConditionApplication {public static void main(String[] args) {//启动springboot的应用,返回spring的ioc容器ConfigurableApplicationContext context = SpringApplication.run(SpringbootConditionApplication.class, args);Object user = context.getBean("user");System.out.println(user);}}
在pom文件里增删jedis坐标测试:
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId>
</dependency>
需求二:
在 Spring 的 IOC 容器中有一个 User 的 Bean,现要求:
将类的判断定义为动态的。判断哪个字节码文件存在可以动态指定。
在condition包下,新建注解ConditionOnClass :
package com.itheima.springbootcondition.condition;import org.springframework.context.annotation.Conditional;import java.lang.annotation.*;@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ClassCondition.class)
public @interface ConditionOnClass {String[] value();
}
ClassCondition 类:
package com.itheima.springbootcondition.condition;import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;import java.util.Iterator;
import java.util.Map;public class ClassCondition implements Condition {/**** @param context 上下文对象。用于获取环境,ioc容器,classloader对象* @param metadata 注解元对象。用于获取注解定义的属性值。* @return*/@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {//需求2:导入通过注解属性值value指定坐标后创建bean//获取注解属性值 valueMap<String, Object> map = metadata.getAnnotationAttributes(ConditionOnClass.class.getName());
// System.out.println(map);String[] value = (String[]) map.get("value");try {for (String classname : value) {Class<?> cls = Class.forName(classname);}} catch (ClassNotFoundException e) {e.printStackTrace();return false;}return true;}
}
UserConfig 类:
package com.itheima.springbootcondition.config;import com.itheima.springbootcondition.condition.ClassCondition;
import com.itheima.springbootcondition.condition.ConditionOnClass;
import com.itheima.springbootcondition.domain.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;@Configuration
public class UserConfig {@Bean
// @Conditional(ClassCondition.class)@ConditionOnClass("redis.clients.jedis.Jedis")public User user(){return new User();}
}
在pom文件里增删jedis坐标测试。