Skip to content

Commit 1d8a3e1

Browse files
committed
BeanFactoryAnnotationUtils searches on bean implementation classes and meta-annotations as well
Issue: SPR-13819 Issue: SPR-13452
1 parent 7d0ebdd commit 1d8a3e1

File tree

6 files changed

+118
-7
lines changed

6 files changed

+118
-7
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/annotation/BeanFactoryAnnotationUtils.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.springframework.beans.factory.support.AbstractBeanDefinition;
2727
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
2828
import org.springframework.beans.factory.support.RootBeanDefinition;
29+
import org.springframework.core.annotation.AnnotationUtils;
2930
import org.springframework.util.ObjectUtils;
3031

3132
/**
@@ -113,6 +114,7 @@ private static boolean isQualifierMatch(String qualifier, String beanName, Confi
113114
if (bf.containsBean(beanName)) {
114115
try {
115116
BeanDefinition bd = bf.getMergedBeanDefinition(beanName);
117+
// Explicit qualifier metadata on bean definition? (typically in XML definition)
116118
if (bd instanceof AbstractBeanDefinition) {
117119
AbstractBeanDefinition abd = (AbstractBeanDefinition) bd;
118120
AutowireCandidateQualifier candidate = abd.getQualifier(Qualifier.class.getName());
@@ -121,15 +123,24 @@ private static boolean isQualifierMatch(String qualifier, String beanName, Confi
121123
return true;
122124
}
123125
}
126+
// Corresponding qualifier on factory method? (typically in configuration class)
124127
if (bd instanceof RootBeanDefinition) {
125128
Method factoryMethod = ((RootBeanDefinition) bd).getResolvedFactoryMethod();
126129
if (factoryMethod != null) {
127-
Qualifier targetAnnotation = factoryMethod.getAnnotation(Qualifier.class);
128-
if (targetAnnotation != null && qualifier.equals(targetAnnotation.value())) {
129-
return true;
130+
Qualifier targetAnnotation = AnnotationUtils.getAnnotation(factoryMethod, Qualifier.class);
131+
if (targetAnnotation != null) {
132+
return qualifier.equals(targetAnnotation.value());
130133
}
131134
}
132135
}
136+
// Corresponding qualifier on bean implementation class? (for custom user types)
137+
Class<?> beanType = bf.getType(beanName);
138+
if (beanType != null) {
139+
Qualifier targetAnnotation = AnnotationUtils.getAnnotation(beanType, Qualifier.class);
140+
if (targetAnnotation != null) {
141+
return qualifier.equals(targetAnnotation.value());
142+
}
143+
}
133144
}
134145
catch (NoSuchBeanDefinitionException ex) {
135146
// Ignore - can't compare qualifiers for a manually registered singleton object

spring-tx/src/test/java/org/springframework/transaction/config/AnnotationDrivenTests.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020

2121
import org.aopalliance.intercept.MethodInterceptor;
2222
import org.aopalliance.intercept.MethodInvocation;
23-
2423
import org.junit.Test;
2524

2625
import org.springframework.aop.support.AopUtils;
26+
import org.springframework.beans.factory.support.RootBeanDefinition;
2727
import org.springframework.context.ApplicationContext;
2828
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
2929
import org.springframework.context.support.ClassPathXmlApplicationContext;
@@ -47,8 +47,16 @@ public void withProxyTargetClass() throws Exception {
4747

4848
@Test
4949
public void withConfigurationClass() throws Exception {
50+
ApplicationContext parent = new AnnotationConfigApplicationContext(TransactionManagerConfiguration.class);
51+
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"annotationDrivenConfigurationClassTests.xml"}, getClass(), parent);
52+
doTestWithMultipleTransactionManagers(context);
53+
}
54+
55+
@Test
56+
public void withAnnotatedTransactionManagers() throws Exception {
5057
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext();
51-
parent.register(TransactionManagerConfiguration.class);
58+
parent.registerBeanDefinition("transactionManager1", new RootBeanDefinition(SynchTransactionManager.class));
59+
parent.registerBeanDefinition("transactionManager2", new RootBeanDefinition(NoSynchTransactionManager.class));
5260
parent.refresh();
5361
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"annotationDrivenConfigurationClassTests.xml"}, getClass(), parent);
5462
doTestWithMultipleTransactionManagers(context);
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2002-2015 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.transaction.config;
18+
19+
import java.lang.annotation.Retention;
20+
import java.lang.annotation.RetentionPolicy;
21+
22+
import org.springframework.beans.factory.annotation.Qualifier;
23+
24+
/**
25+
* @author Juergen Hoeller
26+
*/
27+
@Qualifier("noSynch")
28+
@Retention(RetentionPolicy.RUNTIME)
29+
public @interface NoSynch {
30+
31+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright 2002-2015 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.transaction.config;
18+
19+
import org.springframework.tests.transaction.CallCountingTransactionManager;
20+
21+
/**
22+
* @author Juergen Hoeller
23+
*/
24+
@NoSynch
25+
@SuppressWarnings("serial")
26+
public class NoSynchTransactionManager extends CallCountingTransactionManager {
27+
28+
public NoSynchTransactionManager() {
29+
setTransactionSynchronization(CallCountingTransactionManager.SYNCHRONIZATION_NEVER);
30+
}
31+
32+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2002-2015 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.transaction.config;
18+
19+
import org.springframework.beans.factory.annotation.Qualifier;
20+
import org.springframework.tests.transaction.CallCountingTransactionManager;
21+
22+
/**
23+
* @author Juergen Hoeller
24+
*/
25+
@Qualifier("synch")
26+
@SuppressWarnings("serial")
27+
public class SynchTransactionManager extends CallCountingTransactionManager {
28+
29+
}

spring-tx/src/test/java/org/springframework/transaction/config/TransactionManagerConfiguration.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@ public PlatformTransactionManager transactionManager1() {
3535
}
3636

3737
@Bean
38-
@Qualifier("noSynch")
38+
@NoSynch
3939
public PlatformTransactionManager transactionManager2() {
4040
CallCountingTransactionManager tm = new CallCountingTransactionManager();
4141
tm.setTransactionSynchronization(CallCountingTransactionManager.SYNCHRONIZATION_NEVER);

0 commit comments

Comments
 (0)