introduced "nonPublicAccessAllowed" flag (SPR-5882)
This commit is contained in:
parent
ba27c29dc4
commit
7eabd2da56
|
|
@ -158,7 +158,7 @@ public abstract class BeanUtils {
|
||||||
* @see java.lang.Class#getMethod
|
* @see java.lang.Class#getMethod
|
||||||
* @see #findDeclaredMethod
|
* @see #findDeclaredMethod
|
||||||
*/
|
*/
|
||||||
public static Method findMethod(Class clazz, String methodName, Class[] paramTypes) {
|
public static Method findMethod(Class clazz, String methodName, Class... paramTypes) {
|
||||||
try {
|
try {
|
||||||
return clazz.getMethod(methodName, paramTypes);
|
return clazz.getMethod(methodName, paramTypes);
|
||||||
}
|
}
|
||||||
|
|
@ -195,7 +195,7 @@ public abstract class BeanUtils {
|
||||||
* declared on the given class or one of its superclasses. Prefers public methods,
|
* declared on the given class or one of its superclasses. Prefers public methods,
|
||||||
* but will return a protected, package access, or private method too.
|
* but will return a protected, package access, or private method too.
|
||||||
* <p>Checks <code>Class.getMethods</code> first, falling back to
|
* <p>Checks <code>Class.getMethods</code> first, falling back to
|
||||||
* <code>findDeclaredMethodWithMinimalParameters</code>. This allows to find public
|
* <code>findDeclaredMethodWithMinimalParameters</code>. This allows for finding public
|
||||||
* methods without issues even in environments with restricted Java security settings.
|
* methods without issues even in environments with restricted Java security settings.
|
||||||
* @param clazz the class to check
|
* @param clazz the class to check
|
||||||
* @param methodName the name of the method to find
|
* @param methodName the name of the method to find
|
||||||
|
|
@ -208,7 +208,7 @@ public abstract class BeanUtils {
|
||||||
public static Method findMethodWithMinimalParameters(Class clazz, String methodName)
|
public static Method findMethodWithMinimalParameters(Class clazz, String methodName)
|
||||||
throws IllegalArgumentException {
|
throws IllegalArgumentException {
|
||||||
|
|
||||||
Method targetMethod = doFindMethodWithMinimalParameters(clazz.getDeclaredMethods(), methodName);
|
Method targetMethod = findMethodWithMinimalParameters(clazz.getMethods(), methodName);
|
||||||
if (targetMethod == null) {
|
if (targetMethod == null) {
|
||||||
targetMethod = findDeclaredMethodWithMinimalParameters(clazz, methodName);
|
targetMethod = findDeclaredMethodWithMinimalParameters(clazz, methodName);
|
||||||
}
|
}
|
||||||
|
|
@ -230,7 +230,7 @@ public abstract class BeanUtils {
|
||||||
public static Method findDeclaredMethodWithMinimalParameters(Class clazz, String methodName)
|
public static Method findDeclaredMethodWithMinimalParameters(Class clazz, String methodName)
|
||||||
throws IllegalArgumentException {
|
throws IllegalArgumentException {
|
||||||
|
|
||||||
Method targetMethod = doFindMethodWithMinimalParameters(clazz.getDeclaredMethods(), methodName);
|
Method targetMethod = findMethodWithMinimalParameters(clazz.getDeclaredMethods(), methodName);
|
||||||
if (targetMethod == null && clazz.getSuperclass() != null) {
|
if (targetMethod == null && clazz.getSuperclass() != null) {
|
||||||
targetMethod = findDeclaredMethodWithMinimalParameters(clazz.getSuperclass(), methodName);
|
targetMethod = findDeclaredMethodWithMinimalParameters(clazz.getSuperclass(), methodName);
|
||||||
}
|
}
|
||||||
|
|
@ -246,7 +246,7 @@ public abstract class BeanUtils {
|
||||||
* @throws IllegalArgumentException if methods of the given name were found but
|
* @throws IllegalArgumentException if methods of the given name were found but
|
||||||
* could not be resolved to a unique method with minimal parameters
|
* could not be resolved to a unique method with minimal parameters
|
||||||
*/
|
*/
|
||||||
private static Method doFindMethodWithMinimalParameters(Method[] methods, String methodName)
|
public static Method findMethodWithMinimalParameters(Method[] methods, String methodName)
|
||||||
throws IllegalArgumentException {
|
throws IllegalArgumentException {
|
||||||
|
|
||||||
Method targetMethod = null;
|
Method targetMethod = null;
|
||||||
|
|
|
||||||
|
|
@ -1388,10 +1388,12 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
((InitializingBean) bean).afterPropertiesSet();
|
((InitializingBean) bean).afterPropertiesSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
String initMethodName = (mbd != null ? mbd.getInitMethodName() : null);
|
if (mbd != null) {
|
||||||
|
String initMethodName = mbd.getInitMethodName();
|
||||||
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
|
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
|
||||||
!mbd.isExternallyManagedInitMethod(initMethodName)) {
|
!mbd.isExternallyManagedInitMethod(initMethodName)) {
|
||||||
invokeCustomInitMethod(beanName, bean, initMethodName, mbd.isEnforceInitMethod());
|
invokeCustomInitMethod(beanName, bean, mbd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1406,12 +1408,13 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
* @param enforceInitMethod indicates whether the defined init method needs to exist
|
* @param enforceInitMethod indicates whether the defined init method needs to exist
|
||||||
* @see #invokeInitMethods
|
* @see #invokeInitMethods
|
||||||
*/
|
*/
|
||||||
protected void invokeCustomInitMethod(
|
protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd) throws Throwable {
|
||||||
String beanName, Object bean, String initMethodName, boolean enforceInitMethod) throws Throwable {
|
String initMethodName = mbd.getInitMethodName();
|
||||||
|
Method initMethod = (mbd.isNonPublicAccessAllowed() ?
|
||||||
Method initMethod = BeanUtils.findMethod(bean.getClass(), initMethodName, null);
|
BeanUtils.findMethod(bean.getClass(), initMethodName) :
|
||||||
|
ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
|
||||||
if (initMethod == null) {
|
if (initMethod == null) {
|
||||||
if (enforceInitMethod) {
|
if (mbd.isEnforceInitMethod()) {
|
||||||
throw new BeanDefinitionValidationException("Couldn't find an init method named '" +
|
throw new BeanDefinitionValidationException("Couldn't find an init method named '" +
|
||||||
initMethodName + "' on bean with name '" + beanName + "'");
|
initMethodName + "' on bean with name '" + beanName + "'");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -141,10 +141,12 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||||
private final Map<String, AutowireCandidateQualifier> qualifiers =
|
private final Map<String, AutowireCandidateQualifier> qualifiers =
|
||||||
new LinkedHashMap<String, AutowireCandidateQualifier>();
|
new LinkedHashMap<String, AutowireCandidateQualifier>();
|
||||||
|
|
||||||
private ConstructorArgumentValues constructorArgumentValues;
|
private boolean nonPublicAccessAllowed = true;
|
||||||
|
|
||||||
private boolean lenientConstructorResolution = true;
|
private boolean lenientConstructorResolution = true;
|
||||||
|
|
||||||
|
private ConstructorArgumentValues constructorArgumentValues;
|
||||||
|
|
||||||
private MutablePropertyValues propertyValues;
|
private MutablePropertyValues propertyValues;
|
||||||
|
|
||||||
private MethodOverrides methodOverrides = new MethodOverrides();
|
private MethodOverrides methodOverrides = new MethodOverrides();
|
||||||
|
|
@ -226,6 +228,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||||
setAutowireCandidate(originalAbd.isAutowireCandidate());
|
setAutowireCandidate(originalAbd.isAutowireCandidate());
|
||||||
copyQualifiersFrom(originalAbd);
|
copyQualifiersFrom(originalAbd);
|
||||||
setPrimary(originalAbd.isPrimary());
|
setPrimary(originalAbd.isPrimary());
|
||||||
|
setNonPublicAccessAllowed(originalAbd.isNonPublicAccessAllowed());
|
||||||
setLenientConstructorResolution(originalAbd.isLenientConstructorResolution());
|
setLenientConstructorResolution(originalAbd.isLenientConstructorResolution());
|
||||||
setInitMethodName(originalAbd.getInitMethodName());
|
setInitMethodName(originalAbd.getInitMethodName());
|
||||||
setEnforceInitMethod(originalAbd.isEnforceInitMethod());
|
setEnforceInitMethod(originalAbd.isEnforceInitMethod());
|
||||||
|
|
@ -298,6 +301,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||||
setPrimary(otherAbd.isPrimary());
|
setPrimary(otherAbd.isPrimary());
|
||||||
setDependencyCheck(otherAbd.getDependencyCheck());
|
setDependencyCheck(otherAbd.getDependencyCheck());
|
||||||
setDependsOn(otherAbd.getDependsOn());
|
setDependsOn(otherAbd.getDependsOn());
|
||||||
|
setNonPublicAccessAllowed(otherAbd.isNonPublicAccessAllowed());
|
||||||
setLenientConstructorResolution(otherAbd.isLenientConstructorResolution());
|
setLenientConstructorResolution(otherAbd.isLenientConstructorResolution());
|
||||||
if (otherAbd.getInitMethodName() != null) {
|
if (otherAbd.getInitMethodName() != null) {
|
||||||
setInitMethodName(otherAbd.getInitMethodName());
|
setInitMethodName(otherAbd.getInitMethodName());
|
||||||
|
|
@ -650,6 +654,44 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify whether to allow access to non-public constructors and methods,
|
||||||
|
* for the case of externalized metadata pointing to those.
|
||||||
|
* <p>This applies to constructor resolution, factory method resolution,
|
||||||
|
* and also init/destroy methods. Bean property accessors have to be public
|
||||||
|
* in any case and are not affected by this setting.
|
||||||
|
* <p>Note that annotation-driven configuration will still access non-public
|
||||||
|
* members as far as they have been annotated. This setting applies to
|
||||||
|
* externalized metadata in this bean definition only.
|
||||||
|
*/
|
||||||
|
public void setNonPublicAccessAllowed(boolean nonPublicAccessAllowed) {
|
||||||
|
this.nonPublicAccessAllowed = nonPublicAccessAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether to allow access to non-public constructors and methods.
|
||||||
|
*/
|
||||||
|
public boolean isNonPublicAccessAllowed() {
|
||||||
|
return this.nonPublicAccessAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify whether to resolve constructors in lenient mode (<code>true</code>,
|
||||||
|
* which is the default) or to switch to strict resolution (throwing an exception
|
||||||
|
* in case of ambigious constructors that all match when converting the arguments,
|
||||||
|
* whereas lenient mode would use the one with the 'closest' type matches).
|
||||||
|
*/
|
||||||
|
public void setLenientConstructorResolution(boolean lenientConstructorResolution) {
|
||||||
|
this.lenientConstructorResolution = lenientConstructorResolution;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether to resolve constructors in lenient mode or in strict mode.
|
||||||
|
*/
|
||||||
|
public boolean isLenientConstructorResolution() {
|
||||||
|
return this.lenientConstructorResolution;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify constructor argument values for this bean.
|
* Specify constructor argument values for this bean.
|
||||||
*/
|
*/
|
||||||
|
|
@ -672,23 +714,6 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||||
return !this.constructorArgumentValues.isEmpty();
|
return !this.constructorArgumentValues.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify whether to resolve constructors in lenient mode (<code>true</code>,
|
|
||||||
* which is the default) or to switch to strict resolution (throwing an exception
|
|
||||||
* in case of ambigious constructors that all match when converting the arguments,
|
|
||||||
* whereas lenient mode would use the one with the 'closest' type matches).
|
|
||||||
*/
|
|
||||||
public void setLenientConstructorResolution(boolean lenientConstructorResolution) {
|
|
||||||
this.lenientConstructorResolution = lenientConstructorResolution;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return whether to resolve constructors in lenient mode or in strict mode.
|
|
||||||
*/
|
|
||||||
public boolean isLenientConstructorResolution() {
|
|
||||||
return this.lenientConstructorResolution;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify property values for this bean, if any.
|
* Specify property values for this bean, if any.
|
||||||
*/
|
*/
|
||||||
|
|
@ -976,6 +1001,8 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||||
if (!ObjectUtils.nullSafeEquals(this.qualifiers, that.qualifiers)) return false;
|
if (!ObjectUtils.nullSafeEquals(this.qualifiers, that.qualifiers)) return false;
|
||||||
if (this.primary != that.primary) return false;
|
if (this.primary != that.primary) return false;
|
||||||
|
|
||||||
|
if (this.nonPublicAccessAllowed != that.nonPublicAccessAllowed) return false;
|
||||||
|
if (this.lenientConstructorResolution != that.lenientConstructorResolution) return false;
|
||||||
if (!ObjectUtils.nullSafeEquals(this.constructorArgumentValues, that.constructorArgumentValues)) return false;
|
if (!ObjectUtils.nullSafeEquals(this.constructorArgumentValues, that.constructorArgumentValues)) return false;
|
||||||
if (!ObjectUtils.nullSafeEquals(this.propertyValues, that.propertyValues)) return false;
|
if (!ObjectUtils.nullSafeEquals(this.propertyValues, that.propertyValues)) return false;
|
||||||
if (!ObjectUtils.nullSafeEquals(this.methodOverrides, that.methodOverrides)) return false;
|
if (!ObjectUtils.nullSafeEquals(this.methodOverrides, that.methodOverrides)) return false;
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,8 @@ class ConstructorResolver {
|
||||||
if (candidates == null) {
|
if (candidates == null) {
|
||||||
Class beanClass = mbd.getBeanClass();
|
Class beanClass = mbd.getBeanClass();
|
||||||
try {
|
try {
|
||||||
candidates = beanClass.getDeclaredConstructors();
|
candidates = (mbd.isNonPublicAccessAllowed() ?
|
||||||
|
beanClass.getDeclaredConstructors() : beanClass.getConstructors());
|
||||||
}
|
}
|
||||||
catch (Throwable ex) {
|
catch (Throwable ex) {
|
||||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
||||||
|
|
@ -354,7 +355,8 @@ class ConstructorResolver {
|
||||||
// Need to determine the factory method...
|
// Need to determine the factory method...
|
||||||
// Try all methods with this name to see if they match the given arguments.
|
// Try all methods with this name to see if they match the given arguments.
|
||||||
factoryClass = ClassUtils.getUserClass(factoryClass);
|
factoryClass = ClassUtils.getUserClass(factoryClass);
|
||||||
Method[] rawCandidates = ReflectionUtils.getAllDeclaredMethods(factoryClass);
|
Method[] rawCandidates = (mbd.isNonPublicAccessAllowed() ?
|
||||||
|
ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods());
|
||||||
List<Method> candidateSet = new ArrayList<Method>();
|
List<Method> candidateSet = new ArrayList<Method>();
|
||||||
for (Method candidate : rawCandidates) {
|
for (Method candidate : rawCandidates) {
|
||||||
if (Modifier.isStatic(candidate.getModifiers()) == isStatic &&
|
if (Modifier.isStatic(candidate.getModifiers()) == isStatic &&
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,8 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
|
|
||||||
private final boolean invokeDisposableBean;
|
private final boolean invokeDisposableBean;
|
||||||
|
|
||||||
|
private final boolean nonPublicAccessAllowed;
|
||||||
|
|
||||||
private String destroyMethodName;
|
private String destroyMethodName;
|
||||||
|
|
||||||
private transient Method destroyMethod;
|
private transient Method destroyMethod;
|
||||||
|
|
@ -81,12 +83,15 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
this.beanName = beanName;
|
this.beanName = beanName;
|
||||||
this.invokeDisposableBean =
|
this.invokeDisposableBean =
|
||||||
(this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"));
|
(this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"));
|
||||||
|
this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
|
||||||
String destroyMethodName = beanDefinition.getDestroyMethodName();
|
String destroyMethodName = beanDefinition.getDestroyMethodName();
|
||||||
if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
|
if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
|
||||||
!beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
|
!beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
|
||||||
this.destroyMethodName = destroyMethodName;
|
this.destroyMethodName = destroyMethodName;
|
||||||
try {
|
try {
|
||||||
this.destroyMethod = BeanUtils.findMethodWithMinimalParameters(bean.getClass(), destroyMethodName);
|
this.destroyMethod = (this.nonPublicAccessAllowed ?
|
||||||
|
BeanUtils.findMethodWithMinimalParameters(bean.getClass(), destroyMethodName) :
|
||||||
|
BeanUtils.findMethodWithMinimalParameters(bean.getClass().getMethods(), destroyMethodName));
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException ex) {
|
catch (IllegalArgumentException ex) {
|
||||||
throw new BeanDefinitionValidationException("Couldn't find a unique destroy method on bean with name '" +
|
throw new BeanDefinitionValidationException("Couldn't find a unique destroy method on bean with name '" +
|
||||||
|
|
@ -115,18 +120,15 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new DisposableBeanAdapter for the given bean.
|
* Create a new DisposableBeanAdapter for the given bean.
|
||||||
* @param bean the bean instance (never <code>null</code>)
|
|
||||||
* @param beanName the name of the bean
|
|
||||||
* @param invokeDisposableBean whether to actually invoke DisposableBean's destroy method here
|
|
||||||
* @param destroyMethodName the name of the custom destroy method (<code>null</code> if there is none)
|
|
||||||
* @param postProcessors the List of DestructionAwareBeanPostProcessors, if any
|
|
||||||
*/
|
*/
|
||||||
private DisposableBeanAdapter(Object bean, String beanName, boolean invokeDisposableBean,
|
private DisposableBeanAdapter(Object bean, String beanName, boolean invokeDisposableBean,
|
||||||
String destroyMethodName, List<DestructionAwareBeanPostProcessor> postProcessors) {
|
boolean nonPublicAccessAllowed, String destroyMethodName,
|
||||||
|
List<DestructionAwareBeanPostProcessor> postProcessors) {
|
||||||
|
|
||||||
this.bean = bean;
|
this.bean = bean;
|
||||||
this.beanName = beanName;
|
this.beanName = beanName;
|
||||||
this.invokeDisposableBean = invokeDisposableBean;
|
this.invokeDisposableBean = invokeDisposableBean;
|
||||||
|
this.nonPublicAccessAllowed = nonPublicAccessAllowed;
|
||||||
this.destroyMethodName = destroyMethodName;
|
this.destroyMethodName = destroyMethodName;
|
||||||
this.beanPostProcessors = postProcessors;
|
this.beanPostProcessors = postProcessors;
|
||||||
}
|
}
|
||||||
|
|
@ -184,9 +186,10 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
invokeCustomDestroyMethod(this.destroyMethod);
|
invokeCustomDestroyMethod(this.destroyMethod);
|
||||||
}
|
}
|
||||||
else if (this.destroyMethodName != null) {
|
else if (this.destroyMethodName != null) {
|
||||||
Method destroyMethod =
|
this.destroyMethod = (this.nonPublicAccessAllowed ?
|
||||||
BeanUtils.findMethodWithMinimalParameters(this.bean.getClass(), this.destroyMethodName);
|
BeanUtils.findMethodWithMinimalParameters(this.bean.getClass(), this.destroyMethodName) :
|
||||||
invokeCustomDestroyMethod(destroyMethod);
|
BeanUtils.findMethodWithMinimalParameters(this.bean.getClass().getMethods(), this.destroyMethodName));
|
||||||
|
invokeCustomDestroyMethod(this.destroyMethod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -242,7 +245,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new DisposableBeanAdapter(this.bean, this.beanName, this.invokeDisposableBean,
|
return new DisposableBeanAdapter(this.bean, this.beanName, this.invokeDisposableBean,
|
||||||
this.destroyMethodName, serializablePostProcessors);
|
this.nonPublicAccessAllowed, this.destroyMethodName, serializablePostProcessors);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue