admin管理员组文章数量:1599541
Springboot Condition 详解
-
Condition 是spring boot 4.0增加的功能,它可以选择性的创建bean
-
@Conditional 源码查看
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
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源码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.context.annotation;
import org.springframework.core.type.AnnotatedTypeMetadata;
@FunctionalInterface
public interface Condition {
/**
* 方法参数说明:
* ConditionContext: 上下文对象:可以用户获取classloader,ioc容器,环境
* AnnotatedTypeMetadata: 注解元对象:可以获取注解定义的属性值
**/
boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}
Condition接口提供了一个方法matches,当返回true时条件成立,创建对应的类。返回false反之
使用时,用户实现Condition接口,加入用户自己的判断逻辑,选择性的创建对应的been。
示例
-
创建一个spring boot 工程
Application类
package com.lab;
import com.lab.pojo.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
* springboot启动类
*
* @author 杨秋颐 wyuyangqy@163
* @since 2021-12-14 14:49
*/
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
User user = (User)context.getBean("user");
System.out.println("user = " + user);
}
}
-
用户实体类 略
-
用户配置类
package com.lab.config;
import com.lab.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 用户配置类
*
* @author 杨秋颐 wyuyangqy@163
* @since 2021-12-14 14:55
*/
@Configuration
public class UserConfig {
@Bean
public User user(){
return new User();
}
}
- 启动springboot 可见控制台是可以输出用户,也就是用户类spring已经给我们创建了
添加Condition
- 修改 用户配置类
package com.lab.config;
import com.lab.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
/**
* 用户配置类
*
* @author 杨秋颐 wyuyangqy@163
* @since 2021-12-14 14:55
*/
@Configuration
public class UserConfig {
@Bean
@Conditional(UserCondition.class) //添加Conditional注解 UserCondition见下面代码
public User user(){
return new User();
}
}
- UserCondition代码,由刚才的源码查看可知道,我们需要去实现Condition接口,并重写matches方法
package com.lab.config;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* 创建用户的条件
*
* @author 杨秋颐 wyuyangqy@163
* @since 2021-12-14 15:06
*/
public class UserCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//todo 用户自己的判断逻辑
//默认返回 false,则不创建user
return false;
}
}
- 启动springboot 可见控制台报错,在ioc容器中没找到相应名为"user"的bean
需求当引入了fastjson时,创建user
- 修改UserCondition类
package com.lab.config;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* 创建用户的条件
*
* @author 杨秋颐 wyuyangqy@163
* @since 2021-12-14 15:06
*/
public class UserCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
// 当引入了fastjson 刚创建user
try {
Class<?> aClass = Class.forName("com.alibaba.fastjson.JSON");
return true;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return false;
}
}
}
-
启动springboot 可见控制台报错,在ioc容器中没找到相应名为"user"的bean
-
在maven中引入 fastjson
<!-- https://mvnrepository/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.78</version> </dependency>
-
启动springboot 可见控制台是可以输出用户,也就是用户类spring已经给我们创建了
需求二,将上面需求改为判断任意类名
- 分析:任意类名可以用我们自定义的注解传到matches,由matches的入参:AnnotatedTypeMetadata 获取
实现
- 定义我们自己的注解
package com.lab.anno;
import com.lab.config.UserCondition;
import org.springframework.context.annotation.Conditional;
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
//继承之前定义的
@Conditional(UserCondition.class)
public @interface UserConditionOnClasses {
String[] value();
}
- 修改UserCondition 通过annotatedTypeMetadata 获取注解传进来的className
package com.lab.config;
import com.lab.anno.UserConditionOnClasses;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import java.util.Map;
/**
* 创建用户的条件
*
* @author 杨秋颐 wyuyangqy@163
* @since 2021-12-14 15:06
*/
public class UserCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//获取传入的注解中的属性
Map<String, Object> map = annotatedTypeMetadata.getAnnotationAttributes(UserConditionOnClasses.class.getName());
//获取@UserConditionOnClasses 中的value属性。我们定义的是 String[] 类型
String[] value = (String[]) map.get("value");
// 当引入了fastjson 刚创建user
try {
for (String className : value) {
//"com.alibaba.fastjson.JSON"
Class<?> aClass = Class.forName(className);
}
return true;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return false;
}
}
}
- 修改userConfig,使用我们定义的注解传入class的信息
package com.lab.config;
import com.lab.anno.UserConditionOnClasses;
import com.lab.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
/**
* 用户配置类
*
* @author 杨秋颐 wyuyangqy@163
* @since 2021-12-14 14:55
*/
@Configuration
public class UserConfig {
@Bean
@UserConditionOnClasses("com.alibaba.fastjson.JSON")
public User user(){
return new User();
}
}
- 启动springboot 可见控制台是可以输出用户,也就是用户类spring已经给我们创建了
查看Springboot 给我们提供的Condition注解
- 在spring-boot-autoconfigure下的condition包中
注解名 | 备注 |
---|---|
ConditionalOnBean | 当存在某对象时成立 |
ConditionalOnClass | 当存在某字节码时成立 |
ConditionalOnMissingBean | 当不存在某对象时成立 |
ConditionalOnProperty | 当存在某配置properties值时成立 |
查看Starter包的工作原理
-
查看与condition相同目录下的data->redis
-
RedisAutoConfiguration
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.boot.autoconfigure.data.redis;
import java.net.UnknownHostException;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
@Configuration
@ConditionalOnClass({RedisOperations.class})
@EnableConfigurationProperties({RedisProperties.class})
@Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
public class RedisAutoConfiguration {
public RedisAutoConfiguration() {
}
@Bean
//当ioc容器中不存在 redisTemplate 名字的bean时,创建
@ConditionalOnMissingBean(
name = {"redisTemplate"}
)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
本文标签: 详解SpringBootcondition
版权声明:本文标题:Springboot Condition 详解 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dianzi/1728321298a1153855.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论