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 #findDeclaredMethod
|
||||
*/
|
||||
public static Method findMethod(Class clazz, String methodName, Class[] paramTypes) {
|
||||
public static Method findMethod(Class clazz, String methodName, Class... paramTypes) {
|
||||
try {
|
||||
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,
|
||||
* but will return a protected, package access, or private method too.
|
||||
* <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.
|
||||
* @param clazz the class to check
|
||||
* @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)
|
||||
throws IllegalArgumentException {
|
||||
|
||||
Method targetMethod = doFindMethodWithMinimalParameters(clazz.getDeclaredMethods(), methodName);
|
||||
Method targetMethod = findMethodWithMinimalParameters(clazz.getMethods(), methodName);
|
||||
if (targetMethod == null) {
|
||||
targetMethod = findDeclaredMethodWithMinimalParameters(clazz, methodName);
|
||||
}
|
||||
|
|
@ -230,7 +230,7 @@ public abstract class BeanUtils {
|
|||
public static Method findDeclaredMethodWithMinimalParameters(Class clazz, String methodName)
|
||||
throws IllegalArgumentException {
|
||||
|
||||
Method targetMethod = doFindMethodWithMinimalParameters(clazz.getDeclaredMethods(), methodName);
|
||||
Method targetMethod = findMethodWithMinimalParameters(clazz.getDeclaredMethods(), methodName);
|
||||
if (targetMethod == null && clazz.getSuperclass() != null) {
|
||||
targetMethod = findDeclaredMethodWithMinimalParameters(clazz.getSuperclass(), methodName);
|
||||
}
|
||||
|
|
@ -246,7 +246,7 @@ public abstract class BeanUtils {
|
|||
* @throws IllegalArgumentException if methods of the given name were found but
|
||||
* 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 {
|
||||
|
||||
Method targetMethod = null;
|
||||
|
|
|
|||
|
|
@ -1388,10 +1388,12 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
|||
((InitializingBean) bean).afterPropertiesSet();
|
||||
}
|
||||
|
||||
String initMethodName = (mbd != null ? mbd.getInitMethodName() : null);
|
||||
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
|
||||
!mbd.isExternallyManagedInitMethod(initMethodName)) {
|
||||
invokeCustomInitMethod(beanName, bean, initMethodName, mbd.isEnforceInitMethod());
|
||||
if (mbd != null) {
|
||||
String initMethodName = mbd.getInitMethodName();
|
||||
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
|
||||
!mbd.isExternallyManagedInitMethod(initMethodName)) {
|
||||
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
|
||||
* @see #invokeInitMethods
|
||||
*/
|
||||
protected void invokeCustomInitMethod(
|
||||
String beanName, Object bean, String initMethodName, boolean enforceInitMethod) throws Throwable {
|
||||
|
||||
Method initMethod = BeanUtils.findMethod(bean.getClass(), initMethodName, null);
|
||||
protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd) throws Throwable {
|
||||
String initMethodName = mbd.getInitMethodName();
|
||||
Method initMethod = (mbd.isNonPublicAccessAllowed() ?
|
||||
BeanUtils.findMethod(bean.getClass(), initMethodName) :
|
||||
ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
|
||||
if (initMethod == null) {
|
||||
if (enforceInitMethod) {
|
||||
if (mbd.isEnforceInitMethod()) {
|
||||
throw new BeanDefinitionValidationException("Couldn't find an init method named '" +
|
||||
initMethodName + "' on bean with name '" + beanName + "'");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,10 +141,12 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
|||
private final Map<String, AutowireCandidateQualifier> qualifiers =
|
||||
new LinkedHashMap<String, AutowireCandidateQualifier>();
|
||||
|
||||
private ConstructorArgumentValues constructorArgumentValues;
|
||||
private boolean nonPublicAccessAllowed = true;
|
||||
|
||||
private boolean lenientConstructorResolution = true;
|
||||
|
||||
private ConstructorArgumentValues constructorArgumentValues;
|
||||
|
||||
private MutablePropertyValues propertyValues;
|
||||
|
||||
private MethodOverrides methodOverrides = new MethodOverrides();
|
||||
|
|
@ -226,6 +228,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
|||
setAutowireCandidate(originalAbd.isAutowireCandidate());
|
||||
copyQualifiersFrom(originalAbd);
|
||||
setPrimary(originalAbd.isPrimary());
|
||||
setNonPublicAccessAllowed(originalAbd.isNonPublicAccessAllowed());
|
||||
setLenientConstructorResolution(originalAbd.isLenientConstructorResolution());
|
||||
setInitMethodName(originalAbd.getInitMethodName());
|
||||
setEnforceInitMethod(originalAbd.isEnforceInitMethod());
|
||||
|
|
@ -298,6 +301,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
|||
setPrimary(otherAbd.isPrimary());
|
||||
setDependencyCheck(otherAbd.getDependencyCheck());
|
||||
setDependsOn(otherAbd.getDependsOn());
|
||||
setNonPublicAccessAllowed(otherAbd.isNonPublicAccessAllowed());
|
||||
setLenientConstructorResolution(otherAbd.isLenientConstructorResolution());
|
||||
if (otherAbd.getInitMethodName() != null) {
|
||||
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.
|
||||
*/
|
||||
|
|
@ -672,23 +714,6 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
|||
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.
|
||||
*/
|
||||
|
|
@ -976,6 +1001,8 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
|||
if (!ObjectUtils.nullSafeEquals(this.qualifiers, that.qualifiers)) 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.propertyValues, that.propertyValues)) return false;
|
||||
if (!ObjectUtils.nullSafeEquals(this.methodOverrides, that.methodOverrides)) return false;
|
||||
|
|
|
|||
|
|
@ -142,7 +142,8 @@ class ConstructorResolver {
|
|||
if (candidates == null) {
|
||||
Class beanClass = mbd.getBeanClass();
|
||||
try {
|
||||
candidates = beanClass.getDeclaredConstructors();
|
||||
candidates = (mbd.isNonPublicAccessAllowed() ?
|
||||
beanClass.getDeclaredConstructors() : beanClass.getConstructors());
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
||||
|
|
@ -354,7 +355,8 @@ class ConstructorResolver {
|
|||
// Need to determine the factory method...
|
||||
// Try all methods with this name to see if they match the given arguments.
|
||||
factoryClass = ClassUtils.getUserClass(factoryClass);
|
||||
Method[] rawCandidates = ReflectionUtils.getAllDeclaredMethods(factoryClass);
|
||||
Method[] rawCandidates = (mbd.isNonPublicAccessAllowed() ?
|
||||
ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods());
|
||||
List<Method> candidateSet = new ArrayList<Method>();
|
||||
for (Method candidate : rawCandidates) {
|
||||
if (Modifier.isStatic(candidate.getModifiers()) == isStatic &&
|
||||
|
|
|
|||
|
|
@ -58,6 +58,8 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
|||
|
||||
private final boolean invokeDisposableBean;
|
||||
|
||||
private final boolean nonPublicAccessAllowed;
|
||||
|
||||
private String destroyMethodName;
|
||||
|
||||
private transient Method destroyMethod;
|
||||
|
|
@ -81,12 +83,15 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
|||
this.beanName = beanName;
|
||||
this.invokeDisposableBean =
|
||||
(this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"));
|
||||
this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
|
||||
String destroyMethodName = beanDefinition.getDestroyMethodName();
|
||||
if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
|
||||
!beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
|
||||
this.destroyMethodName = destroyMethodName;
|
||||
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) {
|
||||
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.
|
||||
* @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,
|
||||
String destroyMethodName, List<DestructionAwareBeanPostProcessor> postProcessors) {
|
||||
boolean nonPublicAccessAllowed, String destroyMethodName,
|
||||
List<DestructionAwareBeanPostProcessor> postProcessors) {
|
||||
|
||||
this.bean = bean;
|
||||
this.beanName = beanName;
|
||||
this.invokeDisposableBean = invokeDisposableBean;
|
||||
this.nonPublicAccessAllowed = nonPublicAccessAllowed;
|
||||
this.destroyMethodName = destroyMethodName;
|
||||
this.beanPostProcessors = postProcessors;
|
||||
}
|
||||
|
|
@ -184,9 +186,10 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
|||
invokeCustomDestroyMethod(this.destroyMethod);
|
||||
}
|
||||
else if (this.destroyMethodName != null) {
|
||||
Method destroyMethod =
|
||||
BeanUtils.findMethodWithMinimalParameters(this.bean.getClass(), this.destroyMethodName);
|
||||
invokeCustomDestroyMethod(destroyMethod);
|
||||
this.destroyMethod = (this.nonPublicAccessAllowed ?
|
||||
BeanUtils.findMethodWithMinimalParameters(this.bean.getClass(), this.destroyMethodName) :
|
||||
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,
|
||||
this.destroyMethodName, serializablePostProcessors);
|
||||
this.nonPublicAccessAllowed, this.destroyMethodName, serializablePostProcessors);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue