官方网站面膜做代理,代理龙华网站建设,汉阳区建设局网站,数据做图网站有哪些文章目录 一、条件装配概述1.1 条件装配的基本原理1.2 条件装配的作用 二、常用注解2.1 ConditionalOnClass2.2 ConditionalOnBean2.3 ConditionalOnProperty2.4 ConditionalOnExpression2.5 ConditionalOnMissingBean 三、条件装配的实现原理四、实际案例 一、条件装配概述
1… 文章目录 一、条件装配概述1.1 条件装配的基本原理1.2 条件装配的作用 二、常用注解2.1 ConditionalOnClass2.2 ConditionalOnBean2.3 ConditionalOnProperty2.4 ConditionalOnExpression2.5 ConditionalOnMissingBean 三、条件装配的实现原理四、实际案例 一、条件装配概述
1.1 条件装配的基本原理 条件装配的基本原理是根据特定的条件来决定是否应用特定的配置或组件。在 Spring Boot 中条件装配是通过条件注解来实现的。 条件注解是一种特殊的注解用于标记在配置类、组件类或方法上。它们根据某些条件的结果来决定是否应用相应的配置或组件。
条件注解的基本原理
条件判断Spring 在处理配置类或组件时会对标记了条件注解的类或方法进行条件判断。条件匹配条件注解中定义的条件匹配器会根据特定的条件如类路径是否存在、Bean 是否存在、属性是否被设置等对环境进行判断如果条件满足则返回 true否则返回 false。条件注解处理器Spring 容器会使用条件注解处理器来处理条件注解根据条件匹配的结果来决定是否应用相应的配置或组件。应用配置或组件根据条件注解的处理结果Spring 容器会决定是否应用相应的配置或组件。如果条件满足则进行相应的配置或组件的注册和初始化如果条件不满足则忽略该配置或组件。
1.2 条件装配的作用 条件装配的作用在于根据特定的条件来决定是否应用特定的配置或组件从而实现灵活性和可配置性。 条件装配实现的作用
环境适配通过条件装配可以根据当前的运行环境如开发环境、测试环境、生产环境或者配置如不同的数据库、不同的服务提供商来动态地选择合适的配置或组件从而使应用程序适应不同的环境。可插拔性条件装配可以根据应用程序的需求动态地选择性地应用不同的配置或组件使得应用程序的功能可以根据需求进行扩展或者替换从而增强了应用程序的可插拔性和可扩展性。简化配置通过条件装配可以根据特定的条件自动地应用相应的配置或组件而无需手动配置或编写复杂的条件判断逻辑从而简化了配置过程提高了配置的易用性和可维护性。优化性能通过条件装配可以根据特定的条件选择性地应用相应的配置或组件避免不必要的资源消耗从而优化了应用程序的性能和资源利用率。
二、常用注解
2.1 ConditionalOnClass ConditionalOnClass 是 Spring Boot 中的一个条件注解用于在类路径中存在指定的类时才会应用相应的配置。 定义了一个灵活的条件注解 ConditionalOnClass它可以根据类路径中特定类的存在与否来决定是否应用相应的配置或组件。
示例和用法说明
/*** 只有当应用程序的类路径中存在 RedisTemplate 类时RedisConfiguration 类中定义的 redisTemplate() 方法才会被注册为 Bean并被 Spring 容器管理* 如果类路径中不存在 RedisTemplate 类则该配置类中的 Bean 将被忽略*/
Configuration
ConditionalOnClass({org.springframework.data.redis.core.RedisTemplate.class})
public class RedisConfiguration {Beanpublic RedisTemplateString, Object redisTemplate() {RedisTemplateString, Object redisTemplate new RedisTemplate();// 配置 RedisTemplate 的相关属性return redisTemplate;}
}2.2 ConditionalOnBean ConditionalOnBean 是 Spring Framework 中的一个条件注解它的作用是在容器中存在指定的 Bean 时才会应用相应的配置或组件。如果指定的 Bean 不存在则该配置或组件将被忽略。 定义了一个具有多个属性的注解 ConditionalOnBean可以用于指定条件判断所依赖的类、名称、注解等信息以及搜索依赖 Bean 的策略和泛型容器中的参数化类型。 示例和用法说明
基本用法
/*** MyService 类被标记为 ConditionalOnBean(MyBean.class)这意味着只有当容器中存在 MyBean 类型的 Bean 时MyService 才会被创建并添加到容器中*/
Configuration
public class MyConfiguration {Beanpublic MyBean myBean() {return new MyBean();}ConditionalOnBean(MyBean.class)Beanpublic MyService myService() {return new MyService();}
}多个 Bean 的情况
/*** MyService 类被标记为 ConditionalOnBean({MyBean.class, AnotherBean.class})这意味着只有当容器中同时存在 MyBean 和 AnotherBean 类型的 Bean 时MyService 才会被创建并添加到容器中*/
Configuration
public class MyConfiguration {Beanpublic MyBean myBean() {return new MyBean();}Beanpublic AnotherBean anotherBean() {return new AnotherBean();}ConditionalOnBean({MyBean.class, AnotherBean.class})Beanpublic MyService myService() {return new MyService();}
}使用名称来指定 Bean
/*** MyService 类被标记为 ConditionalOnBean(name {myBean, anotherBean})这意味着只有当容器中同时存在名称为 myBean 和 anotherBean 的 Bean 时MyService 才会被创建并添加到容器中*/
Configuration
public class MyConfiguration {Bean(name myBean)public MyBean myBean() {return new MyBean();}Bean(name anotherBean)public AnotherBean anotherBean() {return new AnotherBean();}ConditionalOnBean(name {myBean, anotherBean})Beanpublic MyService myService() {return new MyService();}
}2.3 ConditionalOnProperty ConditionalOnProperty 注解是 Spring Framework 中的条件注解之一用于基于配置属性的存在与否来决定是否应用某个配置。 定义了一个具有多个属性的注解 ConditionalOnProperty它可以用于根据配置文件中的属性值来决定是否应用某个配置。 示例和说明
/*** ConditionalOnProperty 注解指定了一个名为myapp.feature.enabled 的属性当这个属性存在并且其值为true时MyFeatureConfiguration 配置类中的配置会生效* havingValue 参数指定了期望的属性值如果没有指定havingValue则默认匹配任何非空值* matchIfMissing 参数指定了当配置文件中未设置该属性时是否应该匹配。如果设置为 true则表示当属性不存在时也匹配这样可以设置默认行为*/
Configuration
ConditionalOnProperty(name myapp.feature.enabled,havingValue true,matchIfMissing true
)
public class MyFeatureConfiguration {}myapp.feature.enabledtrue2.4 ConditionalOnExpression ConditionalOnExpression 是 Spring 框架中的一个条件注解在应用配置时根据 SpEL表达式的结果来决定是否进行配置。它允许我们使用更灵活的表达式来控制配置的条件。 定义了一个具有一个属性的注解 ConditionalOnExpression它可以根据 SpEL 表达式的结果来决定是否应用某个配置。 示例和说明
/*** 检查配置文件中的 my.config.enabled 属性是否等于 true* 如果等于 true则表达式结果为 trueMyBean 实例将会被创建* 否则表达式结果为 false配置将被忽略不会创建 MyBean 实例*/
Configuration
public class MyConfig {BeanConditionalOnExpression(#{environment.getProperty(my.config.enabled) true})public MyBean myBean() {// 配置生效时创建 MyBean 实例return new MyBean();}
}2.5 ConditionalOnMissingBean ConditionalOnMissingBean 是一个 Spring Boot 中常用的条件注解它的作用是当容器中不存在指定的 Bean 时才会进行配置。 定义了一个具有多个属性的注解 ConditionalOnMissingBean用于根据存在或缺少特定类型的 bean 来决定是否应用某个配置。 示例和说明
/*** 使用 ConditionalOnMissingBean 注解来判断容器中是否已经存在了 MyService 类型的 Bean* 如果不存在则创建一个 MyServiceImpl 实例并返回* 否则不进行任何操作。*/
Configuration
public class MyConfiguration {BeanConditionalOnMissingBean(MyService.class)public MyService myService() {return new MyServiceImpl();}
}三、条件装配的实现原理 条件装配的实现原理主要基于Spring的IoC容器和Conditional注解。 在Spring的IoC容器中BeanFactoryPostProcessor和BeanPostProcessor是两个核心的接口它们允许我们在bean的创建和配置过程中添加额外的逻辑。(想要了解源码读者可以查看我前面的博文) 条件装配的实现原理
Conditional注解这个注解可以标记在类、方法或注解上用于指定在特定的条件满足时才创建和配置bean。Conditional注解需要一个Class类型的参数这个参数需要实现Condition接口。Condition接口这是一个函数式接口它定义了一个matches(ConditionContext context, AnnotatedTypeMetadata metadata)方法。 这个方法返回一个boolean值表示条件是否满足。如果返回true则Spring容器会创建和配置相应的bean如果返回false则不会创建和配置。两个参数提供了关于Spring容器和当前正在评估的bean的元数据信息。 自动配置在Spring Boot中条件装配被广泛应用于自动配置。 Spring Boot会根据我们在pom.xml文件中引入的依赖自动配置相应的bean。这是通过一系列的AutoConfiguration类实现的这些类上通常会使用ConditionalOnClass、ConditionalOnMissingBean等注解来指定条件。
四、实际案例 假设正在开发一个在线商城的 Spring Boot 应用程序其中包含了用户管理和订单管理两个模块。现在希望在用户注册时发送一封欢迎邮件但是如果用户已经在系统中存在则不发送邮件。 ps使用条件注解 ConditionalOnMissingBean 来实现这一定制化功能。 创建一个邮件服务接口 EmailService 和实现类 WelcomeEmailService。
/*** 邮件服务接口*/
public interface EmailService {void sendWelcomeEmail(String email);
}/*** 发送欢迎邮件*/
Service
public class EmailServiceImpl implements EmailService {Overridepublic void sendWelcomeEmail(String email) {// 发送欢迎邮件的逻辑System.out.println(Sending welcome email to: email);}
}
创建一个用户服务类 UserService在用户注册时调用邮件服务发送欢迎邮件。
public interface UserService {public void registerUser(String email);
}/*** 在用户注册时检查是否已经存在该用户如果不存在则发送欢迎邮件*/
Service
public class UserServiceImpl implements UserService {private final UserMapper userMapper;private final EmailService emailService;Autowiredpublic UserServiceImpl(UserMapper userMapper, EmailService emailService) {this.userMapper userMapper;this.emailService emailService;}Overridepublic void registerUser(String email) {if(!userMapper.existsByEmail(email)) {userMapper.save(email);emailService.sendWelcomeEmail(email);}else {throw new IllegalArgumentException(Email already exists);}}
}
创建一个 UserRepository实现它使用HashSet来模拟存储用户信息。
/*** 不想使用数据库直接使用HashSet来模拟存储用户信息的email* 使用一个HashSet来存储注册过的emailHashSet不允许存储重复的元素* author LEK*/
Repository
public class UserMapper {private final SetString registeredEmails new HashSet();public boolean existsByEmail(String email) {return registeredEmails.contains(email);}public void save(String email) {if (Objects.nonNull(email) !email.isEmpty()) {registeredEmails.add(email);}}
}
使用 ConditionalOnMissingBean 注解来确保只有在容器中不存在 EmailService 的实现类时才会注入 WelcomeEmailService。这样如果用户在系统中已经存在就不会发送欢迎邮件。
Configuration
public class EmailConfig {/*** 邮件配置* */BeanConditionalOnMissingBean(EmailService.class)public EmailServiceImpl email() {return new EmailServiceImpl();}
}
新建UserServiceImplTest测试类由于是使用HashSet来模拟运行每次启动都是不存在的然后手动一下。
SpringBootTest
public class UserServiceImplTest {Autowiredprivate UserService userService;Testpublic void testRegisterExistingUser() {String existingEmail existingexample.com;userService.registerUser(existingEmail);// 注册已存在的用户预期会抛出 IllegalArgumentExceptionuserService.registerUser(existingEmail);}
}
运行效果。 哪儿有勤奋哪儿就有成功