Merge branch '5.3.x'
# Conflicts: # spring-context-support/src/main/java/org/springframework/scheduling/commonj/WorkManagerTaskExecutor.java # spring-core/src/main/java/org/springframework/core/task/SimpleAsyncTaskExecutor.java # spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java # spring-tx/src/main/java/org/springframework/jca/work/SimpleTaskWorkManager.java # spring-tx/src/main/java/org/springframework/jca/work/WorkManagerTaskExecutor.java
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -1832,7 +1832,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
|
||||
}
|
||||
Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod);
|
||||
Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod, bean.getClass());
|
||||
|
||||
try {
|
||||
ReflectionUtils.makeAccessible(methodToInvoke);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -130,7 +130,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||
beanName + "' has a non-boolean parameter - not supported as destroy method");
|
||||
}
|
||||
}
|
||||
destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod);
|
||||
destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod, bean.getClass());
|
||||
}
|
||||
this.destroyMethod = destroyMethod;
|
||||
}
|
||||
@@ -223,9 +223,9 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||
invokeCustomDestroyMethod(this.destroyMethod);
|
||||
}
|
||||
else if (this.destroyMethodName != null) {
|
||||
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
|
||||
if (methodToInvoke != null) {
|
||||
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
|
||||
Method destroyMethod = determineDestroyMethod(this.destroyMethodName);
|
||||
if (destroyMethod != null) {
|
||||
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(destroyMethod, this.bean.getClass()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -76,6 +76,7 @@ public class SimpleThreadPoolTaskExecutor extends SimpleThreadPool
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public void execute(Runnable task, long startTimeout) {
|
||||
execute(task);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -147,6 +147,7 @@ public class ConcurrentTaskExecutor implements AsyncListenableTaskExecutor, Sche
|
||||
this.adaptedExecutor.execute(task);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public void execute(Runnable task, long startTimeout) {
|
||||
this.adaptedExecutor.execute(task, startTimeout);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -340,6 +340,7 @@ public class ThreadPoolTaskExecutor extends ExecutorConfigurationSupport
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public void execute(Runnable task, long startTimeout) {
|
||||
execute(task);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -281,6 +281,7 @@ public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public void execute(Runnable task, long startTimeout) {
|
||||
execute(task);
|
||||
|
||||
@@ -73,6 +73,7 @@ jar {
|
||||
dependsOn cglibRepackJar
|
||||
from(zipTree(cglibRepackJar.archivePath)) {
|
||||
include "org/springframework/cglib/**"
|
||||
exclude "org/springframework/cglib/beans/BeanMap*.class"
|
||||
exclude "org/springframework/cglib/core/AbstractClassGenerator*.class"
|
||||
exclude "org/springframework/cglib/core/AsmApi*.class"
|
||||
exclude "org/springframework/cglib/core/KeyFactory.class"
|
||||
|
||||
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* Copyright 2003,2004 The Apache Software Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cglib.beans;
|
||||
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.asm.ClassVisitor;
|
||||
import org.springframework.cglib.core.AbstractClassGenerator;
|
||||
import org.springframework.cglib.core.KeyFactory;
|
||||
import org.springframework.cglib.core.ReflectUtils;
|
||||
|
||||
/**
|
||||
* A <code>Map</code>-based view of a JavaBean. The default set of keys is the
|
||||
* union of all property names (getters or setters). An attempt to set
|
||||
* a read-only property will be ignored, and write-only properties will
|
||||
* be returned as <code>null</code>. Removal of objects is not a
|
||||
* supported (the key set is fixed).
|
||||
* @author Chris Nokleberg
|
||||
*/
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
abstract public class BeanMap implements Map {
|
||||
/**
|
||||
* Limit the properties reflected in the key set of the map
|
||||
* to readable properties.
|
||||
* @see BeanMap.Generator#setRequire
|
||||
*/
|
||||
public static final int REQUIRE_GETTER = 1;
|
||||
|
||||
/**
|
||||
* Limit the properties reflected in the key set of the map
|
||||
* to writable properties.
|
||||
* @see BeanMap.Generator#setRequire
|
||||
*/
|
||||
public static final int REQUIRE_SETTER = 2;
|
||||
|
||||
/**
|
||||
* Helper method to create a new <code>BeanMap</code>. For finer
|
||||
* control over the generated instance, use a new instance of
|
||||
* <code>BeanMap.Generator</code> instead of this static method.
|
||||
* @param bean the JavaBean underlying the map
|
||||
* @return a new <code>BeanMap</code> instance
|
||||
*/
|
||||
public static BeanMap create(Object bean) {
|
||||
Generator gen = new Generator();
|
||||
gen.setBean(bean);
|
||||
return gen.create();
|
||||
}
|
||||
|
||||
public static class Generator extends AbstractClassGenerator {
|
||||
private static final Source SOURCE = new Source(BeanMap.class.getName());
|
||||
|
||||
private static final BeanMapKey KEY_FACTORY =
|
||||
(BeanMapKey)KeyFactory.create(BeanMapKey.class, KeyFactory.CLASS_BY_NAME);
|
||||
|
||||
interface BeanMapKey {
|
||||
public Object newInstance(Class type, int require);
|
||||
}
|
||||
|
||||
private Object bean;
|
||||
private Class beanClass;
|
||||
private int require;
|
||||
|
||||
public Generator() {
|
||||
super(SOURCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bean that the generated map should reflect. The bean may be swapped
|
||||
* out for another bean of the same type using {@link #setBean}.
|
||||
* Calling this method overrides any value previously set using {@link #setBeanClass}.
|
||||
* You must call either this method or {@link #setBeanClass} before {@link #create}.
|
||||
* @param bean the initial bean
|
||||
*/
|
||||
public void setBean(Object bean) {
|
||||
this.bean = bean;
|
||||
if (bean != null) {
|
||||
beanClass = bean.getClass();
|
||||
setContextClass(beanClass);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the class of the bean that the generated map should support.
|
||||
* You must call either this method or {@link #setBeanClass} before {@link #create}.
|
||||
* @param beanClass the class of the bean
|
||||
*/
|
||||
public void setBeanClass(Class beanClass) {
|
||||
this.beanClass = beanClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the properties reflected by the generated map.
|
||||
* @param require any combination of {@link #REQUIRE_GETTER} and
|
||||
* {@link #REQUIRE_SETTER}; default is zero (any property allowed)
|
||||
*/
|
||||
public void setRequire(int require) {
|
||||
this.require = require;
|
||||
}
|
||||
|
||||
protected ClassLoader getDefaultClassLoader() {
|
||||
return beanClass.getClassLoader();
|
||||
}
|
||||
|
||||
protected ProtectionDomain getProtectionDomain() {
|
||||
return ReflectUtils.getProtectionDomain(beanClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of the <code>BeanMap</code>. An existing
|
||||
* generated class will be reused if possible.
|
||||
*/
|
||||
public BeanMap create() {
|
||||
if (beanClass == null)
|
||||
throw new IllegalArgumentException("Class of bean unknown");
|
||||
setNamePrefix(beanClass.getName());
|
||||
return (BeanMap)super.create(KEY_FACTORY.newInstance(beanClass, require));
|
||||
}
|
||||
|
||||
public void generateClass(ClassVisitor v) throws Exception {
|
||||
new BeanMapEmitter(v, getClassName(), beanClass, require);
|
||||
}
|
||||
|
||||
protected Object firstInstance(Class type) {
|
||||
return ((BeanMap)ReflectUtils.newInstance(type)).newInstance(bean);
|
||||
}
|
||||
|
||||
protected Object nextInstance(Object instance) {
|
||||
return ((BeanMap)instance).newInstance(bean);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new <code>BeanMap</code> instance using the specified bean.
|
||||
* This is faster than using the {@link #create} static method.
|
||||
* @param bean the JavaBean underlying the map
|
||||
* @return a new <code>BeanMap</code> instance
|
||||
*/
|
||||
abstract public BeanMap newInstance(Object bean);
|
||||
|
||||
/**
|
||||
* Get the type of a property.
|
||||
* @param name the name of the JavaBean property
|
||||
* @return the type of the property, or null if the property does not exist
|
||||
*/
|
||||
abstract public Class getPropertyType(String name);
|
||||
|
||||
protected Object bean;
|
||||
|
||||
protected BeanMap() {
|
||||
}
|
||||
|
||||
protected BeanMap(Object bean) {
|
||||
setBean(bean);
|
||||
}
|
||||
|
||||
public Object get(Object key) {
|
||||
return get(bean, key);
|
||||
}
|
||||
|
||||
public Object put(Object key, Object value) {
|
||||
return put(bean, key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the property of a bean. This allows a <code>BeanMap</code>
|
||||
* to be used statically for multiple beans--the bean instance tied to the
|
||||
* map is ignored and the bean passed to this method is used instead.
|
||||
* @param bean the bean to query; must be compatible with the type of
|
||||
* this <code>BeanMap</code>
|
||||
* @param key must be a String
|
||||
* @return the current value, or null if there is no matching property
|
||||
*/
|
||||
abstract public Object get(Object bean, Object key);
|
||||
|
||||
/**
|
||||
* Set the property of a bean. This allows a <code>BeanMap</code>
|
||||
* to be used statically for multiple beans--the bean instance tied to the
|
||||
* map is ignored and the bean passed to this method is used instead.
|
||||
* @param key must be a String
|
||||
* @return the old value, if there was one, or null
|
||||
*/
|
||||
abstract public Object put(Object bean, Object key, Object value);
|
||||
|
||||
/**
|
||||
* Change the underlying bean this map should use.
|
||||
* @param bean the new JavaBean
|
||||
* @see #getBean
|
||||
*/
|
||||
public void setBean(Object bean) {
|
||||
this.bean = bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bean currently in use by this map.
|
||||
* @return the current JavaBean
|
||||
* @see #setBean
|
||||
*/
|
||||
public Object getBean() {
|
||||
return bean;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean containsKey(Object key) {
|
||||
return keySet().contains(key);
|
||||
}
|
||||
|
||||
public boolean containsValue(Object value) {
|
||||
for (Iterator it = keySet().iterator(); it.hasNext();) {
|
||||
Object v = get(it.next());
|
||||
if (((value == null) && (v == null)) || (value != null && value.equals(v)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return keySet().size();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
public Object remove(Object key) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void putAll(Map t) {
|
||||
for (Iterator it = t.keySet().iterator(); it.hasNext();) {
|
||||
Object key = it.next();
|
||||
put(key, t.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (o == null || !(o instanceof Map)) {
|
||||
return false;
|
||||
}
|
||||
Map other = (Map)o;
|
||||
if (size() != other.size()) {
|
||||
return false;
|
||||
}
|
||||
for (Iterator it = keySet().iterator(); it.hasNext();) {
|
||||
Object key = it.next();
|
||||
if (!other.containsKey(key)) {
|
||||
return false;
|
||||
}
|
||||
Object v1 = get(key);
|
||||
Object v2 = other.get(key);
|
||||
if (!((v1 == null) ? v2 == null : v1.equals(v2))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int code = 0;
|
||||
for (Iterator it = keySet().iterator(); it.hasNext();) {
|
||||
Object key = it.next();
|
||||
Object value = get(key);
|
||||
code += ((key == null) ? 0 : key.hashCode()) ^
|
||||
((value == null) ? 0 : value.hashCode());
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
// TODO: optimize
|
||||
public Set entrySet() {
|
||||
HashMap copy = new HashMap();
|
||||
for (Iterator it = keySet().iterator(); it.hasNext();) {
|
||||
Object key = it.next();
|
||||
copy.put(key, get(key));
|
||||
}
|
||||
return Collections.unmodifiableMap(copy).entrySet();
|
||||
}
|
||||
|
||||
public Collection values() {
|
||||
Set keys = keySet();
|
||||
List values = new ArrayList(keys.size());
|
||||
for (Iterator it = keys.iterator(); it.hasNext();) {
|
||||
values.add(get(it.next()));
|
||||
}
|
||||
return Collections.unmodifiableCollection(values);
|
||||
}
|
||||
|
||||
/*
|
||||
* @see java.util.AbstractMap#toString
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append('{');
|
||||
for (Iterator it = keySet().iterator(); it.hasNext();) {
|
||||
Object key = it.next();
|
||||
sb.append(key);
|
||||
sb.append('=');
|
||||
sb.append(get(key));
|
||||
if (it.hasNext()) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Spring's repackaging of the
|
||||
* <a href="http://cglib.sourceforge.net">CGLIB</a> beans package
|
||||
* (for internal use only).
|
||||
*
|
||||
* <p>As this repackaging happens at the class file level, sources
|
||||
* and javadocs are not available here... except for a few files
|
||||
* that have been patched for Spring's purposes on JDK 9-17.
|
||||
*/
|
||||
package org.springframework.cglib.beans;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,8 +21,7 @@ import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* Extended interface for asynchronous {@link TaskExecutor} implementations,
|
||||
* offering an overloaded {@link #execute(Runnable, long)} variant with a start
|
||||
* timeout parameter as well support for {@link java.util.concurrent.Callable}.
|
||||
* offering support for {@link java.util.concurrent.Callable}.
|
||||
*
|
||||
* <p>Note: The {@link java.util.concurrent.Executors} class includes a set of
|
||||
* methods that can convert some other common closure-like objects, for example,
|
||||
@@ -41,10 +40,18 @@ import java.util.concurrent.Future;
|
||||
*/
|
||||
public interface AsyncTaskExecutor extends TaskExecutor {
|
||||
|
||||
/** Constant that indicates immediate execution. */
|
||||
/**
|
||||
* Constant that indicates immediate execution.
|
||||
* @deprecated as of 5.3.16 along with {@link #execute(Runnable, long)}
|
||||
*/
|
||||
@Deprecated
|
||||
long TIMEOUT_IMMEDIATE = 0;
|
||||
|
||||
/** Constant that indicates no time limit. */
|
||||
/**
|
||||
* Constant that indicates no time limit.
|
||||
* @deprecated as of 5.3.16 along with {@link #execute(Runnable, long)}
|
||||
*/
|
||||
@Deprecated
|
||||
long TIMEOUT_INDEFINITE = Long.MAX_VALUE;
|
||||
|
||||
|
||||
@@ -58,7 +65,10 @@ public interface AsyncTaskExecutor extends TaskExecutor {
|
||||
* @throws TaskTimeoutException in case of the task being rejected because
|
||||
* of the timeout (i.e. it cannot be started in time)
|
||||
* @throws TaskRejectedException if the given task was not accepted
|
||||
* @see #execute(Runnable)
|
||||
* @deprecated as of 5.3.16 since the common executors do not support start timeouts
|
||||
*/
|
||||
@Deprecated
|
||||
void execute(Runnable task, long startTimeout);
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -173,6 +173,7 @@ public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
|
||||
* if configured (through the superclass's settings).
|
||||
* @see #doExecute(Runnable)
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void execute(Runnable task) {
|
||||
execute(task, TIMEOUT_INDEFINITE);
|
||||
@@ -187,6 +188,7 @@ public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
|
||||
* @see #TIMEOUT_IMMEDIATE
|
||||
* @see #doExecute(Runnable)
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void execute(Runnable task, long startTimeout) {
|
||||
Assert.notNull(task, "Runnable must not be null");
|
||||
@@ -200,6 +202,7 @@ public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public Future<?> submit(Runnable task) {
|
||||
FutureTask<Object> future = new FutureTask<>(task, null);
|
||||
@@ -207,6 +210,7 @@ public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
|
||||
return future;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public <T> Future<T> submit(Callable<T> task) {
|
||||
FutureTask<T> future = new FutureTask<>(task);
|
||||
@@ -214,6 +218,7 @@ public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
|
||||
return future;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public ListenableFuture<?> submitListenable(Runnable task) {
|
||||
ListenableFutureTask<Object> future = new ListenableFutureTask<>(task, null);
|
||||
@@ -221,6 +226,7 @@ public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
|
||||
return future;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
|
||||
ListenableFutureTask<T> future = new ListenableFutureTask<>(task);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,7 +25,6 @@ import java.util.concurrent.RejectedExecutionException;
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0.1
|
||||
* @see TaskExecutor#execute(Runnable)
|
||||
* @see TaskTimeoutException
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class TaskRejectedException extends RejectedExecutionException {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,8 +23,9 @@ package org.springframework.core.task;
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0.3
|
||||
* @see AsyncTaskExecutor#execute(Runnable, long)
|
||||
* @see TaskRejectedException
|
||||
* @deprecated as of 5.3.16 since the common executors do not support start timeouts
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class TaskTimeoutException extends TaskRejectedException {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -97,6 +97,7 @@ public class TaskExecutorAdapter implements AsyncListenableTaskExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public void execute(Runnable task, long startTimeout) {
|
||||
execute(task);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -1256,7 +1256,7 @@ public abstract class ClassUtils {
|
||||
* (may be {@code null} or may not even implement the method)
|
||||
* @return the specific target method, or the original method if the
|
||||
* {@code targetClass} does not implement it
|
||||
* @see #getInterfaceMethodIfPossible
|
||||
* @see #getInterfaceMethodIfPossible(Method, Class)
|
||||
*/
|
||||
public static Method getMostSpecificMethod(Method method, @Nullable Class<?> targetClass) {
|
||||
if (targetClass != null && targetClass != method.getDeclaringClass() && isOverridable(method, targetClass)) {
|
||||
@@ -1289,28 +1289,54 @@ public abstract class ClassUtils {
|
||||
* @param method the method to be invoked, potentially from an implementation class
|
||||
* @return the corresponding interface method, or the original method if none found
|
||||
* @since 5.1
|
||||
* @deprecated in favor of {@link #getInterfaceMethodIfPossible(Method, Class)}
|
||||
*/
|
||||
@Deprecated
|
||||
public static Method getInterfaceMethodIfPossible(Method method) {
|
||||
return getInterfaceMethodIfPossible(method, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine a corresponding interface method for the given method handle, if possible.
|
||||
* <p>This is particularly useful for arriving at a public exported type on Jigsaw
|
||||
* which can be reflectively invoked without an illegal access warning.
|
||||
* @param method the method to be invoked, potentially from an implementation class
|
||||
* @param targetClass the target class to check for declared interfaces
|
||||
* @return the corresponding interface method, or the original method if none found
|
||||
* @since 5.3.16
|
||||
* @see #getMostSpecificMethod
|
||||
*/
|
||||
public static Method getInterfaceMethodIfPossible(Method method) {
|
||||
public static Method getInterfaceMethodIfPossible(Method method, @Nullable Class<?> targetClass) {
|
||||
if (!Modifier.isPublic(method.getModifiers()) || method.getDeclaringClass().isInterface()) {
|
||||
return method;
|
||||
}
|
||||
return interfaceMethodCache.computeIfAbsent(method, key -> {
|
||||
Class<?> current = key.getDeclaringClass();
|
||||
while (current != null && current != Object.class) {
|
||||
Class<?>[] ifcs = current.getInterfaces();
|
||||
for (Class<?> ifc : ifcs) {
|
||||
try {
|
||||
return ifc.getMethod(key.getName(), key.getParameterTypes());
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
// ignore
|
||||
}
|
||||
// Try cached version of method in its declaring class
|
||||
Method result = interfaceMethodCache.computeIfAbsent(method,
|
||||
key -> findInterfaceMethodIfPossible(key, key.getDeclaringClass(), Object.class));
|
||||
if (result == method && targetClass != null) {
|
||||
// No interface method found yet -> try given target class (possibly a subclass of the
|
||||
// declaring class, late-binding a base class method to a subclass-declared interface:
|
||||
// see e.g. HashMap.HashIterator.hasNext)
|
||||
result = findInterfaceMethodIfPossible(method, targetClass, method.getDeclaringClass());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Method findInterfaceMethodIfPossible(Method method, Class<?> startClass, Class<?> endClass) {
|
||||
Class<?> current = startClass;
|
||||
while (current != null && current != endClass) {
|
||||
Class<?>[] ifcs = current.getInterfaces();
|
||||
for (Class<?> ifc : ifcs) {
|
||||
try {
|
||||
return ifc.getMethod(method.getName(), method.getParameterTypes());
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
// ignore
|
||||
}
|
||||
current = current.getSuperclass();
|
||||
}
|
||||
return key;
|
||||
});
|
||||
current = current.getSuperclass();
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -58,8 +58,18 @@ public class ReflectiveMethodExecutor implements MethodExecutor {
|
||||
* @param method the method to invoke
|
||||
*/
|
||||
public ReflectiveMethodExecutor(Method method) {
|
||||
this(method, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new executor for the given method.
|
||||
* @param method the method to invoke
|
||||
* @param targetClass the target class to invoke the method on
|
||||
* @since 5.3.16
|
||||
*/
|
||||
public ReflectiveMethodExecutor(Method method, @Nullable Class<?> targetClass) {
|
||||
this.originalMethod = method;
|
||||
this.methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(method);
|
||||
this.methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(method, targetClass);
|
||||
if (method.isVarArgs()) {
|
||||
this.varargsPosition = method.getParameterCount() - 1;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -176,7 +176,7 @@ public class ReflectiveMethodResolver implements MethodResolver {
|
||||
}
|
||||
if (matchInfo != null) {
|
||||
if (matchInfo.isExactMatch()) {
|
||||
return new ReflectiveMethodExecutor(method);
|
||||
return new ReflectiveMethodExecutor(method, type);
|
||||
}
|
||||
else if (matchInfo.isCloseMatch()) {
|
||||
if (this.useDistance) {
|
||||
@@ -204,13 +204,13 @@ public class ReflectiveMethodResolver implements MethodResolver {
|
||||
}
|
||||
}
|
||||
if (closeMatch != null) {
|
||||
return new ReflectiveMethodExecutor(closeMatch);
|
||||
return new ReflectiveMethodExecutor(closeMatch, type);
|
||||
}
|
||||
else if (matchRequiringConversion != null) {
|
||||
if (multipleOptions) {
|
||||
throw new SpelEvaluationException(SpelMessage.MULTIPLE_POSSIBLE_METHODS, name);
|
||||
}
|
||||
return new ReflectiveMethodExecutor(matchRequiringConversion);
|
||||
return new ReflectiveMethodExecutor(matchRequiringConversion, type);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -130,7 +130,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
// The readerCache will only contain gettable properties (let's not worry about setters for now).
|
||||
Property property = new Property(type, method, null);
|
||||
TypeDescriptor typeDescriptor = new TypeDescriptor(property);
|
||||
method = ClassUtils.getInterfaceMethodIfPossible(method);
|
||||
method = ClassUtils.getInterfaceMethodIfPossible(method, type);
|
||||
this.readerCache.put(cacheKey, new InvokerPair(method, typeDescriptor));
|
||||
this.typeDescriptorCache.put(cacheKey, typeDescriptor);
|
||||
return true;
|
||||
@@ -173,7 +173,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
// The readerCache will only contain gettable properties (let's not worry about setters for now).
|
||||
Property property = new Property(type, method, null);
|
||||
TypeDescriptor typeDescriptor = new TypeDescriptor(property);
|
||||
method = ClassUtils.getInterfaceMethodIfPossible(method);
|
||||
method = ClassUtils.getInterfaceMethodIfPossible(method, type);
|
||||
invoker = new InvokerPair(method, typeDescriptor);
|
||||
this.lastReadInvokerPair = invoker;
|
||||
this.readerCache.put(cacheKey, invoker);
|
||||
@@ -233,7 +233,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
// Treat it like a property
|
||||
Property property = new Property(type, null, method);
|
||||
TypeDescriptor typeDescriptor = new TypeDescriptor(property);
|
||||
method = ClassUtils.getInterfaceMethodIfPossible(method);
|
||||
method = ClassUtils.getInterfaceMethodIfPossible(method, type);
|
||||
this.writerCache.put(cacheKey, method);
|
||||
this.typeDescriptorCache.put(cacheKey, typeDescriptor);
|
||||
return true;
|
||||
@@ -282,7 +282,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
if (method == null) {
|
||||
method = findSetterForProperty(name, type, target);
|
||||
if (method != null) {
|
||||
method = ClassUtils.getInterfaceMethodIfPossible(method);
|
||||
method = ClassUtils.getInterfaceMethodIfPossible(method, type);
|
||||
cachedMember = method;
|
||||
this.writerCache.put(cacheKey, cachedMember);
|
||||
}
|
||||
@@ -527,7 +527,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
method = findGetterForProperty(name, type, target);
|
||||
if (method != null) {
|
||||
TypeDescriptor typeDescriptor = new TypeDescriptor(new MethodParameter(method, -1));
|
||||
method = ClassUtils.getInterfaceMethodIfPossible(method);
|
||||
method = ClassUtils.getInterfaceMethodIfPossible(method, type);
|
||||
invocationTarget = new InvokerPair(method, typeDescriptor);
|
||||
ReflectionUtils.makeAccessible(method);
|
||||
this.readerCache.put(cacheKey, invocationTarget);
|
||||
|
||||
Reference in New Issue
Block a user