文章目录
参考资料
运行环境
- win10
- IDEA专业版
- SpringBoot 2.6.2
SpringBoot 自动配置原理
一、Condition
Condition 是在 Spring 4.0 增加的条件判断功能,作用是实现选择性的创建Bean操作
思考:
SpringBoot是如何知道要创建哪个 Bean的?比如SpringBoot是如何知道要创建 RedisTemplate的?
需求:
在Spring的IOC容器中有一个User的Bean,现要求
0x001 导入 Jedis 坐标后,加载该Bean,没导入则不加载
测试的项目结构
User.java
package com.uni.springbootcondition.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private int id;
private String username;
private String password;
}
ClassCondition.java
package com.uni.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 {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 需求:导入Jedis坐标后创建Bean
// 思路:判断Redis.clients.jedis.Jedis.class文件是否存在
boolean flag = true;
try {
Class<?> cls = Class.forName("redis.clients.jedis.Jedis");
} catch (ClassNotFoundException e) {
e.printStackTrace();
flag = false;
}
return flag;
}
}
UserConfig.java
package com.uni.springbootcondition.config;
import com.uni.springbootcondition.condition.ClassCondition;
import com.uni.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();
}
}
SpringbootConditionApplication.java
package com.uni.springbootcondition;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
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);
}
}
0x010 将类的判断定义为动态的。判断哪个字节码文件存在可以动态指定。
项目结构:
ClassCondition.java
package com.uni.springbootcondition.condition;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import java.util.Map;
public class ClassCondition implements Condition {
/**
* @param context 上下文对象。 用于获取环境, IOC容器,ClassLoader对象
* @param metadata 注解元对象。 可以用于获取注解定义的属性值
* @return
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 需求:导入通过注解属性值value指定坐标后创建Bean
// 思路:获取注解属性值
Map<String, Object> map = metadata.getAnnotationAttributes(ConditionOnClass.class.getName());
String[] value = (String[])map.get("value");
boolean flag = true;
try {
for (String className : value) {
Class<?> cls = Class.forName(className);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
flag = false;
}
return flag;
}
}
ConditionOnClass.java
package com.uni.springbootcondition.condition;
import org.springframework.context.annotation.Conditional;
import java.lang.annotation.*;
@Target({
ElementType.TYPE, ElementType.