Java 方法级别的 Spring Profiles?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22349120/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 15:07:44  来源:igfitidea点击:

Spring Profiles on method level?

javaspringspring-profiles

提问by membersound

I'd like to introduce some methods that are only executed during development.

我想介绍一些只在开发过程中执行的方法。

I thought I might use Spring @Profileannotation here? But how can I apply this annotation on class level, so that this method is only invoked if the specific profile is configured in properties?

我想我可以Spring @Profile在这里使用注释?但是如何在类级别应用此注释,以便仅在属性中配置特定配置文件时才调用此方法?

spring.profiles.active=dev

Take the following as pseudocode. How can this be done?

将以下内容作为伪代码。如何才能做到这一点?

class MyService {

    void run() { 
       log();
    }

    @Profile("dev")
    void log() {
       //only during dev
    }
}

采纳答案by Andres

AS you can read on http://docs.spring.io/spring/docs/3.1.x/javadoc-api/org/springframework/context/annotation/Profile.html

你可以阅读http://docs.spring.io/spring/docs/3.1.x/javadoc-api/org/springframework/context/annotation/Profile.html

The @Profile annotation may be used in any of the following ways:

as a type-level annotation on any class directly or indirectly annotated with @Component, including @Configuration classes as a meta-annotation, for the purpose of composing custom stereotype annotations If a @Configuration class is marked with @Profile, all of the @Bean methods and @Import annotations associated with that class will be bypassed unless one or more the specified profiles are active.This is very similar to the behavior in Spring XML: if the profile attribute of the beans element is supplied e.g., , the beans element will not be parsed unless profiles 'p1' and/or 'p2' have been activated. Likewise, if a @Component or @Configuration class is marked with @Profile({"p1", "p2"}), that class will not be registered/processed unless profiles 'p1' and/or 'p2' have been activated.

@Profile 注释可以通过以下任何一种方式使用:

作为直接或间接用@Component 注释的任何类上的类型级注释,包括作为元注释的@Configuration 类,用于组合自定义构造型注释如果@Configuration 类用@Profile 标记,则所有@除非一个或多个指定的配置文件处于活动状态,否则将绕过与该类关联的 Bean 方法和 @Import 注释。这与 Spring XML 中的行为非常相似:如果提供了 beans 元素的 profile 属性,例如,则不会解析 beans 元素,除非配置文件 'p1' 和/或 'p2' 已被激活。同样,如果@Component 或@Configuration 类用@Profile({"p1", "p2"}) 标记,则不会注册/处理该类,除非配置文件'p1'

So, a @Profile annotation on a class, aplies to all of it's methods and imports. Not to the class.

因此,类上的 @Profile 注释适用于它的所有方法和导入。不上课。

What you're trying to do could probably be achieved by having two classes that implement the same interface, and injecting one or another depending on the profile. Take a look at the answer to this question.

您尝试做的事情可能可以通过拥有两个实现相同接口的类并根据配置文件注入一个或另一个来实现。看看这个问题的答案。

Annotation-driven dependency injection which handles different environments

处理不同环境的注解驱动依赖注入

回答by Jorge Sanchez

Possible in 4.1

可能在 4.1

The @Profile annotation may be used in any of the following ways:

as a type-level annotation on any class directly or indirectly annotated with @Component, including @Configuration classes. As a meta-annotation, for the purpose of composing custom stereotype annotations. As a method-level annotationon any @Bean method

@Profile 注释可以通过以下任何一种方式使用:

作为直接或间接用@Component 注释的任何类上的类型级注释,包括@Configuration 类。作为元注释,用于编写自定义构造型注释。作为任何@Bean 方法的方法级注解

http://docs.spring.io/spring/docs/4.1.x/javadoc-api/org/springframework/context/annotation/Profile.html

http://docs.spring.io/spring/docs/4.1.x/javadoc-api/org/springframework/context/annotation/Profile.html

回答by Niels Masdorp

For future readers who don't want to have multiple @Beansannotated with @Profile, this could also be a solution:

对于不想有多个@Beans注释的未来读者@Profile,这也可能是一个解决方案:

class MyService {

   @Autowired
   Environment env;

   void run() { 
      if (Arrays.asList(env.getActiveProfiles()).contains("dev")) {
         log();
      }
   }

   void log() {
      //only during dev
   }
}

回答by eis

Just wanted to add that answer saying this is possible with current spring on method-levelis blatantly wrong. Using @Profile on methods in general will not work - the only methods it will work on are in the @Configuration class with @Bean annotation on them.

只是想补充一个答案,说在方法级别的当前 spring 中这是可能的,这是明显错误的。通常在方法上使用 @Profile 是行不通的 - 它可以使用的唯一方法是在带有 @Bean 注释的 @Configuration 类中。

I run a quick test with Spring 4.2.4, where it was seen that

我用 Spring 4.2.4 运行了一个快速测试,发现

  • @Profile in @Configuration class bean creation methods work
  • @Profile in methods of a bean does not work (and is not expected to work - docs are a bit ambiguous)
  • Class-level @Profile works if and only ifit's at the same context as bean definition, in the configuration class or if context-scan is used, there
  • env.acceptsProfiles("profile"), Arrays.asList(env.getActiveProfiles()).contains("profile") works
  • @Configuration 类 bean 创建方法中的 @Profile 工作
  • bean 方法中的 @Profile 不起作用(并且预计不会起作用 - 文档有点模棱两可)
  • 当且仅当它与 bean 定义在相同的上下文中、在配置类中或使用上下文扫描时,类级别的 @Profile 才起作用
  • env.acceptsProfiles("profile"), Arrays.asList(env.getActiveProfiles()).contains("profile") 有效

Test class:

测试类:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.Arrays;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { ProfileTest.ProfileTestConfiguration.class })
@ActiveProfiles("test")
public class ProfileTest {
    static class SomeClass {}
    static class OtherClass {}
    static class ThirdClass {
        @Profile("test")
        public void method() {}
    }
    static class FourthClass {
        @Profile("!test")
        public void method() {}
    }

    static class ProfileTestConfiguration {
        @Bean
        @Profile("test")
        SomeClass someClass() {
            return new SomeClass();
        }
        @Bean
        @Profile("!test")
        OtherClass otherClass() {
            return new OtherClass();
        }
        @Bean
        ThirdClass thirdClass() {
            return new ThirdClass();
        }
        @Bean
        FourthClass fourthClass() {
            return new FourthClass();
        }
    }

    @Autowired
    ApplicationContext context;

    @Test
    public void testProfileAnnotationIncludeClass() {
        context.getBean(SomeClass.class);
    }
    @Test(expected = NoSuchBeanDefinitionException.class)
    public void testProfileAnnotationExcludeClass() {
        context.getBean(OtherClass.class);
    }
    @Test
    public void testProfileAnnotationIncludeMethod() {
        context.getBean(ThirdClass.class).method();
    }
    @Test(expected = Exception.class)  // fails
    public void testProfileAnnotationExcludeMethod() {
        context.getBean(FourthClass.class).method();
    }
}

回答by Grigory Kislin

@Profilecan be used with method and with Java Based Configuration

@Profile可以与方法和基于 Java 的配置一起使用

e.g. separate DB timestamp for PostgreSQL (LocalDateTime) and for HSQLDB (prior to 2.4.0 Timestamp):

例如 PostgreSQL (LocalDateTime) 和 HSQLDB(2.4.0 Timestamp 之前)的单独 DB 时间戳:

@Autowired
private Function<LocalDateTime, T> dateTimeExtractor;

@Bean
@Profile("hsqldb")
public Function<LocalDateTime, Timestamp> getTimestamp() {
    return Timestamp::valueOf;
}

@Bean
@Profile("postgres")
public Function<LocalDateTime, LocalDateTime> getLocalDateTime() {
    return dt -> dt;
}

Have a look also at Spring Profiles example: 3. More…(sample Spring @Profile at method level)

也看看Spring Profiles 示例:3. 更多...(方法级别的 Spring @Profile 示例)