condition

package
v0.0.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 2, 2026 License: MIT Imports: 7 Imported by: 0

README

condition 包 — 条件装配

所属层级: Core Layer
设计理念: 按需加载,条件驱动
设计灵感: Spring Boot @Conditional

概述

condition 包提供条件装配能力,允许根据配置、类路径、自定义条件等动态决定是否注册 Bean 或执行自动配置。支持条件组合(AND/OR/NOT)、自定义条件、条件验证等特性。

核心功能
功能 说明
内置条件 OnProperty、OnClass、OnBean、OnMissingBean、OnProfile 等
条件组合 All(AND)、Any(OR)、Not(NOT)逻辑组合
自定义条件 实现 Condition 接口定义业务条件
表达式条件 SpEL 风格表达式,支持占位符和运算
资源条件 检查类路径、文件、环境变量等资源存在性

核心接口

Condition 接口
type Condition interface {
    Matches(ctx ConditionContext) bool  // 判断条件是否匹配
    String() string                     // 条件描述(用于日志和调试)
}
ConditionContext 接口
type ConditionContext interface {
    Environment() interface{ GetProperty(key string) (any, bool) }
    Container() interface{ Has(id string) bool }
    ClassLoader() interface{ HasClass(name string) bool }
    GetBean(beanID string) (any, bool)
    HasProperty(key string) bool
    GetProperty(key string) (any, bool)
}

快速开始

在自动配置中使用条件
func init() {
    boot.RegisterAutoConfig(
        &GinAutoConfiguration{},
        condition.OnProperty("gin.enabled", "true"),     // 属性条件
        condition.OnClass("github.com/gin-gonic/gin"),   // 类路径条件
    )
}
在启动器中使用条件
type MyStarter struct{}

func (s *MyStarter) Name() string { return "my-starter" }
func (s *MyStarter) Dependencies() []string { return nil }
func (s *MyStarter) Configure(ctx boot.ApplicationContext) error { return nil }
func (s *MyStarter) Start(ctx boot.ApplicationContext) error { return nil }
func (s *MyStarter) Stop(ctx boot.ApplicationContext) error { return nil }

func (s *MyStarter) GetCondition() condition.Condition {
    return condition.All(
        condition.OnProperty("my.enabled", "true"),
        condition.OnClass("github.com/some/lib"),
    )
}

func init() {
    boot.RegisterStarter(&MyStarter{})
}

API 参考

内置条件
条件 说明 示例
OnProperty(key, value?) 属性存在且匹配值 OnProperty("gin.enabled", "true")
OnMissingProperty(key) 属性不存在 OnMissingProperty("gin.enabled")
OnBean(beanID) Bean 存在 OnBean("redisClient")
OnMissingBean(beanID) Bean 不存在 OnMissingBean("customCache")
OnProfile(profile) Profile 匹配 OnProfile("dev")OnProfile("!prod")
OnClass(className) 类路径存在 OnClass("github.com/gin-gonic/gin")
OnMissingClass(className) 类路径不存在 OnMissingClass("github.com/xx/xx")
OnPropertyPrefix(prefix) 配置前缀存在 OnPropertyPrefix("server")
OnProperty 匹配逻辑
  1. 仅传 key 时:存在且为有效字符串(非空)则匹配
  2. 传 key+value 时:存在且值等于预期值则匹配
OnProfile 匹配逻辑
  1. 支持否定前缀 !dev(非 dev 环境时匹配)
  2. 委托给 Environment.AcceptsProfile() 方法
组合条件
函数 逻辑 说明
All(conditions...) AND 所有子条件都匹配时通过(短路)
Any(conditions...) OR 任一子条件匹配时通过(短路)
Not(condition) NOT 对子条件结果取反
// AND 组合
cond := condition.All(
    condition.OnProperty("db.enabled", "true"),
    condition.OnBean("dataSource"),
    condition.OnProfile("!test"),
)

// OR 组合
cond := condition.Any(
    condition.OnProfile("dev"),
    condition.OnProfile("test"),
)

// NOT 组合
cond := condition.Not(condition.OnProfile("prod"))

