Polishing

This commit is contained in:
Juergen Hoeller
2014-08-14 23:49:29 +02:00
parent 42c090efa4
commit a31ebb6c1e
10 changed files with 56 additions and 90 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -170,8 +170,7 @@ public interface BeanFactory {
* <p>Allows for specifying explicit constructor arguments / factory method arguments,
* overriding the specified default arguments (if any) in the bean definition.
* @param name the name of the bean to retrieve
* @param args arguments to use if creating a prototype using explicit arguments to a
* static factory method. It is invalid to use a non-null args value in any other case.
* @param args arguments to use if creating a prototype using explicit arguments
* @return an instance of the bean
* @throws NoSuchBeanDefinitionException if there is no such bean definition
* @throws BeanDefinitionStoreException if arguments have been given but

View File

@@ -239,7 +239,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
AnnotationAttributes annotation = findAutowiredAnnotation(candidate);
if (annotation != null) {
if (requiredConstructor != null) {
throw new BeanCreationException("Invalid autowire-marked constructor: " + candidate +
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructor: " + candidate +
". Found another constructor with 'required' Autowired annotation: " +
requiredConstructor);
}
@@ -250,10 +251,10 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
boolean required = determineRequiredStatus(annotation);
if (required) {
if (!candidates.isEmpty()) {
throw new BeanCreationException(
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructors: " + candidates +
". Found another constructor with 'required' Autowired annotation: " +
requiredConstructor);
candidate);
}
requiredConstructor = candidate;
}

View File

@@ -285,8 +285,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
if (isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException("Circular depends-on relationship between '" +
beanName + "' and '" + dependsOnBean + "'");
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
}
registerDependentBean(dependsOnBean, beanName);
getBean(dependsOnBean);
@@ -1274,7 +1274,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
// Check validity of the usage of the args parameter. This can
// only be used for prototypes constructed via a factory method.
if (args != null && !mbd.isPrototype()) {
throw new BeanDefinitionStoreException(
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"Can only specify arguments for the getBean method when referring to a prototype bean definition");
}
}
@@ -1625,8 +1625,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
* instantiation within this class is performed by this method.
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @param args arguments to use if creating a prototype using explicit arguments to a
* static factory method. This parameter must be {@code null} except in this case.
* @param args arguments to use if creating a prototype using explicit arguments
* @return a new instance of the bean
* @throws BeanCreationException if the bean could not be created
*/

View File

