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");
|
* 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.
|
||||||
@@ -1832,7 +1832,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
|||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
logger.trace("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
|
logger.trace("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
|
||||||
}
|
}
|
||||||
Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod);
|
Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod, bean.getClass());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ReflectionUtils.makeAccessible(methodToInvoke);
|
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");
|
* 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.
|
||||||
@@ -130,7 +130,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
|||||||
beanName + "' has a non-boolean parameter - not supported as destroy method");
|
beanName + "' has a non-boolean parameter - not supported as destroy method");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod);
|
destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod, bean.getClass());
|
||||||
}
|
}
|
||||||
this.destroyMethod = destroyMethod;
|
this.destroyMethod = destroyMethod;
|
||||||
}
|
}
|
||||||
@@ -223,9 +223,9 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
|||||||
invokeCustomDestroyMethod(this.destroyMethod);
|
invokeCustomDestroyMethod(this.destroyMethod);
|
||||||
}
|
}
|
||||||
else if (this.destroyMethodName != null) {
|
else if (this.destroyMethodName != null) {
|
||||||
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
|
Method destroyMethod = determineDestroyMethod(this.destroyMethodName);
|
||||||
if (methodToInvoke != null) {
|
if (destroyMethod != null) {
|
||||||
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
|
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");
|
* 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.
|
||||||
@@ -76,6 +76,7 @@ public class SimpleThreadPoolTaskExecutor extends SimpleThreadPool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
public void execute(Runnable task, long startTimeout) {
|
public void execute(Runnable task, long startTimeout) {
|
||||||
execute(task);
|
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");
|
* 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.
|
||||||
@@ -147,6 +147,7 @@ public class ConcurrentTaskExecutor implements AsyncListenableTaskExecutor, Sche
|
|||||||
this.adaptedExecutor.execute(task);
|
this.adaptedExecutor.execute(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
public void execute(Runnable task, long startTimeout) {
|
public void execute(Runnable task, long startTimeout) {
|
||||||
this.adaptedExecutor.execute(task, 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");
|
* 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.
|
||||||
@@ -340,6 +340,7 @@ public class ThreadPoolTaskExecutor extends ExecutorConfigurationSupport
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
public void execute(Runnable task, long startTimeout) {
|
public void execute(Runnable task, long startTimeout) {
|
||||||
execute(task);
|
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");
|
* 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.
|
||||||
@@ -281,6 +281,7 @@ public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
public void execute(Runnable task, long startTimeout) {
|
public void execute(Runnable task, long startTimeout) {
|
||||||
execute(task);
|
execute(task);
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ jar {
|
|||||||
dependsOn cglibRepackJar
|
dependsOn cglibRepackJar
|
||||||
from(zipTree(cglibRepackJar.archivePath)) {
|
from(zipTree(cglibRepackJar.archivePath)) {
|
||||||
include "org/springframework/cglib/**"
|
include "org/springframework/cglib/**"
|
||||||
|
exclude "org/springframework/cglib/beans/BeanMap*.class"
|
||||||
exclude "org/springframework/cglib/core/AbstractClassGenerator*.class"
|
exclude "org/springframework/cglib/core/AbstractClassGenerator*.class"
|
||||||
exclude "org/springframework/cglib/core/AsmApi*.class"
|
exclude "org/springframework/cglib/core/AsmApi*.class"
|
||||||
exclude "org/springframework/cglib/core/KeyFactory.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");
|
* 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.
|
||||||
@@ -21,8 +21,7 @@ import java.util.concurrent.Future;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Extended interface for asynchronous {@link TaskExecutor} implementations,
|
* Extended interface for asynchronous {@link TaskExecutor} implementations,
|
||||||
* offering an overloaded {@link #execute(Runnable, long)} variant with a start
|
* offering support for {@link java.util.concurrent.Callable}.
|
||||||
* timeout parameter as well support for {@link java.util.concurrent.Callable}.
|
|
||||||
*
|
*
|
||||||
* <p>Note: The {@link java.util.concurrent.Executors} class includes a set of
|
* <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,
|
* 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 {
|
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;
|
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;
|
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
|
* @throws TaskTimeoutException in case of the task being rejected because
|
||||||
* of the timeout (i.e. it cannot be started in time)
|
* of the timeout (i.e. it cannot be started in time)
|
||||||
* @throws TaskRejectedException if the given task was not accepted
|
* @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);
|
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");
|
* 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.
|
||||||
@@ -173,6 +173,7 @@ public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
|
|||||||
* if configured (through the superclass's settings).
|
* if configured (through the superclass's settings).
|
||||||
* @see #doExecute(Runnable)
|
* @see #doExecute(Runnable)
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
public void execute(Runnable task) {
|
public void execute(Runnable task) {
|
||||||
execute(task, TIMEOUT_INDEFINITE);
|
execute(task, TIMEOUT_INDEFINITE);
|
||||||
@@ -187,6 +188,7 @@ public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
|
|||||||
* @see #TIMEOUT_IMMEDIATE
|
* @see #TIMEOUT_IMMEDIATE
|
||||||
* @see #doExecute(Runnable)
|
* @see #doExecute(Runnable)
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
public void execute(Runnable task, long startTimeout) {
|
public void execute(Runnable task, long startTimeout) {
|
||||||
Assert.notNull(task, "Runnable must not be null");
|
Assert.notNull(task, "Runnable must not be null");
|
||||||
@@ -200,6 +202,7 @@ public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
public Future<?> submit(Runnable task) {
|
public Future<?> submit(Runnable task) {
|
||||||
FutureTask<Object> future = new FutureTask<>(task, null);
|
FutureTask<Object> future = new FutureTask<>(task, null);
|
||||||
@@ -207,6 +210,7 @@ public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
|
|||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
public <T> Future<T> submit(Callable<T> task) {
|
public <T> Future<T> submit(Callable<T> task) {
|
||||||
FutureTask<T> future = new FutureTask<>(task);
|
FutureTask<T> future = new FutureTask<>(task);
|
||||||
@@ -214,6 +218,7 @@ public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
|
|||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<?> submitListenable(Runnable task) {
|
public ListenableFuture<?> submitListenable(Runnable task) {
|
||||||
ListenableFutureTask<Object> future = new ListenableFutureTask<>(task, null);
|
ListenableFutureTask<Object> future = new ListenableFutureTask<>(task, null);
|
||||||
@@ -221,6 +226,7 @@ public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
|
|||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
|
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
|
||||||
ListenableFutureTask<T> future = new ListenableFutureTask<>(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");
|
* 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.
|
||||||
@@ -25,7 +25,6 @@ import java.util.concurrent.RejectedExecutionException;
|
|||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @since 2.0.1
|
* @since 2.0.1
|
||||||
* @see TaskExecutor#execute(Runnable)
|
* @see TaskExecutor#execute(Runnable)
|
||||||
* @see TaskTimeoutException
|
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class TaskRejectedException extends RejectedExecutionException {
|
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");
|
* 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.
|
||||||
@@ -23,8 +23,9 @@ package org.springframework.core.task;
|
|||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @since 2.0.3
|
* @since 2.0.3
|
||||||
* @see AsyncTaskExecutor#execute(Runnable, long)
|
* @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")
|
@SuppressWarnings("serial")
|
||||||
public class TaskTimeoutException extends TaskRejectedException {
|
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");
|
* 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.
|
||||||
@@ -97,6 +97,7 @@ public class TaskExecutorAdapter implements AsyncListenableTaskExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
public void execute(Runnable task, long startTimeout) {
|
public void execute(Runnable task, long startTimeout) {
|
||||||
execute(task);
|
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");
|
* 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.
|
||||||
@@ -1256,7 +1256,7 @@ public abstract class ClassUtils {
|
|||||||
* (may be {@code null} or may not even implement the method)
|
* (may be {@code null} or may not even implement the method)
|
||||||
* @return the specific target method, or the original method if the
|
* @return the specific target method, or the original method if the
|
||||||
* {@code targetClass} does not implement it
|
* {@code targetClass} does not implement it
|
||||||
* @see #getInterfaceMethodIfPossible
|
* @see #getInterfaceMethodIfPossible(Method, Class)
|
||||||
*/
|
*/
|
||||||
public static Method getMostSpecificMethod(Method method, @Nullable Class<?> targetClass) {
|
public static Method getMostSpecificMethod(Method method, @Nullable Class<?> targetClass) {
|
||||||
if (targetClass != null && targetClass != method.getDeclaringClass() && isOverridable(method, 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
|
* @param method the method to be invoked, potentially from an implementation class
|
||||||
* @return the corresponding interface method, or the original method if none found
|
* @return the corresponding interface method, or the original method if none found
|
||||||
* @since 5.1
|
* @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
|
* @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()) {
|
if (!Modifier.isPublic(method.getModifiers()) || method.getDeclaringClass().isInterface()) {
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
return interfaceMethodCache.computeIfAbsent(method, key -> {
|
// Try cached version of method in its declaring class
|
||||||
Class<?> current = key.getDeclaringClass();
|
Method result = interfaceMethodCache.computeIfAbsent(method,
|
||||||
while (current != null && current != Object.class) {
|
key -> findInterfaceMethodIfPossible(key, key.getDeclaringClass(), Object.class));
|
||||||
Class<?>[] ifcs = current.getInterfaces();
|
if (result == method && targetClass != null) {
|
||||||
for (Class<?> ifc : ifcs) {
|
// No interface method found yet -> try given target class (possibly a subclass of the
|
||||||
try {
|
// declaring class, late-binding a base class method to a subclass-declared interface:
|
||||||
return ifc.getMethod(key.getName(), key.getParameterTypes());
|
// see e.g. HashMap.HashIterator.hasNext)
|
||||||
}
|
result = findInterfaceMethodIfPossible(method, targetClass, method.getDeclaringClass());
|
||||||
catch (NoSuchMethodException ex) {
|
}
|
||||||
// ignore
|
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");
|
* 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.
|
||||||
@@ -58,8 +58,18 @@ public class ReflectiveMethodExecutor implements MethodExecutor {
|
|||||||
* @param method the method to invoke
|
* @param method the method to invoke
|
||||||
*/
|
*/
|
||||||
public ReflectiveMethodExecutor(Method method) {
|
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.originalMethod = method;
|
||||||
this.methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(method);
|
this.methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(method, targetClass);
|
||||||
if (method.isVarArgs()) {
|
if (method.isVarArgs()) {
|
||||||
this.varargsPosition = method.getParameterCount() - 1;
|
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");
|
* 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.
|
||||||
@@ -176,7 +176,7 @@ public class ReflectiveMethodResolver implements MethodResolver {
|
|||||||
}
|
}
|
||||||
if (matchInfo != null) {
|
if (matchInfo != null) {
|
||||||
if (matchInfo.isExactMatch()) {
|
if (matchInfo.isExactMatch()) {
|
||||||
return new ReflectiveMethodExecutor(method);
|
return new ReflectiveMethodExecutor(method, type);
|
||||||
}
|
}
|
||||||
else if (matchInfo.isCloseMatch()) {
|
else if (matchInfo.isCloseMatch()) {
|
||||||
if (this.useDistance) {
|
if (this.useDistance) {
|
||||||
@@ -204,13 +204,13 @@ public class ReflectiveMethodResolver implements MethodResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (closeMatch != null) {
|
if (closeMatch != null) {
|
||||||
return new ReflectiveMethodExecutor(closeMatch);
|
return new ReflectiveMethodExecutor(closeMatch, type);
|
||||||
}
|
}
|
||||||
else if (matchRequiringConversion != null) {
|
else if (matchRequiringConversion != null) {
|
||||||
if (multipleOptions) {
|
if (multipleOptions) {
|
||||||
throw new SpelEvaluationException(SpelMessage.MULTIPLE_POSSIBLE_METHODS, name);
|
throw new SpelEvaluationException(SpelMessage.MULTIPLE_POSSIBLE_METHODS, name);
|
||||||
}
|
}
|
||||||
return new ReflectiveMethodExecutor(matchRequiringConversion);
|
return new ReflectiveMethodExecutor(matchRequiringConversion, type);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return null;
|
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");
|
* 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.
|
||||||
@@ -130,7 +130,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
|||||||
// The readerCache will only contain gettable properties (let's not worry about setters for now).
|
// The readerCache will only contain gettable properties (let's not worry about setters for now).
|
||||||
Property property = new Property(type, method, null);
|
Property property = new Property(type, method, null);
|
||||||
TypeDescriptor typeDescriptor = new TypeDescriptor(property);
|
TypeDescriptor typeDescriptor = new TypeDescriptor(property);
|
||||||
method = ClassUtils.getInterfaceMethodIfPossible(method);
|
method = ClassUtils.getInterfaceMethodIfPossible(method, type);
|
||||||
this.readerCache.put(cacheKey, new InvokerPair(method, typeDescriptor));
|
this.readerCache.put(cacheKey, new InvokerPair(method, typeDescriptor));
|
||||||
this.typeDescriptorCache.put(cacheKey, typeDescriptor);
|
this.typeDescriptorCache.put(cacheKey, typeDescriptor);
|
||||||
return true;
|
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).
|
// The readerCache will only contain gettable properties (let's not worry about setters for now).
|
||||||
Property property = new Property(type, method, null);
|
Property property = new Property(type, method, null);
|
||||||
TypeDescriptor typeDescriptor = new TypeDescriptor(property);
|
TypeDescriptor typeDescriptor = new TypeDescriptor(property);
|
||||||
method = ClassUtils.getInterfaceMethodIfPossible(method);
|
method = ClassUtils.getInterfaceMethodIfPossible(method, type);
|
||||||
invoker = new InvokerPair(method, typeDescriptor);
|
invoker = new InvokerPair(method, typeDescriptor);
|
||||||
this.lastReadInvokerPair = invoker;
|
this.lastReadInvokerPair = invoker;
|
||||||
this.readerCache.put(cacheKey, invoker);
|
this.readerCache.put(cacheKey, invoker);
|
||||||
@@ -233,7 +233,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
|||||||
// Treat it like a property
|
// Treat it like a property
|
||||||
Property property = new Property(type, null, method);
|
Property property = new Property(type, null, method);
|
||||||
TypeDescriptor typeDescriptor = new TypeDescriptor(property);
|
TypeDescriptor typeDescriptor = new TypeDescriptor(property);
|
||||||
method = ClassUtils.getInterfaceMethodIfPossible(method);
|
method = ClassUtils.getInterfaceMethodIfPossible(method, type);
|
||||||
this.writerCache.put(cacheKey, method);
|
this.writerCache.put(cacheKey, method);
|
||||||
this.typeDescriptorCache.put(cacheKey, typeDescriptor);
|
this.typeDescriptorCache.put(cacheKey, typeDescriptor);
|
||||||
return true;
|
return true;
|
||||||
@@ -282,7 +282,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
|||||||
if (method == null) {
|
if (method == null) {
|
||||||
method = findSetterForProperty(name, type, target);
|
method = findSetterForProperty(name, type, target);
|
||||||
if (method != null) {
|
if (method != null) {
|
||||||
method = ClassUtils.getInterfaceMethodIfPossible(method);
|
method = ClassUtils.getInterfaceMethodIfPossible(method, type);
|
||||||
cachedMember = method;
|
cachedMember = method;
|
||||||
this.writerCache.put(cacheKey, cachedMember);
|
this.writerCache.put(cacheKey, cachedMember);
|
||||||
}
|
}
|
||||||
@@ -527,7 +527,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
|||||||
method = findGetterForProperty(name, type, target);
|
method = findGetterForProperty(name, type, target);
|
||||||
if (method != null) {
|
if (method != null) {
|
||||||
TypeDescriptor typeDescriptor = new TypeDescriptor(new MethodParameter(method, -1));
|
TypeDescriptor typeDescriptor = new TypeDescriptor(new MethodParameter(method, -1));
|
||||||
method = ClassUtils.getInterfaceMethodIfPossible(method);
|
method = ClassUtils.getInterfaceMethodIfPossible(method, type);
|
||||||
invocationTarget = new InvokerPair(method, typeDescriptor);
|
invocationTarget = new InvokerPair(method, typeDescriptor);
|
||||||
ReflectionUtils.makeAccessible(method);
|
ReflectionUtils.makeAccessible(method);
|
||||||
this.readerCache.put(cacheKey, invocationTarget);
|
this.readerCache.put(cacheKey, invocationTarget);
|
||||||
|
|||||||
Reference in New Issue
Block a user