我想介绍一些仅在开发过程中执行的方法。
我以为我可能会在这里使用Spring @Profile
注释?但是如何在类级别上应用此批注,以便仅在属性中配置特定的配置文件时才调用此方法?
spring.profiles.active=dev
将以下内容作为伪代码。怎么办呢?
class MyService {
void run() {
log();
}
@Profile("dev")
void log() {
//only during dev
}
}
答案 0 :(得分:13)
对于不希望多个@Beans
注明@Profile
的读者,这也可能是一个解决方案:
class MyService {
@Autowired
Environment env;
void run() {
if (Arrays.asList(env.getActiveProfiles()).contains("dev")) {
log();
}
}
void log() {
//only during dev
}
}
答案 1 :(得分:11)
@Profile注释可以通过以下任何方式使用:
作为任何类的类型级注释直接或间接 用@Component注释,包括@Configuration类作为 元注释,用于组成自定义构造型 注释如果@Configuration类标有@Profile,则全部 与该类关联的@Bean方法和@Import注释 除非一个或多个指定的配置文件处于活动状态,否则将被绕过。 这与Spring XML中的行为非常相似:如果是配置文件 例如,bean元素的属性被提供,除非配置文件,否则将不解析beans元素 'p1'和/或'p2'已被激活。同样,如果@Component或 @Configuration类标有@Profile({“p1”,“p2”}),该类 除非配置文件'p1'和/或'p2'具有,否则不会注册/处理 被激活了。
因此,类上的@Profile注释适用于所有方法和导入。不是上课。
您尝试做的事情可能是通过让两个类实现相同的接口,并根据配置文件注入一个或另一个来实现的。看看这个问题的答案。
Annotation-driven dependency injection which handles different environments
答案 2 :(得分:10)
只是想补充一点,answer saying this is possible with current spring on method-level显然是错误的。一般情况下对方法使用@Profile是行不通的 - 它将使用的唯一方法是在@Configuration类中使用@Bean注释。
我使用Spring 4.2.4进行快速测试,在那里可以看到
测试类:
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();
}
}
答案 3 :(得分:7)
可能在4.1
中@Profile注释可以通过以下任何方式使用:
作为任何类的类型级注释直接或间接 用@Component注释,包括@Configuration类。作为一个 元注释,用于组成自定义构造型 注释。 作为任何@Bean方法的方法级注释
答案 4 :(得分:6)
@Profile
可以与方法一起使用,也可以与Java Based Configuration
e.g。 PostgreSQL(LocalDateTime)和HSQLDB(2.4.0时间戳之前)的单独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;
}
另请参阅Spring Profiles example:3。更多...(在方法级别采样Spring @Profile)
答案 5 :(得分:0)
使用Environment个人资料可以实现:
class MyClass {
@Autowired
Environment env;
void methodA() {
if (env.acceptsProfiles(Profiles.of("dev"))) {
methodB();
}
}
void methodB() {
// when profile is 'dev'
}
}
Profiles.of
也可以与逻辑表达式一起使用:
(字符串...个人档案)的静态个人档案创建一个新的个人档案实例 根据给定的配置文件字符串检查匹配项。的 如果有任何给定的配置文件字符串,则返回的实例将匹配 匹配。
配置文件字符串可能包含一个简单的配置文件名称(例如 “生产”)或配置文件表达式。配置文件表达式允许 例如,要表达的更复杂的配置文件逻辑 “生产与云”。
配置文件表达式中支持以下运算符:
! -逻辑非概要文件&-逻辑非概要文件| -- 逻辑或配置文件,请注意&和|经营者 不使用括号不能混用。例如,“ a&b | c”是 不是有效的表达;它必须表示为“(a&b)| c”或“ a& (b | c)”。
答案 6 :(得分:0)
@Profile
不能用于此目的,但您不妨编写自己的 @RunOnProfile
注释和方面。您的方法如下所示:
@RunOnProfile({"dev", "uat"})
public void doSomething() {
log.info("I'm doing something on dev and uat");
}
或
@RunOnProfile("!prod")
public void doSomething() {
log.info("I'm doing something on profile other than prod");
}
这是 @RunOnProfile
注释和方面的代码:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RunOnProfile {
String[] value();
@Aspect
@Configuration
class RunOnProfileAspect {
@Autowired
Environment env;
@Around("@annotation(runOnProfile)")
public Object around(ProceedingJoinPoint joinPoint, RunOnProfile runOnProfile) throws Throwable {
if (env.acceptsProfiles(runOnProfile.value()))
return joinPoint.proceed();
return null;
}
}
}
注意 1:如果您希望得到回报,而个人资料不适用,您将获得 null
。
注意 2:这与任何其他 Spring 方面一样工作。您需要调用自动装配的 bean 方法,bean 代理才能启动。换句话说,您不能直接从其他类方法调用该方法。如果需要,您需要在类上自动装配组件并调用 self.doSomething()
。