@@ -25,7 +25,6 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanInstantiationException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.cglib.core.SpringNamingPolicy;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.CallbackFilter;
@@ -89,14 +88,13 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
*/
private static class CglibSubclassCreator {
private static final Class<?>[] CALLBACK_TYPES = new Class<?>[] { NoOp.class,
LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class };
private static final Class<?>[] CALLBACK_TYPES = new Class<?>[]
{NoOp.class, LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class};
private final RootBeanDefinition beanDefinition;
private final BeanFactory owner;
CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) {
this.beanDefinition = beanDefinition;
this.owner = owner;
@@ -113,7 +111,6 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
*/
Object instantiate(Constructor<?> ctor, Object[] args) {
Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
Object instance;
if (ctor == null) {
instance = BeanUtils.instantiate(subclass);
@@ -123,19 +120,17 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
instance = enhancedSubclassConstructor.newInstance(args);
}
catch (Exception e) {
catch (Exception ex) {
throw new BeanInstantiationException(this.beanDefinition.getBeanClass(), String.format(
"Failed to invoke construcor for CGLIB enhanced subclass [%s]", subclass.getName()), e);
"Failed to invoke constructor for CGLIB enhanced subclass [%s]", subclass.getName()), ex);
}
}
// SPR-10785: set callbacks directly on the instance instead of in the
// enhanced class (via the Enhancer) in order to avoid memory leaks.
Factory factory = (Factory) instance;
factory.setCallbacks(new Callback[] { NoOp.INSTANCE,//
new LookupOverrideMethodInterceptor(beanDefinition, owner),//
new ReplaceOverrideMethodInterceptor(beanDefinition, owner) });
factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
return instance;
}
@@ -153,6 +148,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
}
}
/**
* Class providing hashCode and equals methods required by CGLIB to
* ensure that CGLIB doesn't generate a distinct class per bean.
@@ -162,7 +158,6 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
private final RootBeanDefinition beanDefinition;
CglibIdentitySupport(RootBeanDefinition beanDefinition) {
this.beanDefinition = beanDefinition;
}
@@ -173,8 +168,8 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
@Override
public boolean equals(Object other) {
return other.getClass().equals(this.getClass())
&& ((CglibIdentitySupport) other).getBeanDefinition().equals(this.getBeanDefinition());
return (getClass().equals(other.getClass()) &&
this.beanDefinition.equals(((CglibIdentitySupport) other).beanDefinition));
}
@Override
@@ -183,6 +178,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
}
}
/**
* CGLIB callback for filtering method interception behavior.
*/
@@ -190,7 +186,6 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
private static final Log logger = LogFactory.getLog(MethodOverrideCallbackFilter.class);
MethodOverrideCallbackFilter(RootBeanDefinition beanDefinition) {
super(beanDefinition);
}
@@ -210,11 +205,12 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
else if (methodOverride instanceof ReplaceOverride) {
return METHOD_REPLACER;
}
throw new UnsupportedOperationException("Unexpected MethodOverride subclass: "
+ methodOverride.getClass().getName());
throw new UnsupportedOperationException("Unexpected MethodOverride subclass: " +
methodOverride.getClass().getName());
}
}
/**
* CGLIB MethodInterceptor to override methods, replacing them with an
* implementation that returns a bean looked up in the container.
@@ -223,7 +219,6 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
private final BeanFactory owner;
LookupOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
super(beanDefinition);
this.owner = owner;
@@ -245,7 +240,6 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
private final BeanFactory owner;
ReplaceOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
super(beanDefinition);
this.owner = owner;
@@ -255,7 +249,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
ReplaceOverride ro = (ReplaceOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
// TODO could cache if a singleton for minor performance optimization
MethodReplacer mr = owner.getBean(ro.getMethodReplacerBeanName(), MethodReplacer.class);
MethodReplacer mr = this.owner.getBean(ro.getMethodReplacerBeanName(), MethodReplacer.class);
return mr.reimplement(obj, method, args);
}
}

View File

@@ -37,8 +37,7 @@ public class LookupOverride extends MethodOverride {
/**
* Construct a new LookupOverride.
* @param methodName the name of the method to override.
* This method must have no arguments.
* @param methodName the name of the method to override
* @param beanName the name of the bean in the current BeanFactory
* that the overridden method should return
*/
@@ -48,6 +47,7 @@ public class LookupOverride extends MethodOverride {
this.beanName = beanName;
}
/**
* Return the name of the bean that should be returned by this method.
*/
@@ -63,10 +63,6 @@ public class LookupOverride extends MethodOverride {
return (method.getName().equals(getMethodName()) && method.getParameterTypes().length == 0);
}
@Override
public String toString() {
return "LookupOverride for method '" + getMethodName() + "'; will return bean '" + this.beanName + "'";
}
@Override
public boolean equals(Object other) {
@@ -79,4 +75,9 @@ public class LookupOverride extends MethodOverride {
return (29 * super.hashCode() + ObjectUtils.nullSafeHashCode(this.beanName));
}
@Override
public String toString() {
return "LookupOverride for method '" + getMethodName() + "'";
}
}

View File

@@ -52,6 +52,7 @@ public abstract class MethodOverride implements BeanMetadataElement {
this.methodName = methodName;
}
/**
* Return the name of the method to be overridden.
*/
@@ -99,6 +100,7 @@ public abstract class MethodOverride implements BeanMetadataElement {
*/
public abstract boolean matches(Method method);
@Override
public boolean equals(Object other) {
if (this == other) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,6 +52,7 @@ public class ReplaceOverride extends MethodOverride {
this.methodReplacerBeanName = methodReplacerBeanName;
}
/**
* Return the name of the bean implementing MethodReplacer.
*/
@@ -97,12 +98,6 @@ public class ReplaceOverride extends MethodOverride {
}
@Override
public String toString() {
return "Replace override for method '" + getMethodName() + "; will call bean '" +
this.methodReplacerBeanName + "'";
}
@Override
public boolean equals(Object other) {
if (!(other instanceof ReplaceOverride) || !super.equals(other)) {
@@ -121,4 +116,9 @@ public class ReplaceOverride extends MethodOverride {
return hashCode;
}
@Override
public String toString() {
return "Replace override for method '" + getMethodName() + "'";
}
}