@Profile注解与@Conditional注解

博客介绍了Spring的@Profile和@Conditional注解。@Profile可根据当前环境动态激活和切换组件,能指定组件在特定环境注册;@Conditional则按一定条件判断,满足条件就向容器注入bean,还给出了这两个注解的代码示例及测试结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

@Profile注解:是spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能。

@Conditional:按照一定的条件进行判断,满足条件则给容器中注入bean

@Profile代码示例:

package common.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.util.StringValueResolver;

import javax.sql.DataSource;

@Configuration
@PropertySource("classpath:/dbconfig.properties")
public class MainConfigProfile implements EmbeddedValueResolverAware {
    @Value("${db.username}")
    private String userName;

    private StringValueResolver valueResolver;

    private String driver;

    @Profile("dev")
    @Bean("devDataSource")
    public DataSource dataSourceDev(@Value("${db.password}")String pwd){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUsername(userName);
        dataSource.setPassword(pwd);
        dataSource.setUrl("dbc:mysql://localhost:3306/dev");
        dataSource.setDriverClassName(driver);
        return dataSource;
    }

    @Profile("test")
    @Bean("testDataSource")
    public DataSource dataSourceTest(@Value("${db.password}")String pwd){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUsername(userName);
        dataSource.setPassword(pwd);
        dataSource.setUrl("dbc:mysql://localhost:3306/test");

        dataSource.setDriverClassName(driver);
        return dataSource;
    }

    @Profile("prod")
    @Bean("prodDataSource")
    public DataSource dataSourceProd(@Value("${db.password}")String pwd){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUsername(userName);
        dataSource.setPassword(pwd);
        dataSource.setUrl("dbc:mysql://localhost:3306/prod");
        dataSource.setDriverClassName(driver);
        return dataSource;
    }

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        this.valueResolver = resolver;
        driver = valueResolver.resolveStringValue("${db.driverClass}");
    }
}

测试类:

package common;

import common.config.MainConfigProfile;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ProFileTest {

    //1.使用命令行动态参数: 在虚拟机参数位置加载 -Dspring.profiles.active=test
    //2、代码的方式激活某种环境;
    @Test
    public void test(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigProfile.class);
//        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
//        context.getEnvironment().setActiveProfiles("dev");
//        context.register(MainConfigProfile.class);
//        context.refresh();

        String[] names = context.getBeanDefinitionNames();
        for (String s: names){
            System.out.println(s);
        }
    }
}

测试结果的输出可以看出使用了@Profile注解后,可以指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境都能注册这个组件。

@Condition示例

配置类:

package common.config;

import common.bean.Red;
import common.bean.Yellow;
import condition.WindowsCondition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

/**
 * @Conditional注解加在配置类上,不满足条件时,配置类都不会注入到容器中
 */
@Configuration
public class MainConfigCondition {

    @Bean
    public Red red(){
        return new Red();
    }
    @Conditional(WindowsCondition.class)
    @Bean
    public Yellow yellow(){
        return new Yellow();
    }
}

 

package condition;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        if(property.contains("Windows")){
            return false;
        }
        return true;
    }
}

测试类:

package common;

import common.config.MainConfigCondition;
import common.config.MainConfigProfile;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ProFileTest {

    @Test
    public void test(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigCondition.class);
        String[] names = context.getBeanDefinitionNames();
        for (String s: names){
            System.out.println(s);
        }
    }
}

测试结果:

八月 29, 2018 4:11:43 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2a3046da: startup date [Wed Aug 29 16:11:43 CST 2018]; root of context hierarchy
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfigCondition
red

 

转载于:https://my.oschina.net/wuyiyi/blog/1936053

