导入:
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
*/
@Override
public 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
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//需求2:导入通过注解属性值value指定坐标后创建bean
//获取注解属性值 value
Map<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坐标测试。