Skip to content

Commit bfdb93b

Browse files
committed
Merge branch '5.3.x'
# Conflicts: # build.gradle # src/docs/asciidoc/integration.adoc
2 parents ea9b8c1 + 0ebb1c5 commit bfdb93b

File tree

15 files changed

+198
-37
lines changed

15 files changed

+198
-37
lines changed

spring-aop/src/main/java/org/springframework/aop/framework/DefaultAopProxyFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,10 @@
4545
* @see AdvisedSupport#setProxyTargetClass
4646
* @see AdvisedSupport#setInterfaces
4747
*/
48-
@SuppressWarnings("serial")
4948
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
5049

50+
private static final long serialVersionUID = 7930414337282325166L;
51+
5152

5253
@Override
5354
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {

spring-aop/src/main/java/org/springframework/aop/framework/ProxyFactoryBean.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -421,11 +421,7 @@ private boolean isNamedBeanAnAdvisorOrAdvice(String beanName) {
421421
* are unaffected by such changes.
422422
*/
423423
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
424-
if (this.advisorChainInitialized) {
425-
return;
426-
}
427-
428-
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
424+
if (!this.advisorChainInitialized && !ObjectUtils.isEmpty(this.interceptorNames)) {
429425
if (this.beanFactory == null) {
430426
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
431427
"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
@@ -464,9 +460,9 @@ private synchronized void initializeAdvisorChain() throws AopConfigException, Be
464460
addAdvisorOnChainCreation(advice);
465461
}
466462
}
467-
}
468463

469-
this.advisorChainInitialized = true;
464+
this.advisorChainInitialized = true;
465+
}
470466
}
471467

472468

spring-beans/src/main/java/org/springframework/beans/factory/ListableBeanFactory.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2021 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.
@@ -353,9 +353,31 @@ <T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSin
353353
* @since 3.0
354354
* @see #getBeanNamesForAnnotation
355355
* @see #getBeansWithAnnotation
356+
* @see #getType(String)
356357
*/
357358
@Nullable
358359
<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
359360
throws NoSuchBeanDefinitionException;
360361

362+
/**
363+
* Find an {@link Annotation} of {@code annotationType} on the specified bean,
364+
* traversing its interfaces and super classes if no annotation can be found on
365+
* the given class itself, as well as checking the bean's factory method (if any).
366+
* @param beanName the name of the bean to look for annotations on
367+
* @param annotationType the type of annotation to look for
368+
* (at class, interface or factory method level of the specified bean)
369+
* @param allowFactoryBeanInit whether a {@code FactoryBean} may get initialized
370+
* just for the purpose of determining its object type
371+
* @return the annotation of the given type if found, or {@code null} otherwise
372+
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
373+
* @since 5.3.14
374+
* @see #getBeanNamesForAnnotation
375+
* @see #getBeansWithAnnotation
376+
* @see #getType(String, boolean)
377+
*/
378+
@Nullable
379+
<A extends Annotation> A findAnnotationOnBean(
380+
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
381+
throws NoSuchBeanDefinitionException;
382+
361383
}

spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -719,14 +719,23 @@ public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> an
719719
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
720720
throws NoSuchBeanDefinitionException {
721721

722-
return findMergedAnnotationOnBean(beanName, annotationType)
722+
return findAnnotationOnBean(beanName, annotationType, true);
723+
}
724+
725+
@Override
726+
@Nullable
727+
public <A extends Annotation> A findAnnotationOnBean(
728+
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
729+
throws NoSuchBeanDefinitionException {
730+
731+
return findMergedAnnotationOnBean(beanName, annotationType, allowFactoryBeanInit)
723732
.synthesize(MergedAnnotation::isPresent).orElse(null);
724733
}
725734

726735
private <A extends Annotation> MergedAnnotation<A> findMergedAnnotationOnBean(
727-
String beanName, Class<A> annotationType) {
736+
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit) {
728737

729-
Class<?> beanType = getType(beanName);
738+
Class<?> beanType = getType(beanName, allowFactoryBeanInit);
730739
if (beanType != null) {
731740
MergedAnnotation<A> annotation =
732741
MergedAnnotations.from(beanType, SearchStrategy.TYPE_HIERARCHY).get(annotationType);

spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,16 @@ public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> an
459459
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
460460
throws NoSuchBeanDefinitionException {
461461

462-
Class<?> beanType = getType(beanName);
462+
return findAnnotationOnBean(beanName, annotationType, true);
463+
}
464+
465+
@Override
466+
@Nullable
467+
public <A extends Annotation> A findAnnotationOnBean(
468+
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
469+
throws NoSuchBeanDefinitionException {
470+
471+
Class<?> beanType = getType(beanName, allowFactoryBeanInit);
463472
return (beanType != null ? AnnotatedElementUtils.findMergedAnnotation(beanType, annotationType) : null);
464473
}
465474

spring-context-support/src/main/java/org/springframework/scheduling/quartz/LocalDataSourceJobStore.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
* Subclass of Quartz's {@link JobStoreCMT} class that delegates to a Spring-managed
4040
* {@link DataSource} instead of using a Quartz-managed JDBC connection pool.
4141
* This JobStore will be used if SchedulerFactoryBean's "dataSource" property is set.
42+
* You may also configure it explicitly, possibly as a custom subclass of this class.
4243
*
4344
* <p>Supports both transactional and non-transactional DataSource access.
4445
* With a non-XA DataSource and local Spring transactions, a single DataSource
@@ -58,6 +59,8 @@
5859
* @since 1.1
5960
* @see SchedulerFactoryBean#setDataSource
6061
* @see SchedulerFactoryBean#setNonTransactionalDataSource
62+
* @see SchedulerFactoryBean#getConfigTimeDataSource()
63+
* @see SchedulerFactoryBean#getConfigTimeNonTransactionalDataSource()
6164
* @see org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection
6265
* @see org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection
6366
*/

spring-context-support/src/main/java/org/springframework/scheduling/quartz/SchedulerFactoryBean.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,9 +310,11 @@ public void setTaskExecutor(Executor taskExecutor) {
310310

311311
/**
312312
* Set the default {@link DataSource} to be used by the Scheduler.
313-
* If set, this will override corresponding settings in Quartz properties.
314313
* <p>Note: If this is set, the Quartz settings should not define
315314
* a job store "dataSource" to avoid meaningless double configuration.
315+
* Also, do not define a "org.quartz.jobStore.class" property at all.
316+
* (You may explicitly define Spring's {@link LocalDataSourceJobStore}
317+
* but that's the default when using this method anyway.)
316318
* <p>A Spring-specific subclass of Quartz' JobStoreCMT will be used.
317319
* It is therefore strongly recommended to perform all operations on
318320
* the Scheduler within Spring-managed (or plain JTA) transactions.

spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,6 +1309,16 @@ public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> a
13091309
return getBeanFactory().findAnnotationOnBean(beanName, annotationType);
13101310
}
13111311

1312+
@Override
1313+
@Nullable
1314+
public <A extends Annotation> A findAnnotationOnBean(
1315+
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
1316+
throws NoSuchBeanDefinitionException {
1317+
1318+
assertBeanFactoryActive();
1319+
return getBeanFactory().findAnnotationOnBean(beanName, annotationType, allowFactoryBeanInit);
1320+
}
1321+
13121322

13131323
//---------------------------------------------------------------------
13141324
// Implementation of HierarchicalBeanFactory interface

spring-context/src/test/java/org/springframework/aop/framework/ProxyFactoryBeanTests.java

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2021 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.
@@ -65,10 +65,10 @@
6565
import static org.assertj.core.api.Assertions.assertThatIOException;
6666

6767
/**
68-
* @since 13.03.2003
6968
* @author Rod Johnson
7069
* @author Juergen Hoeller
7170
* @author Chris Beams
71+
* @since 13.03.2003
7272
*/
7373
public class ProxyFactoryBeanTests {
7474

@@ -633,20 +633,50 @@ public void testFrozenFactoryBean() {
633633
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
634634
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(new ClassPathResource(FROZEN_CONTEXT, CLASS));
635635

636-
Advised advised = (Advised)bf.getBean("frozen");
636+
Advised advised = (Advised) bf.getBean("frozen");
637637
assertThat(advised.isFrozen()).as("The proxy should be frozen").isTrue();
638638
}
639639

640640
@Test
641-
public void testDetectsInterfaces() throws Exception {
641+
public void testDetectsInterfaces() {
642642
ProxyFactoryBean fb = new ProxyFactoryBean();
643643
fb.setTarget(new TestBean());
644644
fb.addAdvice(new DebugInterceptor());
645645
fb.setBeanFactory(new DefaultListableBeanFactory());
646+
646647
ITestBean proxy = (ITestBean) fb.getObject();
647648
assertThat(AopUtils.isJdkDynamicProxy(proxy)).isTrue();
648649
}
649650

651+
@Test
652+
public void testWithInterceptorNames() {
653+
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
654+
bf.registerSingleton("debug", new DebugInterceptor());
655+
656+
ProxyFactoryBean fb = new ProxyFactoryBean();
657+
fb.setTarget(new TestBean());
658+
fb.setInterceptorNames("debug");
659+
fb.setBeanFactory(bf);
660+
661+
Advised proxy = (Advised) fb.getObject();
662+
assertThat(proxy.getAdvisorCount()).isEqualTo(1);
663+
}
664+
665+
@Test
666+
public void testWithLateInterceptorNames() {
667+
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
668+
bf.registerSingleton("debug", new DebugInterceptor());
669+
670+
ProxyFactoryBean fb = new ProxyFactoryBean();
671+
fb.setTarget(new TestBean());
672+
fb.setBeanFactory(bf);
673+
fb.getObject();
674+
675+
fb.setInterceptorNames("debug");
676+
Advised proxy = (Advised) fb.getObject();
677+
assertThat(proxy.getAdvisorCount()).isEqualTo(1);
678+
}
679+
650680

651681
/**
652682
* Fires only on void methods. Saves list of methods intercepted.

spring-context/src/test/java/org/springframework/cache/config/EnableCachingIntegrationTests.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,19 @@ private void fooGetSimple(FooService service) {
9696
assertCacheHit(key, value, cache);
9797
}
9898

99+
@Test
100+
public void barServiceWithCacheableInterfaceCglib() {
101+
this.context = new AnnotationConfigApplicationContext(BarConfigCglib.class);
102+
BarService service = this.context.getBean(BarService.class);
103+
Cache cache = getCache();
104+
105+
Object key = new Object();
106+
assertCacheMiss(key, cache);
107+
108+
Object value = service.getSimple(key);
109+
assertCacheHit(key, value, cache);
110+
}
111+
99112
@Test
100113
public void beanConditionOff() {
101114
this.context = new AnnotationConfigApplicationContext(BeanConditionConfig.class);
@@ -223,6 +236,36 @@ public Object getSimple(Object key) {
223236
}
224237
}
225238

239+
@Configuration
240+
@Import(SharedConfig.class)
241+
@EnableCaching(proxyTargetClass = true)
242+
static class BarConfigCglib {
243+
244+
@Bean
245+
public BarService barService() {
246+
return new BarServiceImpl();
247+
}
248+
}
249+
250+
251+
interface BarService {
252+
253+
@Cacheable(cacheNames = "testCache")
254+
Object getSimple(Object key);
255+
}
256+
257+
258+
static class BarServiceImpl implements BarService {
259+
260+
private final AtomicLong counter = new AtomicLong();
261+
262+
@Override
263+
public Object getSimple(Object key) {
264+
return this.counter.getAndIncrement();
265+
}
266+
}
267+
268+
226269
@Configuration
227270
@Import(FooConfig.class)
228271
@EnableCaching

0 commit comments

Comments
 (0)