// 嵌套组合
cond := condition.All(
    condition.OnProperty("app.enabled", "true"),
    condition.Any(
        condition.OnProfile("dev"),
        condition.OnProfile("staging"),
    ),
    condition.Not(
        condition.OnMissingBean("customHandler"),
    ),
)
自定义条件
// 方式一:内联函数
cond := condition.Custom("hasCustomDB", func(ctx condition.ConditionContext) bool {
    val, ok := ctx.GetProperty("db.type")
    return ok && val == "postgres"
})

// 方式二:实现 Condition 接口
type MyCondition struct{}

func (m *MyCondition) Matches(ctx condition.ConditionContext) bool {
    bean, ok := ctx.GetBean("userService")
    if !ok {
        return false
    }
    return bean != nil
}

func (m *MyCondition) String() string {
    return "MyCondition"
}

// 使用
condition.All(
    condition.OnProperty("my.feature.enabled", "true"),
    &MyCondition{},
)
扩展条件
条件 说明 示例
OnExpression(expr) SpEL 表达式 OnExpression("${server.port} > 8080")
OnResourceExists(path) 资源存在 OnResourceExists("classpath:config.yml")
OnEnvVarExists(name) 环境变量存在 OnEnvVarExists("DATABASE_URL")
OnExpression 表达式
// 简单比较
condition.OnExpression("${server.port} > 8080")

// 逻辑运算
condition.OnExpression("${app.env} == 'prod' && ${debug.enabled} == false")

// 三元运算
condition.OnExpression("${feature.flag} ? true : false")
OnResourceExists 资源路径
// 类路径资源
condition.OnResourceExists("classpath:config.yml")

// 文件系统资源
condition.OnResourceExists("file:/etc/app/config.json")

// 默认类路径
condition.OnResourceExists("config.yml")

使用示例

条件组合示例
// 生产环境且数据库配置完整时才注册
container.Register(
    reflect.TypeOf(&ProductionDB{}),
    core.Bean(&ProductionDB{}),
    core.Condition(condition.All(
        condition.OnProfile("prod"),
        condition.OnPropertyExists("db.host"),
        condition.OnPropertyExists("db.port"),
        condition.OnPropertyExists("db.name"),
    )),
)

// 开发环境或测试环境注册 Mock 服务
container.Register(
    reflect.TypeOf(&MockEmailService{}),
    core.Bean(&MockEmailService{}),
    core.Condition(condition.Any(
        condition.OnProfile("dev"),
        condition.OnProfile("test"),
    )),
)
自定义条件示例
// 仅当应用版本 >= 2.0 时生效
var versionCondition = condition.Custom("version>=2.0", func(ctx condition.ConditionContext) bool {
    val, ok := ctx.GetProperty("app.version")
    if !ok {
        return false
    }
    return val == "2.0" || val == "2.1" || val == "3.0"
})

// 使用自定义条件
boot.RegisterAutoConfig(
    &NewFeatureAutoConfiguration{},
    versionCondition,
)
条件调试输出
fmt.Println(condition.OnProperty("gin.enabled", "true").String())
// 输出: OnProperty(gin.enabled=true)

fmt.Println(condition.OnMissingBean("redis").String())
// 输出: OnMissingBean(redis)

fmt.Println(condition.All(
    condition.OnProperty("db.enabled", "true"),
    condition.Any(
        condition.OnProfile("dev"),
        condition.OnProfile("staging"),
    ),
).String())
// 输出: All(OnProperty(db.enabled=true), Any(OnProfile(dev), OnProfile(staging)))

与 Spring Boot @Conditional 对照

Spring Boot enhance 说明
@ConditionalOnProperty condition.OnProperty() 配置属性条件
@ConditionalOnMissingProperty condition.OnMissingProperty() 配置属性缺失
@ConditionalOnBean condition.OnBean() Bean 存在条件
@ConditionalOnMissingBean condition.OnMissingBean() Bean 缺失条件
@Profile condition.OnProfile() Profile 条件
@ConditionalOnClass condition.OnClass() 类路径条件
@ConditionalOnMissingClass condition.OnMissingClass() 类路径缺失条件
@ConditionalOnExpression condition.OnExpression() 表达式条件
@Conditional (多个) condition.All() / condition.Any() 组合条件

