Merge branch '5.3.x'
# Conflicts: # build.gradle # src/docs/asciidoc/integration.adoc
This commit is contained in:
commit
bfdb93b406
|
|
@ -45,9 +45,10 @@ import org.springframework.core.NativeDetector;
|
||||||
* @see AdvisedSupport#setProxyTargetClass
|
* @see AdvisedSupport#setProxyTargetClass
|
||||||
* @see AdvisedSupport#setInterfaces
|
* @see AdvisedSupport#setInterfaces
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
|
||||||
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
|
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 7930414337282325166L;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
|
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
|
||||||
|
|
|
||||||
|
|
@ -421,11 +421,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||||
* are unaffected by such changes.
|
* are unaffected by such changes.
|
||||||
*/
|
*/
|
||||||
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
|
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
|
||||||
if (this.advisorChainInitialized) {
|
if (!this.advisorChainInitialized && !ObjectUtils.isEmpty(this.interceptorNames)) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
|
|
||||||
if (this.beanFactory == null) {
|
if (this.beanFactory == null) {
|
||||||
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
|
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
|
||||||
"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
|
"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
|
||||||
|
|
@ -464,10 +460,10 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||||
addAdvisorOnChainCreation(advice);
|
addAdvisorOnChainCreation(advice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
this.advisorChainInitialized = true;
|
this.advisorChainInitialized = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2020 the original author or authors.
|
* Copyright 2002-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -353,9 +353,31 @@ public interface ListableBeanFactory extends BeanFactory {
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
* @see #getBeanNamesForAnnotation
|
* @see #getBeanNamesForAnnotation
|
||||||
* @see #getBeansWithAnnotation
|
* @see #getBeansWithAnnotation
|
||||||
|
* @see #getType(String)
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
|
<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
|
||||||
throws NoSuchBeanDefinitionException;
|
throws NoSuchBeanDefinitionException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find an {@link Annotation} of {@code annotationType} on the specified bean,
|
||||||
|
* traversing its interfaces and super classes if no annotation can be found on
|
||||||
|
* the given class itself, as well as checking the bean's factory method (if any).
|
||||||
|
* @param beanName the name of the bean to look for annotations on
|
||||||
|
* @param annotationType the type of annotation to look for
|
||||||
|
* (at class, interface or factory method level of the specified bean)
|
||||||
|
* @param allowFactoryBeanInit whether a {@code FactoryBean} may get initialized
|
||||||
|
* just for the purpose of determining its object type
|
||||||
|
* @return the annotation of the given type if found, or {@code null} otherwise
|
||||||
|
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
|
||||||
|
* @since 5.3.14
|
||||||
|
* @see #getBeanNamesForAnnotation
|
||||||
|
* @see #getBeansWithAnnotation
|
||||||
|
* @see #getType(String, boolean)
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
<A extends Annotation> A findAnnotationOnBean(
|
||||||
|
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
|
||||||
|
throws NoSuchBeanDefinitionException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -719,14 +719,23 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
|
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
|
||||||
throws NoSuchBeanDefinitionException {
|
throws NoSuchBeanDefinitionException {
|
||||||
|
|
||||||
return findMergedAnnotationOnBean(beanName, annotationType)
|
return findAnnotationOnBean(beanName, annotationType, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public <A extends Annotation> A findAnnotationOnBean(
|
||||||
|
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
|
||||||
|
throws NoSuchBeanDefinitionException {
|
||||||
|
|
||||||
|
return findMergedAnnotationOnBean(beanName, annotationType, allowFactoryBeanInit)
|
||||||
.synthesize(MergedAnnotation::isPresent).orElse(null);
|
.synthesize(MergedAnnotation::isPresent).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <A extends Annotation> MergedAnnotation<A> findMergedAnnotationOnBean(
|
private <A extends Annotation> MergedAnnotation<A> findMergedAnnotationOnBean(
|
||||||
String beanName, Class<A> annotationType) {
|
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit) {
|
||||||
|
|
||||||
Class<?> beanType = getType(beanName);
|
Class<?> beanType = getType(beanName, allowFactoryBeanInit);
|
||||||
if (beanType != null) {
|
if (beanType != null) {
|
||||||
MergedAnnotation<A> annotation =
|
MergedAnnotation<A> annotation =
|
||||||
MergedAnnotations.from(beanType, SearchStrategy.TYPE_HIERARCHY).get(annotationType);
|
MergedAnnotations.from(beanType, SearchStrategy.TYPE_HIERARCHY).get(annotationType);
|
||||||
|
|
|
||||||
|
|
@ -459,7 +459,16 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
|
||||||
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
|
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
|
||||||
throws NoSuchBeanDefinitionException {
|
throws NoSuchBeanDefinitionException {
|
||||||
|
|
||||||
Class<?> beanType = getType(beanName);
|
return findAnnotationOnBean(beanName, annotationType, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public <A extends Annotation> A findAnnotationOnBean(
|
||||||
|
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
|
||||||
|
throws NoSuchBeanDefinitionException {
|
||||||
|
|
||||||
|
Class<?> beanType = getType(beanName, allowFactoryBeanInit);
|
||||||
return (beanType != null ? AnnotatedElementUtils.findMergedAnnotation(beanType, annotationType) : null);
|
return (beanType != null ? AnnotatedElementUtils.findMergedAnnotation(beanType, annotationType) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ import org.springframework.lang.Nullable;
|
||||||
* Subclass of Quartz's {@link JobStoreCMT} class that delegates to a Spring-managed
|
* Subclass of Quartz's {@link JobStoreCMT} class that delegates to a Spring-managed
|
||||||
* {@link DataSource} instead of using a Quartz-managed JDBC connection pool.
|
* {@link DataSource} instead of using a Quartz-managed JDBC connection pool.
|
||||||
* This JobStore will be used if SchedulerFactoryBean's "dataSource" property is set.
|
* This JobStore will be used if SchedulerFactoryBean's "dataSource" property is set.
|
||||||
|
* You may also configure it explicitly, possibly as a custom subclass of this class.
|
||||||
*
|
*
|
||||||
* <p>Supports both transactional and non-transactional DataSource access.
|
* <p>Supports both transactional and non-transactional DataSource access.
|
||||||
* With a non-XA DataSource and local Spring transactions, a single DataSource
|
* With a non-XA DataSource and local Spring transactions, a single DataSource
|
||||||
|
|
@ -58,6 +59,8 @@ import org.springframework.lang.Nullable;
|
||||||
* @since 1.1
|
* @since 1.1
|
||||||
* @see SchedulerFactoryBean#setDataSource
|
* @see SchedulerFactoryBean#setDataSource
|
||||||
* @see SchedulerFactoryBean#setNonTransactionalDataSource
|
* @see SchedulerFactoryBean#setNonTransactionalDataSource
|
||||||
|
* @see SchedulerFactoryBean#getConfigTimeDataSource()
|
||||||
|
* @see SchedulerFactoryBean#getConfigTimeNonTransactionalDataSource()
|
||||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection
|
* @see org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection
|
||||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection
|
* @see org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -310,9 +310,11 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the default {@link DataSource} to be used by the Scheduler.
|
* Set the default {@link DataSource} to be used by the Scheduler.
|
||||||
* If set, this will override corresponding settings in Quartz properties.
|
|
||||||
* <p>Note: If this is set, the Quartz settings should not define
|
* <p>Note: If this is set, the Quartz settings should not define
|
||||||
* a job store "dataSource" to avoid meaningless double configuration.
|
* a job store "dataSource" to avoid meaningless double configuration.
|
||||||
|
* Also, do not define a "org.quartz.jobStore.class" property at all.
|
||||||
|
* (You may explicitly define Spring's {@link LocalDataSourceJobStore}
|
||||||
|
* but that's the default when using this method anyway.)
|
||||||
* <p>A Spring-specific subclass of Quartz' JobStoreCMT will be used.
|
* <p>A Spring-specific subclass of Quartz' JobStoreCMT will be used.
|
||||||
* It is therefore strongly recommended to perform all operations on
|
* It is therefore strongly recommended to perform all operations on
|
||||||
* the Scheduler within Spring-managed (or plain JTA) transactions.
|
* the Scheduler within Spring-managed (or plain JTA) transactions.
|
||||||
|
|
|
||||||
|
|
@ -1309,6 +1309,16 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||||
return getBeanFactory().findAnnotationOnBean(beanName, annotationType);
|
return getBeanFactory().findAnnotationOnBean(beanName, annotationType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public <A extends Annotation> A findAnnotationOnBean(
|
||||||
|
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
|
||||||
|
throws NoSuchBeanDefinitionException {
|
||||||
|
|
||||||
|
assertBeanFactoryActive();
|
||||||
|
return getBeanFactory().findAnnotationOnBean(beanName, annotationType, allowFactoryBeanInit);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
// Implementation of HierarchicalBeanFactory interface
|
// Implementation of HierarchicalBeanFactory interface
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2020 the original author or authors.
|
* Copyright 2002-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -65,10 +65,10 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
import static org.assertj.core.api.Assertions.assertThatIOException;
|
import static org.assertj.core.api.Assertions.assertThatIOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 13.03.2003
|
|
||||||
* @author Rod Johnson
|
* @author Rod Johnson
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @author Chris Beams
|
* @author Chris Beams
|
||||||
|
* @since 13.03.2003
|
||||||
*/
|
*/
|
||||||
public class ProxyFactoryBeanTests {
|
public class ProxyFactoryBeanTests {
|
||||||
|
|
||||||
|
|
@ -638,15 +638,45 @@ public class ProxyFactoryBeanTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDetectsInterfaces() throws Exception {
|
public void testDetectsInterfaces() {
|
||||||
ProxyFactoryBean fb = new ProxyFactoryBean();
|
ProxyFactoryBean fb = new ProxyFactoryBean();
|
||||||
fb.setTarget(new TestBean());
|
fb.setTarget(new TestBean());
|
||||||
fb.addAdvice(new DebugInterceptor());
|
fb.addAdvice(new DebugInterceptor());
|
||||||
fb.setBeanFactory(new DefaultListableBeanFactory());
|
fb.setBeanFactory(new DefaultListableBeanFactory());
|
||||||
|
|
||||||
ITestBean proxy = (ITestBean) fb.getObject();
|
ITestBean proxy = (ITestBean) fb.getObject();
|
||||||
assertThat(AopUtils.isJdkDynamicProxy(proxy)).isTrue();
|
assertThat(AopUtils.isJdkDynamicProxy(proxy)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithInterceptorNames() {
|
||||||
|
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||||
|
bf.registerSingleton("debug", new DebugInterceptor());
|
||||||
|
|
||||||
|
ProxyFactoryBean fb = new ProxyFactoryBean();
|
||||||
|
fb.setTarget(new TestBean());
|
||||||
|
fb.setInterceptorNames("debug");
|
||||||
|
fb.setBeanFactory(bf);
|
||||||
|
|
||||||
|
Advised proxy = (Advised) fb.getObject();
|
||||||
|
assertThat(proxy.getAdvisorCount()).isEqualTo(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithLateInterceptorNames() {
|
||||||
|
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||||
|
bf.registerSingleton("debug", new DebugInterceptor());
|
||||||
|
|
||||||
|
ProxyFactoryBean fb = new ProxyFactoryBean();
|
||||||
|
fb.setTarget(new TestBean());
|
||||||
|
fb.setBeanFactory(bf);
|
||||||
|
fb.getObject();
|
||||||
|
|
||||||
|
fb.setInterceptorNames("debug");
|
||||||
|
Advised proxy = (Advised) fb.getObject();
|
||||||
|
assertThat(proxy.getAdvisorCount()).isEqualTo(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fires only on void methods. Saves list of methods intercepted.
|
* Fires only on void methods. Saves list of methods intercepted.
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,19 @@ public class EnableCachingIntegrationTests {
|
||||||
assertCacheHit(key, value, cache);
|
assertCacheHit(key, value, cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void barServiceWithCacheableInterfaceCglib() {
|
||||||
|
this.context = new AnnotationConfigApplicationContext(BarConfigCglib.class);
|
||||||
|
BarService service = this.context.getBean(BarService.class);
|
||||||
|
Cache cache = getCache();
|
||||||
|
|
||||||
|
Object key = new Object();
|
||||||
|
assertCacheMiss(key, cache);
|
||||||
|
|
||||||
|
Object value = service.getSimple(key);
|
||||||
|
assertCacheHit(key, value, cache);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void beanConditionOff() {
|
public void beanConditionOff() {
|
||||||
this.context = new AnnotationConfigApplicationContext(BeanConditionConfig.class);
|
this.context = new AnnotationConfigApplicationContext(BeanConditionConfig.class);
|
||||||
|
|
@ -223,6 +236,36 @@ public class EnableCachingIntegrationTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@Import(SharedConfig.class)
|
||||||
|
@EnableCaching(proxyTargetClass = true)
|
||||||
|
static class BarConfigCglib {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public BarService barService() {
|
||||||
|
return new BarServiceImpl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface BarService {
|
||||||
|
|
||||||
|
@Cacheable(cacheNames = "testCache")
|
||||||
|
Object getSimple(Object key);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static class BarServiceImpl implements BarService {
|
||||||
|
|
||||||
|
private final AtomicLong counter = new AtomicLong();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getSimple(Object key) {
|
||||||
|
return this.counter.getAndIncrement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Import(FooConfig.class)
|
@Import(FooConfig.class)
|
||||||
@EnableCaching
|
@EnableCaching
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ class ThreadPoolExecutorFactoryBeanTests {
|
||||||
verify(threadPoolExecutor).prestartAllCoreThreads();
|
verify(threadPoolExecutor).prestartAllCoreThreads();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
static class ExecutorConfig {
|
static class ExecutorConfig {
|
||||||
|
|
||||||
|
|
@ -83,9 +84,10 @@ class ThreadPoolExecutorFactoryBeanTests {
|
||||||
ThreadPoolExecutorFactoryBean executor() {
|
ThreadPoolExecutorFactoryBean executor() {
|
||||||
return new ThreadPoolExecutorFactoryBean();
|
return new ThreadPoolExecutorFactoryBean();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
private static class TestThreadPoolExecutorFactoryBean extends ThreadPoolExecutorFactoryBean {
|
private static class TestThreadPoolExecutorFactoryBean extends ThreadPoolExecutorFactoryBean {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import java.util.regex.Pattern;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility methods for formatting and logging messages.
|
* Utility methods for formatting and logging messages.
|
||||||
|
|
@ -71,10 +72,10 @@ public abstract class LogFormatUtils {
|
||||||
}
|
}
|
||||||
String result;
|
String result;
|
||||||
try {
|
try {
|
||||||
result = value.toString();
|
result = ObjectUtils.nullSafeToString(value);
|
||||||
}
|
}
|
||||||
catch (Throwable ex) {
|
catch (Throwable ex) {
|
||||||
result = ex.toString();
|
result = ObjectUtils.nullSafeToString(ex);
|
||||||
}
|
}
|
||||||
if (maxLength != -1) {
|
if (maxLength != -1) {
|
||||||
result = (result.length() > maxLength ? result.substring(0, maxLength) + " (truncated)..." : result);
|
result = (result.length() > maxLength ? result.substring(0, maxLength) + " (truncated)..." : result);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2020 the original author or authors.
|
* Copyright 2002-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -1159,6 +1159,20 @@ class ResolvableTypeTests {
|
||||||
assertThatResolvableType(complex4).isNotAssignableFrom(complex3);
|
assertThatResolvableType(complex4).isNotAssignableFrom(complex3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void identifyTypeVariable() throws Exception {
|
||||||
|
Method method = ClassArguments.class.getMethod("typedArgumentFirst", Class.class, Class.class, Class.class);
|
||||||
|
ResolvableType returnType = ResolvableType.forMethodReturnType(method, ClassArguments.class);
|
||||||
|
|
||||||
|
ResolvableType arg0 = ResolvableType.forMethodParameter(method, 0, ClassArguments.class);
|
||||||
|
ResolvableType arg1 = ResolvableType.forMethodParameter(method, 1, ClassArguments.class);
|
||||||
|
ResolvableType arg2 = ResolvableType.forMethodParameter(method, 2, ClassArguments.class);
|
||||||
|
|
||||||
|
assertThat(returnType.getType().equals(arg0.as(Class.class).getGeneric(0).getType())).isTrue();
|
||||||
|
assertThat(returnType.getType().equals(arg1.as(Class.class).getGeneric(0).getType())).isFalse();
|
||||||
|
assertThat(returnType.getType().equals(arg2.as(Class.class).getGeneric(0).getType())).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void hashCodeAndEquals() throws Exception {
|
void hashCodeAndEquals() throws Exception {
|
||||||
ResolvableType forClass = ResolvableType.forClass(List.class);
|
ResolvableType forClass = ResolvableType.forClass(List.class);
|
||||||
|
|
@ -1427,6 +1441,10 @@ class ResolvableTypeTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface TypedMethods extends Methods<String> {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static class AssignmentBase<O, C, S> {
|
static class AssignmentBase<O, C, S> {
|
||||||
|
|
||||||
public O o;
|
public O o;
|
||||||
|
|
@ -1479,7 +1497,9 @@ class ResolvableTypeTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface TypedMethods extends Methods<String> {
|
interface ClassArguments {
|
||||||
|
|
||||||
|
<T> T typedArgumentFirst(Class<T> arg0, Class<?> arg1, Class<Object> arg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2020 the original author or authors.
|
* Copyright 2002-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -314,6 +314,15 @@ class StubWebApplicationContext implements WebApplicationContext {
|
||||||
return this.beanFactory.findAnnotationOnBean(beanName, annotationType);
|
return this.beanFactory.findAnnotationOnBean(beanName, annotationType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public <A extends Annotation> A findAnnotationOnBean(
|
||||||
|
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
|
||||||
|
throws NoSuchBeanDefinitionException {
|
||||||
|
|
||||||
|
return this.beanFactory.findAnnotationOnBean(beanName, annotationType, allowFactoryBeanInit);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
// Implementation of HierarchicalBeanFactory interface
|
// Implementation of HierarchicalBeanFactory interface
|
||||||
|
|
|
||||||
|
|
@ -5385,6 +5385,7 @@ You can use these macros instead of the six-digit value, thus: `@Scheduled(cron
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[[scheduling-quartz]]
|
[[scheduling-quartz]]
|
||||||
=== Using the Quartz Scheduler
|
=== Using the Quartz Scheduler
|
||||||
|
|
||||||
|
|
@ -5440,7 +5441,6 @@ has it applied automatically:
|
||||||
protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {
|
protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {
|
||||||
// do the actual work
|
// do the actual work
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -5560,11 +5560,19 @@ seconds and one running every morning at 6 AM. To finalize everything, we need t
|
||||||
</bean>
|
</bean>
|
||||||
----
|
----
|
||||||
|
|
||||||
More properties are available for the `SchedulerFactoryBean`, such as the calendars
|
More properties are available for the `SchedulerFactoryBean`, such as the calendars used by the
|
||||||
used by the job details, properties to customize Quartz with, and others. See the
|
job details, properties to customize Quartz with, and a Spring-provided JDBC DataSource. See
|
||||||
{api-spring-framework}/scheduling/quartz/SchedulerFactoryBean.html[`SchedulerFactoryBean`]
|
the {api-spring-framework}/scheduling/quartz/SchedulerFactoryBean.html[`SchedulerFactoryBean`]
|
||||||
javadoc for more information.
|
javadoc for more information.
|
||||||
|
|
||||||
|
NOTE: `SchedulerFactoryBean` also recognizes a `quartz.properties` file in the classpath,
|
||||||
|
based on Quartz property keys, as with regular Quartz configuration. Please note that many
|
||||||
|
`SchedulerFactoryBean` settings interact with common Quartz settings in the properties file;
|
||||||
|
it is therefore not recommended to specify values at both levels. For example, do not set
|
||||||
|
an "org.quartz.jobStore.class" property if you mean to rely on a Spring-provided DataSource,
|
||||||
|
or specify an `org.springframework.scheduling.quartz.LocalDataSourceJobStore` variant which
|
||||||
|
is a full-fledged replacement for the standard `org.quartz.impl.jdbcjobstore.JobStoreTX`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -5866,7 +5874,6 @@ is updated in the cache. The following example shows how to use the `sync` attri
|
||||||
----
|
----
|
||||||
<1> Using the `sync` attribute.
|
<1> Using the `sync` attribute.
|
||||||
|
|
||||||
|
|
||||||
NOTE: This is an optional feature, and your favorite cache library may not support it.
|
NOTE: This is an optional feature, and your favorite cache library may not support it.
|
||||||
All `CacheManager` implementations provided by the core framework support it. See the
|
All `CacheManager` implementations provided by the core framework support it. See the
|
||||||
documentation of your cache provider for more details.
|
documentation of your cache provider for more details.
|
||||||
|
|
@ -6024,7 +6031,6 @@ all entries from the `books` cache:
|
||||||
----
|
----
|
||||||
<1> Using the `allEntries` attribute to evict all entries from the cache.
|
<1> Using the `allEntries` attribute to evict all entries from the cache.
|
||||||
|
|
||||||
|
|
||||||
This option comes in handy when an entire cache region needs to be cleared out.
|
This option comes in handy when an entire cache region needs to be cleared out.
|
||||||
Rather than evicting each entry (which would take a long time, since it is inefficient),
|
Rather than evicting each entry (which would take a long time, since it is inefficient),
|
||||||
all the entries are removed in one operation, as the preceding example shows.
|
all the entries are removed in one operation, as the preceding example shows.
|
||||||
|
|
@ -6083,7 +6089,6 @@ comes into play. The following examples uses `@CacheConfig` to set the name of t
|
||||||
----
|
----
|
||||||
<1> Using `@CacheConfig` to set the name of the cache.
|
<1> Using `@CacheConfig` to set the name of the cache.
|
||||||
|
|
||||||
|
|
||||||
`@CacheConfig` is a class-level annotation that allows sharing the cache names,
|
`@CacheConfig` is a class-level annotation that allows sharing the cache names,
|
||||||
the custom `KeyGenerator`, the custom `CacheManager`, and the custom `CacheResolver`.
|
the custom `KeyGenerator`, the custom `CacheManager`, and the custom `CacheResolver`.
|
||||||
Placing this annotation on the class does not turn on any caching operation.
|
Placing this annotation on the class does not turn on any caching operation.
|
||||||
|
|
@ -6224,11 +6229,11 @@ if you need to annotate non-public methods, as it changes the bytecode itself.
|
||||||
****
|
****
|
||||||
|
|
||||||
TIP: Spring recommends that you only annotate concrete classes (and methods of concrete
|
TIP: Spring recommends that you only annotate concrete classes (and methods of concrete
|
||||||
classes) with the `@Cache{asterisk}` annotation, as opposed to annotating interfaces.
|
classes) with the `@Cache{asterisk}` annotations, as opposed to annotating interfaces.
|
||||||
You certainly can place the `@Cache{asterisk}` annotation on an interface (or an interface
|
You certainly can place an `@Cache{asterisk}` annotation on an interface (or an interface
|
||||||
method), but this works only as you would expect it to if you use the proxy mode (`mode="proxy"`).
|
method), but this works only if you use the proxy mode (`mode="proxy"`). If you use the
|
||||||
If you use the weaving-based aspect (`mode="aspectj"`), the caching settings are not
|
weaving-based aspect (`mode="aspectj"`), the caching settings are not recognized on
|
||||||
recognized by weaving infrastructure.
|
interface-level declarations by the weaving infrastructure.
|
||||||
|
|
||||||
NOTE: In proxy mode (the default), only external method calls coming in through the
|
NOTE: In proxy mode (the default), only external method calls coming in through the
|
||||||
proxy are intercepted. This means that self-invocation (in effect, a method within the
|
proxy are intercepted. This means that self-invocation (in effect, a method within the
|
||||||
|
|
@ -6365,7 +6370,6 @@ to customize the factory for each cache operation, as the following example show
|
||||||
----
|
----
|
||||||
<1> Customizing the factory for this operation.
|
<1> Customizing the factory for this operation.
|
||||||
|
|
||||||
|
|
||||||
NOTE: For all referenced classes, Spring tries to locate a bean with the given type.
|
NOTE: For all referenced classes, Spring tries to locate a bean with the given type.
|
||||||
If more than one match exists, a new instance is created and can use the regular
|
If more than one match exists, a new instance is created and can use the regular
|
||||||
bean lifecycle callbacks, such as dependency injection.
|
bean lifecycle callbacks, such as dependency injection.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue