Consistent throwing of BeanCreationExceptions (and reflection exceptions)
Issue: SPR-14883
This commit is contained in:
parent
fd7045adac
commit
b42d731fc8
|
@ -220,7 +220,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
public void setBeanFactory(BeanFactory beanFactory) {
|
||||||
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
|
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"AutowiredAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory");
|
"AutowiredAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory");
|
||||||
|
@ -238,7 +238,10 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName) throws BeansException {
|
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
|
||||||
|
throws BeanCreationException {
|
||||||
|
|
||||||
|
// Let's check for lookup methods here..
|
||||||
if (!this.lookupMethodsChecked.contains(beanName)) {
|
if (!this.lookupMethodsChecked.contains(beanName)) {
|
||||||
ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() {
|
ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -263,10 +266,19 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||||
// Quick check on the concurrent map first, with minimal locking.
|
// Quick check on the concurrent map first, with minimal locking.
|
||||||
Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
|
Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
|
||||||
if (candidateConstructors == null) {
|
if (candidateConstructors == null) {
|
||||||
|
// Fully synchronized resolution now...
|
||||||
synchronized (this.candidateConstructorsCache) {
|
synchronized (this.candidateConstructorsCache) {
|
||||||
candidateConstructors = this.candidateConstructorsCache.get(beanClass);
|
candidateConstructors = this.candidateConstructorsCache.get(beanClass);
|
||||||
if (candidateConstructors == null) {
|
if (candidateConstructors == null) {
|
||||||
Constructor<?>[] rawCandidates = beanClass.getDeclaredConstructors();
|
Constructor<?>[] rawCandidates;
|
||||||
|
try {
|
||||||
|
rawCandidates = beanClass.getDeclaredConstructors();
|
||||||
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
|
throw new BeanCreationException(beanName,
|
||||||
|
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
|
||||||
|
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
|
||||||
|
}
|
||||||
List<Constructor<?>> candidates = new ArrayList<Constructor<?>>(rawCandidates.length);
|
List<Constructor<?>> candidates = new ArrayList<Constructor<?>>(rawCandidates.length);
|
||||||
Constructor<?> requiredConstructor = null;
|
Constructor<?> requiredConstructor = null;
|
||||||
Constructor<?> defaultConstructor = null;
|
Constructor<?> defaultConstructor = null;
|
||||||
|
@ -320,9 +332,9 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||||
}
|
}
|
||||||
else if (candidates.size() == 1 && logger.isWarnEnabled()) {
|
else if (candidates.size() == 1 && logger.isWarnEnabled()) {
|
||||||
logger.warn("Inconsistent constructor declaration on bean with name '" + beanName +
|
logger.warn("Inconsistent constructor declaration on bean with name '" + beanName +
|
||||||
"': single autowire-marked constructor flagged as optional - this constructor " +
|
"': single autowire-marked constructor flagged as optional - " +
|
||||||
"is effectively required since there is no default constructor to fall back to: " +
|
"this constructor is effectively required since there is no " +
|
||||||
candidates.get(0));
|
"default constructor to fall back to: " + candidates.get(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
candidateConstructors = candidates.toArray(new Constructor<?>[candidates.size()]);
|
candidateConstructors = candidates.toArray(new Constructor<?>[candidates.size()]);
|
||||||
|
@ -342,7 +354,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PropertyValues postProcessPropertyValues(
|
public PropertyValues postProcessPropertyValues(
|
||||||
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
|
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
|
||||||
|
|
||||||
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
|
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
|
||||||
try {
|
try {
|
||||||
|
@ -361,9 +373,9 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||||
* 'Native' processing method for direct calls with an arbitrary target instance,
|
* 'Native' processing method for direct calls with an arbitrary target instance,
|
||||||
* resolving all of its fields and methods which are annotated with {@code @Autowired}.
|
* resolving all of its fields and methods which are annotated with {@code @Autowired}.
|
||||||
* @param bean the target instance to process
|
* @param bean the target instance to process
|
||||||
* @throws BeansException if autowiring failed
|
* @throws BeanCreationException if autowiring failed
|
||||||
*/
|
*/
|
||||||
public void processInjection(Object bean) throws BeansException {
|
public void processInjection(Object bean) throws BeanCreationException {
|
||||||
Class<?> clazz = bean.getClass();
|
Class<?> clazz = bean.getClass();
|
||||||
InjectionMetadata metadata = findAutowiringMetadata(clazz.getName(), clazz, null);
|
InjectionMetadata metadata = findAutowiringMetadata(clazz.getName(), clazz, null);
|
||||||
try {
|
try {
|
||||||
|
@ -373,7 +385,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
catch (Throwable ex) {
|
catch (Throwable ex) {
|
||||||
throw new BeanCreationException("Injection of autowired dependencies failed for class [" + clazz + "]", ex);
|
throw new BeanCreationException(
|
||||||
|
"Injection of autowired dependencies failed for class [" + clazz + "]", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,7 +459,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||||
}
|
}
|
||||||
if (method.getParameterTypes().length == 0) {
|
if (method.getParameterTypes().length == 0) {
|
||||||
if (logger.isWarnEnabled()) {
|
if (logger.isWarnEnabled()) {
|
||||||
logger.warn("Autowired annotation should be used on methods with parameters: " + method);
|
logger.warn("Autowired annotation should only be used on methods with parameters: " +
|
||||||
|
method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
boolean required = determineRequiredStatus(ann);
|
boolean required = determineRequiredStatus(ann);
|
||||||
|
@ -629,7 +643,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||||
Class<?>[] paramTypes = method.getParameterTypes();
|
Class<?>[] paramTypes = method.getParameterTypes();
|
||||||
arguments = new Object[paramTypes.length];
|
arguments = new Object[paramTypes.length];
|
||||||
DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
|
DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
|
||||||
Set<String> autowiredBeanNames = new LinkedHashSet<String>(paramTypes.length);
|
Set<String> autowiredBeans = new LinkedHashSet<String>(paramTypes.length);
|
||||||
TypeConverter typeConverter = beanFactory.getTypeConverter();
|
TypeConverter typeConverter = beanFactory.getTypeConverter();
|
||||||
for (int i = 0; i < arguments.length; i++) {
|
for (int i = 0; i < arguments.length; i++) {
|
||||||
MethodParameter methodParam = new MethodParameter(method, i);
|
MethodParameter methodParam = new MethodParameter(method, i);
|
||||||
|
@ -637,7 +651,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||||
currDesc.setContainingClass(bean.getClass());
|
currDesc.setContainingClass(bean.getClass());
|
||||||
descriptors[i] = currDesc;
|
descriptors[i] = currDesc;
|
||||||
try {
|
try {
|
||||||
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeanNames, typeConverter);
|
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
|
||||||
if (arg == null && !this.required) {
|
if (arg == null && !this.required) {
|
||||||
arguments = null;
|
arguments = null;
|
||||||
break;
|
break;
|
||||||
|
@ -655,9 +669,9 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||||
for (int i = 0; i < arguments.length; i++) {
|
for (int i = 0; i < arguments.length; i++) {
|
||||||
this.cachedMethodArguments[i] = descriptors[i];
|
this.cachedMethodArguments[i] = descriptors[i];
|
||||||
}
|
}
|
||||||
registerDependentBeans(beanName, autowiredBeanNames);
|
registerDependentBeans(beanName, autowiredBeans);
|
||||||
if (autowiredBeanNames.size() == paramTypes.length) {
|
if (autowiredBeans.size() == paramTypes.length) {
|
||||||
Iterator<String> it = autowiredBeanNames.iterator();
|
Iterator<String> it = autowiredBeans.iterator();
|
||||||
for (int i = 0; i < paramTypes.length; i++) {
|
for (int i = 0; i < paramTypes.length; i++) {
|
||||||
String autowiredBeanName = it.next();
|
String autowiredBeanName = it.next();
|
||||||
if (beanFactory.containsBean(autowiredBeanName)) {
|
if (beanFactory.containsBean(autowiredBeanName)) {
|
||||||
|
@ -706,19 +720,19 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
private static class ShortcutDependencyDescriptor extends DependencyDescriptor {
|
private static class ShortcutDependencyDescriptor extends DependencyDescriptor {
|
||||||
|
|
||||||
private final String shortcutName;
|
private final String shortcut;
|
||||||
|
|
||||||
private final Class<?> requiredType;
|
private final Class<?> requiredType;
|
||||||
|
|
||||||
public ShortcutDependencyDescriptor(DependencyDescriptor original, String shortcutName, Class<?> requiredType) {
|
public ShortcutDependencyDescriptor(DependencyDescriptor original, String shortcut, Class<?> requiredType) {
|
||||||
super(original);
|
super(original);
|
||||||
this.shortcutName = shortcutName;
|
this.shortcut = shortcut;
|
||||||
this.requiredType = requiredType;
|
this.requiredType = requiredType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object resolveShortcut(BeanFactory beanFactory) {
|
public Object resolveShortcut(BeanFactory beanFactory) {
|
||||||
return resolveCandidate(this.shortcutName, this.requiredType, beanFactory);
|
return resolveCandidate(this.shortcut, this.requiredType, beanFactory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2016 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.
|
||||||
|
@ -141,8 +141,7 @@ public class RequiredAnnotationBeanPostProcessor extends InstantiationAwareBeanP
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PropertyValues postProcessPropertyValues(
|
public PropertyValues postProcessPropertyValues(
|
||||||
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
|
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
|
||||||
throws BeansException {
|
|
||||||
|
|
||||||
if (!this.validatedBeanNames.contains(beanName)) {
|
if (!this.validatedBeanNames.contains(beanName)) {
|
||||||
if (!shouldSkip(this.beanFactory, beanName)) {
|
if (!shouldSkip(this.beanFactory, beanName)) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2012 the original author or authors.
|
* Copyright 2002-2016 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.
|
||||||
|
@ -66,8 +66,7 @@ public abstract class InstantiationAwareBeanPostProcessorAdapter implements Smar
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PropertyValues postProcessPropertyValues(
|
public PropertyValues postProcessPropertyValues(
|
||||||
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
|
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
|
||||||
throws BeansException {
|
|
||||||
|
|
||||||
return pvs;
|
return pvs;
|
||||||
}
|
}
|
||||||
|
|
|
@ -479,12 +479,22 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
"BeanPostProcessor before instantiation of bean failed", ex);
|
"BeanPostProcessor before instantiation of bean failed", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
|
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Finished creating instance of bean '" + beanName + "'");
|
logger.debug("Finished creating instance of bean '" + beanName + "'");
|
||||||
}
|
}
|
||||||
return beanInstance;
|
return beanInstance;
|
||||||
}
|
}
|
||||||
|
catch (BeanCreationException ex) {
|
||||||
|
// A previously detected exception with proper bean creation context already...
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
|
throw new BeanCreationException(
|
||||||
|
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Actually create the specified bean. Pre-creation processing has already happened
|
* Actually create the specified bean. Pre-creation processing has already happened
|
||||||
|
@ -500,7 +510,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
* @see #instantiateUsingFactoryMethod
|
* @see #instantiateUsingFactoryMethod
|
||||||
* @see #autowireConstructor
|
* @see #autowireConstructor
|
||||||
*/
|
*/
|
||||||
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
|
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
|
||||||
|
throws BeanCreationException {
|
||||||
|
|
||||||
// Instantiate the bean.
|
// Instantiate the bean.
|
||||||
BeanWrapper instanceWrapper = null;
|
BeanWrapper instanceWrapper = null;
|
||||||
if (mbd.isSingleton()) {
|
if (mbd.isSingleton()) {
|
||||||
|
@ -515,7 +527,13 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
// Allow post-processors to modify the merged bean definition.
|
// Allow post-processors to modify the merged bean definition.
|
||||||
synchronized (mbd.postProcessingLock) {
|
synchronized (mbd.postProcessingLock) {
|
||||||
if (!mbd.postProcessed) {
|
if (!mbd.postProcessed) {
|
||||||
|
try {
|
||||||
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
|
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
|
||||||
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
|
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
||||||
|
"Post-processing failed of bean type [" + beanType + "] failed", ex);
|
||||||
|
}
|
||||||
mbd.postProcessed = true;
|
mbd.postProcessed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -550,7 +568,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
throw (BeanCreationException) ex;
|
throw (BeanCreationException) ex;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
|
throw new BeanCreationException(
|
||||||
|
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -586,7 +605,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
registerDisposableBeanIfNecessary(beanName, bean, mbd);
|
registerDisposableBeanIfNecessary(beanName, bean, mbd);
|
||||||
}
|
}
|
||||||
catch (BeanDefinitionValidationException ex) {
|
catch (BeanDefinitionValidationException ex) {
|
||||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
|
throw new BeanCreationException(
|
||||||
|
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return exposedObject;
|
return exposedObject;
|
||||||
|
@ -773,10 +793,11 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
ReflectionUtils.doWithMethods(fbClass,
|
ReflectionUtils.doWithMethods(fbClass,
|
||||||
new ReflectionUtils.MethodCallback() {
|
new ReflectionUtils.MethodCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
public void doWith(Method method) {
|
||||||
if (method.getName().equals(factoryMethodName) &&
|
if (method.getName().equals(factoryMethodName) &&
|
||||||
FactoryBean.class.isAssignableFrom(method.getReturnType())) {
|
FactoryBean.class.isAssignableFrom(method.getReturnType())) {
|
||||||
objectType.value = GenericTypeResolver.resolveReturnTypeArgument(method, FactoryBean.class);
|
objectType.value = GenericTypeResolver.resolveReturnTypeArgument(
|
||||||
|
method, FactoryBean.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -933,7 +954,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName)
|
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName)
|
||||||
throws BeansException {
|
throws BeansException {
|
||||||
|
|
||||||
try {
|
|
||||||
for (BeanPostProcessor bp : getBeanPostProcessors()) {
|
for (BeanPostProcessor bp : getBeanPostProcessors()) {
|
||||||
if (bp instanceof MergedBeanDefinitionPostProcessor) {
|
if (bp instanceof MergedBeanDefinitionPostProcessor) {
|
||||||
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
|
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
|
||||||
|
@ -941,11 +961,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
|
||||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
|
||||||
"Post-processing failed of bean type [" + beanType + "] failed", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply before-instantiation post-processors, resolving whether there is a
|
* Apply before-instantiation post-processors, resolving whether there is a
|
||||||
|
@ -1107,7 +1122,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
return bw;
|
return bw;
|
||||||
}
|
}
|
||||||
catch (Throwable ex) {
|
catch (Throwable ex) {
|
||||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
|
throw new BeanCreationException(
|
||||||
|
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1659,7 +1675,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
* methods with arguments.
|
* methods with arguments.
|
||||||
* @see #invokeInitMethods
|
* @see #invokeInitMethods
|
||||||
*/
|
*/
|
||||||
protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
|
protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd)
|
||||||
|
throws Throwable {
|
||||||
|
|
||||||
String initMethodName = mbd.getInitMethodName();
|
String initMethodName = mbd.getInitMethodName();
|
||||||
final Method initMethod = (mbd.isNonPublicAccessAllowed() ?
|
final Method initMethod = (mbd.isNonPublicAccessAllowed() ?
|
||||||
BeanUtils.findMethod(bean.getClass(), initMethodName) :
|
BeanUtils.findMethod(bean.getClass(), initMethodName) :
|
||||||
|
|
|
@ -287,13 +287,13 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
// Guarantee initialization of beans that the current bean depends on.
|
// Guarantee initialization of beans that the current bean depends on.
|
||||||
String[] dependsOn = mbd.getDependsOn();
|
String[] dependsOn = mbd.getDependsOn();
|
||||||
if (dependsOn != null) {
|
if (dependsOn != null) {
|
||||||
for (String dependsOnBean : dependsOn) {
|
for (String dep : dependsOn) {
|
||||||
if (isDependent(beanName, dependsOnBean)) {
|
if (isDependent(beanName, dep)) {
|
||||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
||||||
"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
|
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
|
||||||
}
|
}
|
||||||
registerDependentBean(dependsOnBean, beanName);
|
registerDependentBean(dep, beanName);
|
||||||
getBean(dependsOnBean);
|
getBean(dep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -460,19 +460,19 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (isFactoryBean(beanName, mbd)) {
|
if (isFactoryBean(beanName, mbd)) {
|
||||||
final FactoryBean<?> factoryBean = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
|
final FactoryBean<?> fb = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
|
||||||
if (System.getSecurityManager() != null) {
|
if (System.getSecurityManager() != null) {
|
||||||
return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
|
return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
public Boolean run() {
|
public Boolean run() {
|
||||||
return ((factoryBean instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factoryBean).isPrototype()) ||
|
return ((fb instanceof SmartFactoryBean && ((SmartFactoryBean<?>) fb).isPrototype()) ||
|
||||||
!factoryBean.isSingleton());
|
!fb.isSingleton());
|
||||||
}
|
}
|
||||||
}, getAccessControlContext());
|
}, getAccessControlContext());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return ((factoryBean instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factoryBean).isPrototype()) ||
|
return ((fb instanceof SmartFactoryBean && ((SmartFactoryBean<?>) fb).isPrototype()) ||
|
||||||
!factoryBean.isSingleton());
|
!fb.isSingleton());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1053,11 +1053,11 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
* Destroy the given bean instance (usually a prototype instance
|
* Destroy the given bean instance (usually a prototype instance
|
||||||
* obtained from this factory) according to the given bean definition.
|
* obtained from this factory) according to the given bean definition.
|
||||||
* @param beanName the name of the bean definition
|
* @param beanName the name of the bean definition
|
||||||
* @param beanInstance the bean instance to destroy
|
* @param bean the bean instance to destroy
|
||||||
* @param mbd the merged bean definition
|
* @param mbd the merged bean definition
|
||||||
*/
|
*/
|
||||||
protected void destroyBean(String beanName, Object beanInstance, RootBeanDefinition mbd) {
|
protected void destroyBean(String beanName, Object bean, RootBeanDefinition mbd) {
|
||||||
new DisposableBeanAdapter(beanInstance, beanName, mbd, getBeanPostProcessors(), getAccessControlContext()).destroy();
|
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), getAccessControlContext()).destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1238,12 +1238,13 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
pbd = getMergedBeanDefinition(parentBeanName);
|
pbd = getMergedBeanDefinition(parentBeanName);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (getParentBeanFactory() instanceof ConfigurableBeanFactory) {
|
BeanFactory parent = getParentBeanFactory();
|
||||||
pbd = ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(parentBeanName);
|
if (parent instanceof ConfigurableBeanFactory) {
|
||||||
|
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new NoSuchBeanDefinitionException(bd.getParentName(),
|
throw new NoSuchBeanDefinitionException(parentBeanName,
|
||||||
"Parent name '" + bd.getParentName() + "' is equal to bean name '" + beanName +
|
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
|
||||||
"': cannot be resolved without an AbstractBeanFactory parent");
|
"': cannot be resolved without an AbstractBeanFactory parent");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1359,12 +1360,14 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
catch (ClassNotFoundException ex) {
|
catch (ClassNotFoundException ex) {
|
||||||
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
|
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
|
||||||
}
|
}
|
||||||
catch (LinkageError err) {
|
catch (LinkageError ex) {
|
||||||
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
|
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch) throws ClassNotFoundException {
|
private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
|
||||||
|
throws ClassNotFoundException {
|
||||||
|
|
||||||
ClassLoader beanClassLoader = getBeanClassLoader();
|
ClassLoader beanClassLoader = getBeanClassLoader();
|
||||||
ClassLoader classLoaderToUse = beanClassLoader;
|
ClassLoader classLoaderToUse = beanClassLoader;
|
||||||
if (!ObjectUtils.isEmpty(typesToMatch)) {
|
if (!ObjectUtils.isEmpty(typesToMatch)) {
|
||||||
|
|
|
@ -483,6 +483,7 @@ public abstract class ReflectionUtils {
|
||||||
* @param clazz the class to introspect
|
* @param clazz the class to introspect
|
||||||
* @param mc the callback to invoke for each method
|
* @param mc the callback to invoke for each method
|
||||||
* @since 4.2
|
* @since 4.2
|
||||||
|
* @throws IllegalStateException if introspection fails
|
||||||
* @see #doWithMethods
|
* @see #doWithMethods
|
||||||
*/
|
*/
|
||||||
public static void doWithLocalMethods(Class<?> clazz, MethodCallback mc) {
|
public static void doWithLocalMethods(Class<?> clazz, MethodCallback mc) {
|
||||||
|
@ -504,6 +505,7 @@ public abstract class ReflectionUtils {
|
||||||
* twice, unless excluded by a {@link MethodFilter}.
|
* twice, unless excluded by a {@link MethodFilter}.
|
||||||
* @param clazz the class to introspect
|
* @param clazz the class to introspect
|
||||||
* @param mc the callback to invoke for each method
|
* @param mc the callback to invoke for each method
|
||||||
|
* @throws IllegalStateException if introspection fails
|
||||||
* @see #doWithMethods(Class, MethodCallback, MethodFilter)
|
* @see #doWithMethods(Class, MethodCallback, MethodFilter)
|
||||||
*/
|
*/
|
||||||
public static void doWithMethods(Class<?> clazz, MethodCallback mc) {
|
public static void doWithMethods(Class<?> clazz, MethodCallback mc) {
|
||||||
|
@ -518,6 +520,7 @@ public abstract class ReflectionUtils {
|
||||||
* @param clazz the class to introspect
|
* @param clazz the class to introspect
|
||||||
* @param mc the callback to invoke for each method
|
* @param mc the callback to invoke for each method
|
||||||
* @param mf the filter that determines the methods to apply the callback to
|
* @param mf the filter that determines the methods to apply the callback to
|
||||||
|
* @throws IllegalStateException if introspection fails
|
||||||
*/
|
*/
|
||||||
public static void doWithMethods(Class<?> clazz, MethodCallback mc, MethodFilter mf) {
|
public static void doWithMethods(Class<?> clazz, MethodCallback mc, MethodFilter mf) {
|
||||||
// Keep backing up the inheritance hierarchy.
|
// Keep backing up the inheritance hierarchy.
|
||||||
|
@ -547,6 +550,7 @@ public abstract class ReflectionUtils {
|
||||||
* Get all declared methods on the leaf class and all superclasses.
|
* Get all declared methods on the leaf class and all superclasses.
|
||||||
* Leaf class methods are included first.
|
* Leaf class methods are included first.
|
||||||
* @param leafClass the class to introspect
|
* @param leafClass the class to introspect
|
||||||
|
* @throws IllegalStateException if introspection fails
|
||||||
*/
|
*/
|
||||||
public static Method[] getAllDeclaredMethods(Class<?> leafClass) {
|
public static Method[] getAllDeclaredMethods(Class<?> leafClass) {
|
||||||
final List<Method> methods = new ArrayList<Method>(32);
|
final List<Method> methods = new ArrayList<Method>(32);
|
||||||
|
@ -564,6 +568,7 @@ public abstract class ReflectionUtils {
|
||||||
* Leaf class methods are included first and while traversing the superclass hierarchy
|
* Leaf class methods are included first and while traversing the superclass hierarchy
|
||||||
* any methods found with signatures matching a method already included are filtered out.
|
* any methods found with signatures matching a method already included are filtered out.
|
||||||
* @param leafClass the class to introspect
|
* @param leafClass the class to introspect
|
||||||
|
* @throws IllegalStateException if introspection fails
|
||||||
*/
|
*/
|
||||||
public static Method[] getUniqueDeclaredMethods(Class<?> leafClass) {
|
public static Method[] getUniqueDeclaredMethods(Class<?> leafClass) {
|
||||||
final List<Method> methods = new ArrayList<Method>(32);
|
final List<Method> methods = new ArrayList<Method>(32);
|
||||||
|
@ -604,11 +609,13 @@ public abstract class ReflectionUtils {
|
||||||
* interfaces, since those are effectively to be treated just like declared methods.
|
* interfaces, since those are effectively to be treated just like declared methods.
|
||||||
* @param clazz the class to introspect
|
* @param clazz the class to introspect
|
||||||
* @return the cached array of methods
|
* @return the cached array of methods
|
||||||
|
* @throws IllegalStateException if introspection fails
|
||||||
* @see Class#getDeclaredMethods()
|
* @see Class#getDeclaredMethods()
|
||||||
*/
|
*/
|
||||||
private static Method[] getDeclaredMethods(Class<?> clazz) {
|
private static Method[] getDeclaredMethods(Class<?> clazz) {
|
||||||
Method[] result = declaredMethodsCache.get(clazz);
|
Method[] result = declaredMethodsCache.get(clazz);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
|
try {
|
||||||
Method[] declaredMethods = clazz.getDeclaredMethods();
|
Method[] declaredMethods = clazz.getDeclaredMethods();
|
||||||
List<Method> defaultMethods = findConcreteMethodsOnInterfaces(clazz);
|
List<Method> defaultMethods = findConcreteMethodsOnInterfaces(clazz);
|
||||||
if (defaultMethods != null) {
|
if (defaultMethods != null) {
|
||||||
|
@ -625,6 +632,11 @@ public abstract class ReflectionUtils {
|
||||||
}
|
}
|
||||||
declaredMethodsCache.put(clazz, (result.length == 0 ? NO_METHODS : result));
|
declaredMethodsCache.put(clazz, (result.length == 0 ? NO_METHODS : result));
|
||||||
}
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
|
throw new IllegalStateException("Failed to introspect Class [" + clazz +
|
||||||
|
"] from ClassLoader [" + clazz.getClassLoader() + "]", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -649,6 +661,7 @@ public abstract class ReflectionUtils {
|
||||||
* @param clazz the target class to analyze
|
* @param clazz the target class to analyze
|
||||||
* @param fc the callback to invoke for each field
|
* @param fc the callback to invoke for each field
|
||||||
* @since 4.2
|
* @since 4.2
|
||||||
|
* @throws IllegalStateException if introspection fails
|
||||||
* @see #doWithFields
|
* @see #doWithFields
|
||||||
*/
|
*/
|
||||||
public static void doWithLocalFields(Class<?> clazz, FieldCallback fc) {
|
public static void doWithLocalFields(Class<?> clazz, FieldCallback fc) {
|
||||||
|
@ -667,6 +680,7 @@ public abstract class ReflectionUtils {
|
||||||
* class hierarchy to get all declared fields.
|
* class hierarchy to get all declared fields.
|
||||||
* @param clazz the target class to analyze
|
* @param clazz the target class to analyze
|
||||||
* @param fc the callback to invoke for each field
|
* @param fc the callback to invoke for each field
|
||||||
|
* @throws IllegalStateException if introspection fails
|
||||||
*/
|
*/
|
||||||
public static void doWithFields(Class<?> clazz, FieldCallback fc) {
|
public static void doWithFields(Class<?> clazz, FieldCallback fc) {
|
||||||
doWithFields(clazz, fc, null);
|
doWithFields(clazz, fc, null);
|
||||||
|
@ -678,6 +692,7 @@ public abstract class ReflectionUtils {
|
||||||
* @param clazz the target class to analyze
|
* @param clazz the target class to analyze
|
||||||
* @param fc the callback to invoke for each field
|
* @param fc the callback to invoke for each field
|
||||||
* @param ff the filter that determines the fields to apply the callback to
|
* @param ff the filter that determines the fields to apply the callback to
|
||||||
|
* @throws IllegalStateException if introspection fails
|
||||||
*/
|
*/
|
||||||
public static void doWithFields(Class<?> clazz, FieldCallback fc, FieldFilter ff) {
|
public static void doWithFields(Class<?> clazz, FieldCallback fc, FieldFilter ff) {
|
||||||
// Keep backing up the inheritance hierarchy.
|
// Keep backing up the inheritance hierarchy.
|
||||||
|
@ -705,14 +720,21 @@ public abstract class ReflectionUtils {
|
||||||
* in order to avoid the JVM's SecurityManager check and defensive array copying.
|
* in order to avoid the JVM's SecurityManager check and defensive array copying.
|
||||||
* @param clazz the class to introspect
|
* @param clazz the class to introspect
|
||||||
* @return the cached array of fields
|
* @return the cached array of fields
|
||||||
|
* @throws IllegalStateException if introspection fails
|
||||||
* @see Class#getDeclaredFields()
|
* @see Class#getDeclaredFields()
|
||||||
*/
|
*/
|
||||||
private static Field[] getDeclaredFields(Class<?> clazz) {
|
private static Field[] getDeclaredFields(Class<?> clazz) {
|
||||||
Field[] result = declaredFieldsCache.get(clazz);
|
Field[] result = declaredFieldsCache.get(clazz);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
|
try {
|
||||||
result = clazz.getDeclaredFields();
|
result = clazz.getDeclaredFields();
|
||||||
declaredFieldsCache.put(clazz, (result.length == 0 ? NO_FIELDS : result));
|
declaredFieldsCache.put(clazz, (result.length == 0 ? NO_FIELDS : result));
|
||||||
}
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
|
throw new IllegalStateException("Failed to introspect Class [" + clazz +
|
||||||
|
"] from ClassLoader [" + clazz.getClassLoader() + "]", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -720,6 +742,7 @@ public abstract class ReflectionUtils {
|
||||||
* Given the source object and the destination, which must be the same class
|
* Given the source object and the destination, which must be the same class
|
||||||
* or a subclass, copy all fields, including inherited fields. Designed to
|
* or a subclass, copy all fields, including inherited fields. Designed to
|
||||||
* work on objects with public no-arg constructors.
|
* work on objects with public no-arg constructors.
|
||||||
|
* @throws IllegalStateException if introspection fails
|
||||||
*/
|
*/
|
||||||
public static void shallowCopyFieldState(final Object src, final Object dest) {
|
public static void shallowCopyFieldState(final Object src, final Object dest) {
|
||||||
if (src == null) {
|
if (src == null) {
|
||||||
|
|
Loading…
Reference in New Issue