最佳实践

1. 使用内置条件简化配置
// ✅ 推荐:使用内置条件
container.Register(
    reflect.TypeOf(&MyService{}),
    core.Bean(&MyService{}),
    core.Condition(condition.OnProperty("my.enabled", "true")),
)

// ⚠️ 不推荐:手动检查条件
func init() {
    if os.Getenv("MY_ENABLED") == "true" {
        container.Register(...)
    }
}
2. 合理使用条件组合
// ✅ 推荐:明确表达条件逻辑
condition.All(
    condition.OnProperty("feature.enabled", "true"),
    condition.OnMissingBean("customImpl"),
)

// ⚠️ 不推荐:嵌套过深
condition.All(
    condition.Any(
        condition.All(...),
        condition.Any(...),
    ),
    condition.None(...),
)
3. 使用 OnMissingBean 提供默认实现
// ✅ 推荐:提供默认实现,允许用户覆盖
container.Register(
    reflect.TypeOf(&CacheService{}),
    core.Bean(&DefaultCacheService{}),
    core.Condition(condition.OnMissingBean("customCache")),
)
4. 自定义条件提供清晰的 String() 实现
// ✅ 推荐:便于调试和日志
func (m *MyCondition) String() string {
    return "MyCondition(threshold=100)"
}
5. 避免过度使用条件装配
// ✅ 推荐:仅在必要时使用条件
// - 可选依赖
// - 环境差异化配置
// - 提供默认实现

// ⚠️ 不推荐:核心业务逻辑使用条件装配
// 这会导致代码难以理解和调试

Documentation

Overview

Package condition 提供条件化注册功能,用于 enhance 框架。

该模块支持根据条件动态决定是否注册 Bean 或执行自动配置。 参考 Spring Boot 的 @Conditional 注解设计。

架构设计

  • Condition: 条件接口,定义条件判断逻辑
  • ConditionContext: 条件上下文接口
  • EnvironmentAccessor: 环境配置访问接口
  • ContainerAccessor: 容器访问接口
  • OnProperty: 基于配置属性的条件
  • OnModuleLoaded: 基于模块加载的条件(替代 Java 的 OnClass)
  • OnBean: 基于 Bean 存在的条件
  • OnMissingBean: 基于 Bean 缺失的条件
  • 条件组合: 支持 AND、OR、NOT 逻辑组合

内置条件

  • OnProperty: 检查配置属性是否存在或等于特定值
  • OnModuleLoaded: 检查指定模块是否已加载(Go 替代方案)
  • OnBean: 检查指定 Bean 是否已注册
  • OnMissingBean: 检查指定 Bean 是否未注册
  • OnMissingModule: 检查指定模块是否未加载

使用方式

在自动配置中使用条件:

type MyAutoConfiguration struct{}

func (m *MyAutoConfiguration) Configure(ctx boot.ApplicationContext) error {
    // 配置逻辑
    return nil
}

func init() {
    boot.RegisterAutoConfig(
        &MyAutoConfiguration{},
        condition.OnProperty("my.feature.enabled", "true"),
    )
}

条件组合

支持多个条件的逻辑组合:

condition.And(
    condition.OnProperty("feature.enabled", "true"),
    condition.OnMissingBean("customService"),
)

condition.Or(
    condition.OnProperty("env", "dev"),
    condition.OnProperty("env", "test"),
)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AllWithOptions

func AllWithOptions(opts ...CompositeOption) func(conditions ...Condition) Condition

AllWithOptions 返回一个带选项的复合条件

Types

type CompositeOption

type CompositeOption func(*compositeConfig)

CompositeOption 复合条件选项函数

func WithDescription

func WithDescription(desc string) CompositeOption

WithDescription 设置条件描述

func WithLazyEvaluation

func WithLazyEvaluation() CompositeOption

WithLazyEvaluation 启用惰性求值(短路优化) All 和 Any 默认已经支持短路优化,此选项用于显式声明

type Condition