<think>好的,我现在要解释一下@Profile注解的作用。用户之前问过关于Spring AOP中的MethodSignature的问题,现在转向了@Profile,可能是在学习Spring框架的不同部分。首先,我需要回忆@Profile的基本用途。 记得@Profile是Spring中的一个注解,用于根据环境配置来条件化地注册Bean。也就是说,当应用运行在某个特定的Profile时,被@Profile标记的组件才会被加载。比如开发环境、测试环境、生产环境的不同配置。 那用户可能想知道@Profile的具体作用,比如如何启用不同的配置,或者解决多环境配置的问题。我需要分点说明,结构清晰。同时要注意用户之前的问题是关于方法签名和AOP的,可能用户现在在学习Spring的核心功能,比如Bean管理和环境配置。 首先,要定义@Profile的作用,然后说明使用场景,比如按环境加载Bean。接着,可能需要解释如何激活Profile,比如通过配置文件或启动参数。然后举一些例子,比如配置数据源的不同环境,或者测试和生产环境的不同服务实现。 还要注意用户可能混淆其他类似的注解,比如@Conditional,不过@Profile是更高级的抽象,基于条件配置。需要明确区别,但可能不需要深入,除非用户问到。 另外,需要提到@Profile可以用在类级别或方法级别,结合@Bean一起使用。例如,在配置类中,某个Bean只有在指定Profile激活时才会被创建。 可能用户在使用多环境配置时遇到问题,比如Bean未按预期加载,所以需要了解@Profile如何帮助控制Bean的创建。需要强调它的核心作用是根据环境条件注册Bean,帮助管理不同环境的配置。 还要注意示例代码的正确性,比如用@Component @Profile("dev")来标记只在开发环境有效的组件。同时,激活Profile的方式,比如在application.properties里设置spring.profiles.active=dev,或者命令行参数--spring.profiles.active=prod。 最后,总结一下@Profile的优势,比如配置隔离、避免资源冲突,确保不同环境使用合适的配置。同时提醒常见的使用场景,如数据库配置、外部服务切换等。 需要确保语言口语化,但信息准确,结构清晰,帮助用户逐步理解。可能还要对比直接使用@Profile和其他条件注解的区别,但保持简洁。检查是否有遗漏的关键点,比如如何组合多个Profile,使用!操作符排除Profile等。 总之,回答要覆盖@Profile的定义、作用、使用方式、示例、激活方法以及适用场景,确保用户能够全面理解其用途和应用方法。</think>--- ### **`@Profile` 注解的作用** `@Profile` 是 Spring 框架中的一个**条件化注册 Bean**的注解,用于根据**当前运行环境**(Profile)动态控制哪些 Bean 或配置类需要被加载。它的核心作用是**实现多环境配置的隔离**,例如开发环境、测试环境、生产环境使用不同的配置。 --- ### **1. 核心用途** - **按环境加载 Bean** 标记 `@Profile("环境名")` 的 Bean 或配置类,**仅当指定的环境激活时才会被注册到 Spring 容器**。 - **解决多环境配置冲突** 例如:开发环境使用本地数据库,生产环境使用云数据库,避免不同环境的配置互相干扰。 --- ### **2. 使用场景** | **场景** | **示例** | |-------------------------|--------------------------------------------------------------------------| | 不同环境的数据源配置 | 开发环境用 `H2`,生产环境用 `MySQL` | | 启用/禁用特定功能 | 测试环境开启 Mock 服务,生产环境关闭 | | 环境专属的 Bean 实现 | `@Profile("dev")` 使用本地日志,`@Profile("prod")` 使用云日志服务 | --- ### **3. 基本用法** #### **(1) 标注在类上** ```java @Configuration @Profile("dev") // 仅在 dev 环境生效 public class DevConfig { @Bean public DataSource devDataSource() { return new H2Database(); // 开发环境数据源 } } ``` #### **(2) 标注在方法上(配合 `@Bean`)** ```java @Configuration public class AppConfig { @Bean @Profile("prod") // 仅在 prod 环境生效 public DataSource prodDataSource() { return new MySQLDatabase(); // 生产环境数据源 } } ``` #### **(3) 标注在组件类上** ```java @Component @Profile("test") // 仅在 test 环境生效 public class MockPaymentService implements PaymentService { // 测试环境的支付模拟实现 } ``` --- ### **4. 如何激活 Profile?** 可以通过以下方式指定当前激活的环境: - **配置文件(`application.properties`)** ```properties spring.profiles.active=dev ``` - **启动参数** ```bash java -jar app.jar --spring.profiles.active=prod ``` - **单元测试中** ```java @ActiveProfiles("test") // 指定测试类使用的 Profile @SpringBootTest public class PaymentServiceTest { // ... } ``` --- ### **5. 高级用法** #### **(1) 多 Profile 组合** 支持同时激活多个 Profile,用逗号分隔: ```properties spring.profiles.active=dev,logging ``` #### **(2) 排除特定 Profile** 使用 `!` 表示排除某个环境: ```java @Profile("!prod") // 所有非生产环境生效 public class NonProdService { /* ... */ } ``` #### **(3) 默认 Profile** 若未显式激活任何 Profile,则使用 `default` 环境。也可自定义默认值: ```properties spring.profiles.default=local ``` --- ### **6. `@Conditional` 的区别** - `@Profile` 是基于**环境名称**的条件判断(底层是 `@Conditional(ProfileCondition.class)`)。 - `@Conditional` 是更通用的条件注解,支持自定义逻辑(例如根据系统属性、文件是否存在等)。 --- ### **7. 典型应用场景** 1. **数据库切换**:不同环境使用不同的数据源。 2. **功能开关**:测试环境开启调试工具,生产环境关闭。 3. **外部服务配置**:开发环境用本地模拟服务,生产环境用真实服务。 --- ### **总结** `@Profile` 是 Spring 多环境配置的核心工具,通过**环境隔离**确保代码的灵活性和安全性。掌握它的用法,可以高效管理不同环境的差异配置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值