Skip to content

Commit aecf60d

Browse files
committed
Discovering and accumulating all @Profile meta-annotations
Issue: SPR-10812
1 parent c977101 commit aecf60d

File tree

2 files changed

+76
-25
lines changed

2 files changed

+76
-25
lines changed

spring-context/src/main/java/org/springframework/context/annotation/ProfileCondition.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,30 @@
1616

1717
package org.springframework.context.annotation;
1818

19-
import org.springframework.core.annotation.AnnotationAttributes;
2019
import org.springframework.core.type.AnnotatedTypeMetadata;
20+
import org.springframework.util.MultiValueMap;
2121

2222
/**
2323
* {@link Condition} that matches based on the value of a {@link Profile @Profile}
2424
* annotation.
2525
*
2626
* @author Chris Beams
2727
* @author Phillip Webb
28+
* @author Juergen Hoeller
2829
* @since 4.0
2930
*/
3031
class ProfileCondition implements Condition {
3132

3233
@Override
3334
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
34-
if (context.getEnvironment() != null && metadata.isAnnotated(Profile.class.getName())) {
35-
AnnotationAttributes profile = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(Profile.class.getName()));
36-
if (!context.getEnvironment().acceptsProfiles(profile.getStringArray("value"))) {
35+
if (context.getEnvironment() != null) {
36+
MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
37+
if (attrs != null) {
38+
for (Object value : attrs.get("value")) {
39+
if (context.getEnvironment().acceptsProfiles(((String[]) value))) {
40+
return true;
41+
}
42+
}
3743
return false;
3844
}
3945
}

spring-context/src/test/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProviderTests.java

Lines changed: 66 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,25 @@
1616

1717
package org.springframework.context.annotation;
1818

19-
import static org.hamcrest.CoreMatchers.is;
20-
import static org.junit.Assert.assertEquals;
21-
import static org.junit.Assert.assertFalse;
22-
import static org.junit.Assert.assertThat;
23-
import static org.junit.Assert.assertTrue;
24-
25-
import java.util.Iterator;
19+
import java.lang.annotation.Retention;
20+
import java.lang.annotation.RetentionPolicy;
2621
import java.util.Set;
2722
import java.util.regex.Pattern;
2823

24+
import example.profilescan.DevComponent;
25+
import example.profilescan.ProfileAnnotatedComponent;
26+
import example.profilescan.ProfileMetaAnnotatedComponent;
27+
import example.scannable.FooDao;
28+
import example.scannable.FooService;
29+
import example.scannable.FooServiceImpl;
30+
import example.scannable.MessageBean;
31+
import example.scannable.NamedComponent;
32+
import example.scannable.NamedStubDao;
33+
import example.scannable.ServiceInvocationCounter;
34+
import example.scannable.StubFooDao;
2935
import org.aspectj.lang.annotation.Aspect;
3036
import org.junit.Test;
37+
3138
import org.springframework.beans.factory.config.BeanDefinition;
3239
import org.springframework.core.env.ConfigurableEnvironment;
3340
import org.springframework.core.env.StandardEnvironment;
@@ -39,17 +46,8 @@
3946
import org.springframework.stereotype.Repository;
4047
import org.springframework.stereotype.Service;
4148

42-
import example.profilescan.DevComponent;
43-
import example.profilescan.ProfileAnnotatedComponent;
44-
import example.profilescan.ProfileMetaAnnotatedComponent;
45-
import example.scannable.FooDao;
46-
import example.scannable.FooService;
47-
import example.scannable.FooServiceImpl;
48-
import example.scannable.MessageBean;
49-
import example.scannable.NamedComponent;
50-
import example.scannable.NamedStubDao;
51-
import example.scannable.ServiceInvocationCounter;
52-
import example.scannable.StubFooDao;
49+
import static org.hamcrest.CoreMatchers.*;
50+
import static org.junit.Assert.*;
5351

5452
/**
5553
* @author Mark Fisher
@@ -276,9 +274,39 @@ public void testIntegrationWithAnnotationConfigApplicationContext_defaultAndDevP
276274
}
277275
}
278276

277+
@Test
278+
public void testIntegrationWithAnnotationConfigApplicationContext_metaProfile() {
279+
Class<?> beanClass = MetaProfileAnnotatedComponent.class;
280+
String beanName = MetaProfileAnnotatedComponent.BEAN_NAME;
281+
{
282+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
283+
ctx.getEnvironment().setDefaultProfiles(TEST_DEFAULT_PROFILE_NAME);
284+
// no active profiles are set
285+
ctx.register(beanClass);
286+
ctx.refresh();
287+
assertThat(ctx.containsBean(beanName), is(true));
288+
}
289+
{
290+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
291+
ctx.getEnvironment().setDefaultProfiles(TEST_DEFAULT_PROFILE_NAME);
292+
ctx.getEnvironment().setActiveProfiles("dev");
293+
ctx.register(beanClass);
294+
ctx.refresh();
295+
assertThat(ctx.containsBean(beanName), is(true));
296+
}
297+
{
298+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
299+
ctx.getEnvironment().setDefaultProfiles(TEST_DEFAULT_PROFILE_NAME);
300+
ctx.getEnvironment().setActiveProfiles("other");
301+
ctx.register(beanClass);
302+
ctx.refresh();
303+
assertThat(ctx.containsBean(beanName), is(false));
304+
}
305+
}
306+
279307
private boolean containsBeanClass(Set<BeanDefinition> candidates, Class<?> beanClass) {
280-
for (Iterator<BeanDefinition> it = candidates.iterator(); it.hasNext();) {
281-
ScannedGenericBeanDefinition definition = (ScannedGenericBeanDefinition) it.next();
308+
for (BeanDefinition candidate : candidates) {
309+
ScannedGenericBeanDefinition definition = (ScannedGenericBeanDefinition) candidate;
282310
if (beanClass.getName().equals(definition.getBeanClassName())) {
283311
return true;
284312
}
@@ -293,9 +321,26 @@ private static class DefaultProfileAnnotatedComponent {
293321
static final String BEAN_NAME = "defaultProfileAnnotatedComponent";
294322
}
295323

296-
@Profile({TEST_DEFAULT_PROFILE_NAME,"dev"})
324+
@Profile({TEST_DEFAULT_PROFILE_NAME, "dev"})
297325
@Component(DefaultAndDevProfileAnnotatedComponent.BEAN_NAME)
298326
private static class DefaultAndDevProfileAnnotatedComponent {
299327
static final String BEAN_NAME = "defaultAndDevProfileAnnotatedComponent";
300328
}
329+
330+
@DefaultProfile @DevProfile
331+
@Component(MetaProfileAnnotatedComponent.BEAN_NAME)
332+
private static class MetaProfileAnnotatedComponent {
333+
static final String BEAN_NAME = "metaProfileAnnotatedComponent";
334+
}
335+
336+
@Profile(TEST_DEFAULT_PROFILE_NAME)
337+
@Retention(RetentionPolicy.RUNTIME)
338+
public @interface DefaultProfile {
339+
}
340+
341+
@Profile("dev")
342+
@Retention(RetentionPolicy.RUNTIME)
343+
public @interface DevProfile {
344+
}
345+
301346
}

0 commit comments

Comments
 (0)