type Condition interface {
	// Matches 评估条件是否匹配。
	Matches(ctx ConditionContext) bool
	// String 返回条件的可读描述,用于日志输出。
	String() string
}

Condition 条件接口。

参考 Spring Boot 的 @Conditional 注解体系。 用于在 AutoConfiguration 中控制 Bean 是否注册。

func All

func All(conditions ...Condition) Condition

All 返回一个复合条件,当所有子条件都匹配时返回 true(逻辑与运算)。 执行逻辑:遍历所有子条件,依次调用 Matches 方法:

  1. 只要有一个子条件不匹配,立即短路返回 false(不再继续判断后续条件)
  2. 所有子条件都匹配时返回 true

该行为与编程语言中的 && 运算符一致,支持短路优化。

func AllFunc

func AllFunc(fns ...func(ctx ConditionContext) bool) Condition

AllFunc 创建函数类型的逻辑与条件

与 All() 等效,但直接接受函数而非 Condition 接口。

示例:

cond := condition.AllFunc(
    func(ctx condition.ConditionContext) bool { return ctx.HasProperty("db.url") },
    func(ctx condition.ConditionContext) bool { return ctx.HasProperty("db.password") },
)

func Always

func Always() Condition

Always 创建始终匹配的条件

用于测试或强制启用的场景。

func Any

func Any(conditions ...Condition) Condition

Any 返回一个复合条件,当任一子条件匹配时返回 true(逻辑或运算)。 执行逻辑:遍历所有子条件,依次调用 Matches 方法:

  1. 只要有一个子条件匹配,立即短路返回 true(不再继续判断后续条件)
  2. 所有子条件都不匹配时返回 false

该行为与编程语言中的 || 运算符一致,支持短路优化。

func AnyFunc

func AnyFunc(fns ...func(ctx ConditionContext) bool) Condition

AnyFunc 创建函数类型的逻辑或条件

与 Any() 等效,但直接接受函数而非 Condition 接口。

示例:

cond := condition.AnyFunc(
    func(ctx condition.ConditionContext) bool { return ctx.HasProperty("cache.redis.url") },
    func(ctx condition.ConditionContext) bool { return ctx.HasProperty("cache.memcached.url") },
)

func Custom

func Custom(name string, evaluator func(ctx ConditionContext) bool) Condition

Custom 创建自定义条件

通过传入的评估函数决定是否匹配,name 用于日志和调试输出。

func Func

func Func(fn func(ctx ConditionContext) bool) Condition

Func 将普通函数包装为 Condition

便捷函数,用于快速创建条件。

示例:

cond := condition.Func(func(ctx condition.ConditionContext) bool {
    return os.Getenv("ENABLE_FEATURE") == "1"
})

func Never

func Never() Condition

Never 创建始终不匹配的条件

用于禁用某个自动配置。

func Not

func Not(condition Condition) Condition

Not 返回一个复合条件,对子条件的匹配结果取反(逻辑非运算)。 执行逻辑:调用子条件的 Matches 方法,然后对其结果取反:

  1. 子条件匹配时返回 false
  2. 子条件不匹配时返回 true

该行为与编程语言中的 ! 运算符一致。

func OnBean

func OnBean(beanID string) Condition

OnBean 创建基于 Bean 存在的条件

当容器中存在指定 ID 的 Bean 时匹配。

func OnEnvVarExists

func OnEnvVarExists(envVar string) Condition

OnEnvVarExists 创建基于环境变量存在性的条件

当指定的环境变量存在时匹配。

示例:

condition.OnEnvVarExists("DATABASE_URL")
condition.OnEnvVarExists("REDIS_HOST")

func OnEnvVarMissing

func OnEnvVarMissing(envVar string) Condition

OnEnvVarMissing 创建基于环境变量不存在性的条件

当指定的环境变量不存在时匹配。

func OnExpression

func OnExpression(expression string) Condition

OnExpression 创建基于 SpEL 表达式的条件

表达式支持以下语法:

  • 属性引用: ${server.port} 或 server.port
  • 比较运算: >, <, >=, <=, ==, !=
  • 逻辑运算: &&, ||, !
  • 三元运算: condition ? trueVal : falseVal
  • 字面量: 字符串、数字、布尔值

示例:

condition.OnExpression("${server.port} > 8080")
condition.OnExpression("${app.env} == 'prod' && ${debug.enabled} == false")

func OnMissingBean

func OnMissingBean(beanID string) Condition

OnMissingBean 创建基于 Bean 不存在的条件

当容器中不存在指定 ID 的 Bean 时匹配。

func OnMissingModule

func OnMissingModule(moduleName string) Condition

OnMissingModule 创建基于模块未加载的条件

当指定模块未加载到容器中时匹配。

func OnMissingProperty

func OnMissingProperty(key string) Condition

OnMissingProperty 创建基于属性不存在的条件

当指定的配置键不存在时匹配。

func OnModuleLoaded

func OnModuleLoaded(moduleName string) Condition

OnModuleLoaded 创建基于模块加载的条件

当指定模块已加载到容器中时匹配。 Go 中不支持 Java 的 Class.forName() 动态类加载,改用模块名称检查。

func OnProfile

func OnProfile(profile string) Condition

OnProfile 创建基于 Profile 的条件

当指定 Profile 被激活时匹配。支持否定前缀 "!",如 "!dev" 表示非 dev 环境时匹配。

func OnProperty

func OnProperty(key string, expectedValue ...string) Condition

OnProperty 创建基于配置属性的条件

如果只传 key,当该属性存在且不为空时匹配。 如果传 key 和 value,当该属性等于 value 时匹配。

func OnPropertyPrefix

func OnPropertyPrefix(prefix string) Condition

OnPropertyPrefix 创建基于配置前缀存在的条件

当存在以指定前缀开头的配置键时匹配。

func OnResourceExists

func OnResourceExists(location string) Condition

OnResourceExists 创建基于资源存在性的条件

支持以下资源前缀:

  • classpath: - 类路径资源(Go 中检查文件是否存在)
  • file: - 文件系统资源
  • 无前缀 - 默认为 classpath

示例:

condition.OnResourceExists("classpath:config.yml")
condition.OnResourceExists("file:/etc/app/config.json")
condition.OnResourceExists("config.yml") // 等同于 classpath:config.yml

func OnResourceMissing

func OnResourceMissing(location string) Condition

OnResourceMissing 创建基于资源不存在性的条件

当指定资源不存在时匹配。

func When

func When(description string, fn func(ctx ConditionContext) bool) Condition

When 创建带描述的条件

在 ConditionFunc 基础上增加可读的 String() 输出。

示例:

cond := condition.When("feature flag is enabled", func(ctx condition.ConditionContext) bool {
    val, _ := ctx.GetProperty("feature.enabled")
    return val == "true"
})

type ConditionBuilder

type ConditionBuilder struct {
	// contains filtered or unexported fields
}

ConditionBuilder 条件构建器,提供流式 DSL

示例:

condition.New().
    OnProperty("feature.enabled", "true").
    And().
    OnBean("dataSource").
    Or().
    OnProfile("dev").
    Build()

func New

func New() *ConditionBuilder

New 创建条件构建器

func (*ConditionBuilder) All

func (b *ConditionBuilder) All(conditions ...Condition) *ConditionBuilder

All 添加一个 All 复合条件

func (*ConditionBuilder) And

And 添加逻辑与操作

func (*ConditionBuilder) Any

func (b *ConditionBuilder) Any(conditions ...Condition) *ConditionBuilder

Any 添加一个 Any 复合条件

func (*ConditionBuilder) Build

func (b *ConditionBuilder) Build() Condition

Build 构建最终条件

func (*ConditionBuilder) Not

Not 添加逻辑非操作(对下一个条件取反)

func (*ConditionBuilder) OnBean

func (b *ConditionBuilder) OnBean(beanID string) *ConditionBuilder

OnBean 添加 Bean 存在条件

func (*ConditionBuilder) OnEnvVarExists

func (b *ConditionBuilder) OnEnvVarExists(envVar string) *ConditionBuilder

OnEnvVarExists 添加环境变量存在条件

func (*ConditionBuilder) OnEnvVarMissing

func (b *ConditionBuilder) OnEnvVarMissing(envVar string) *ConditionBuilder

OnEnvVarMissing 添加环境变量缺失条件

func (*ConditionBuilder) OnExpression

func (b *ConditionBuilder) OnExpression(expression string) *ConditionBuilder

OnExpression 添加表达式条件

func (*ConditionBuilder) OnMissingBean

func (b *ConditionBuilder) OnMissingBean(beanID string) *ConditionBuilder

OnMissingBean 添加 Bean 缺失条件

func (*ConditionBuilder) OnMissingModule

func (b *ConditionBuilder) OnMissingModule(moduleName string) *ConditionBuilder

OnMissingModule 添加模块缺失条件

func (*ConditionBuilder) OnMissingProperty

func (b *ConditionBuilder) OnMissingProperty(key string) *ConditionBuilder

OnMissingProperty 添加属性缺失条件

func (*ConditionBuilder) OnModuleLoaded

func (b *ConditionBuilder) OnModuleLoaded(moduleName string) *ConditionBuilder

OnModuleLoaded 添加模块加载条件

func (*ConditionBuilder) OnProfile

func (b *ConditionBuilder) OnProfile(profile string) *ConditionBuilder

OnProfile 添加 Profile 条件

func (*ConditionBuilder) OnProperty

func (b *ConditionBuilder) OnProperty(key string, expectedValue ...string) *ConditionBuilder

OnProperty 添加属性条件

func (*ConditionBuilder) OnResourceExists

func (b *ConditionBuilder) OnResourceExists(location string) *ConditionBuilder

OnResourceExists 添加资源存在条件

func (*ConditionBuilder) OnResourceMissing

func (b *ConditionBuilder) OnResourceMissing(location string) *ConditionBuilder

OnResourceMissing 添加资源缺失条件

func (*ConditionBuilder) Or

Or 添加逻辑或操作

type ConditionBuilderGroup

type ConditionBuilderGroup struct {
	// contains filtered or unexported fields
}

ConditionBuilderGroup 条件组构建器

func AllWith

func AllWith(conditions ...Condition) ConditionBuilderGroup

All 改进版:支持链式调用

func (ConditionBuilderGroup) And

And 添加与条件组

func (ConditionBuilderGroup) Build

func (g ConditionBuilderGroup) Build() Condition

Build 构建最终条件

func (ConditionBuilderGroup) Or

Or 添加或条件组

type ConditionContext

type ConditionContext interface {
	// Environment 返回环境配置,用于读取属性值。
	Environment() EnvironmentAccessor
	// Container 返回 DI 容器,用于检查 Bean 是否存在。
	Container() ContainerAccessor

	// GetBeanByType 从容器中按类型获取 Bean 实例。
	GetBeanByType(t reflect.Type) (any, bool)
	// HasProperty 检查属性是否存在。
	HasProperty(key string) bool
	// GetProperty 获取属性值。
	GetProperty(key string) (any, bool)
}

ConditionContext 条件上下文。

提供条件判断所需的环境、容器和一些便捷方法。

type ConditionFunc

type ConditionFunc func(ctx ConditionContext) bool

ConditionFunc 条件函数类型

这是 Condition 接口的函数式替代方案,适用于简单条件判断。 无需实现接口,直接写函数即可。

示例:

// 简单条件函数
cond := condition.ConditionFunc(func(ctx condition.ConditionContext) bool {
    val, ok := ctx.GetProperty("feature.enabled")
    return ok && val == "true"
})

// 或使用内置的 OnProperty 等函数(它们已经返回 Condition)
cond := condition.OnProperty("feature.enabled", "true")

func (ConditionFunc) Matches

func (f ConditionFunc) Matches(ctx ConditionContext) bool

Matches 实现 Condition 接口

func (ConditionFunc) String

func (f ConditionFunc) String() string

String 返回条件的可读描述

type ContainerAccessor

type ContainerAccessor interface {
	Has(id string) bool
}

ContainerAccessor 容器访问接口。

type EnvironmentAccessor

type EnvironmentAccessor interface {
	GetProperty(key string) (any, bool)
}

EnvironmentAccessor 环境配置访问接口。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL