diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java
index 99678159d3..37c74ce2a1 100644
--- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java
+++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java
@@ -17,17 +17,11 @@
package org.springframework.context.annotation;
import java.lang.reflect.Method;
+import java.util.Arrays;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.springframework.cglib.proxy.Callback;
-import org.springframework.cglib.proxy.CallbackFilter;
-import org.springframework.cglib.proxy.Enhancer;
-import org.springframework.cglib.proxy.MethodInterceptor;
-import org.springframework.cglib.proxy.MethodProxy;
-import org.springframework.cglib.proxy.NoOp;
-
import org.springframework.aop.scope.ScopedProxyFactoryBean;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.DisposableBean;
@@ -35,6 +29,12 @@ import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.SimpleInstantiationStrategy;
+import org.springframework.cglib.proxy.Callback;
+import org.springframework.cglib.proxy.CallbackFilter;
+import org.springframework.cglib.proxy.Enhancer;
+import org.springframework.cglib.proxy.MethodInterceptor;
+import org.springframework.cglib.proxy.MethodProxy;
+import org.springframework.cglib.proxy.NoOp;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.Assert;
@@ -52,8 +52,8 @@ class ConfigurationClassEnhancer {
private static final Log logger = LogFactory.getLog(ConfigurationClassEnhancer.class);
- private static final Class>[] CALLBACK_TYPES = { BeanMethodInterceptor.class,
- DisposableBeanMethodInterceptor.class, NoOp.class };
+ private static final Class>[] CALLBACK_TYPES = {BeanMethodInterceptor.class,
+ DisposableBeanMethodInterceptor.class, NoOp.class};
private static final CallbackFilter CALLBACK_FILTER = new CallbackFilter() {
public int accept(Method candidateMethod) {
@@ -80,10 +80,8 @@ class ConfigurationClassEnhancer {
public ConfigurationClassEnhancer(ConfigurableBeanFactory beanFactory) {
Assert.notNull(beanFactory, "BeanFactory must not be null");
// Callback instances must be ordered in the same way as CALLBACK_TYPES and CALLBACK_FILTER
- this.callbackInstances = new Callback[] {
- new BeanMethodInterceptor(beanFactory),
- DISPOSABLE_BEAN_METHOD_INTERCEPTOR,
- NoOp.INSTANCE };
+ this.callbackInstances = new Callback[]
+ {new BeanMethodInterceptor(beanFactory), DISPOSABLE_BEAN_METHOD_INTERCEPTOR, NoOp.INSTANCE};
}
/**
@@ -169,9 +167,8 @@ class ConfigurationClassEnhancer {
}
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
- return beanFactory.getBean(beanName);
+ return this.beanFactory.getBean(this.beanName);
}
-
}
@@ -209,19 +206,16 @@ class ConfigurationClassEnhancer {
*/
private static class BeanMethodInterceptor implements MethodInterceptor {
- private static final Class>[] CALLBACK_TYPES = {
- GetObjectMethodInterceptor.class, NoOp.class };
+ private static final Class>[] CALLBACK_TYPES = {GetObjectMethodInterceptor.class, NoOp.class};
- private static final CallbackFilter CALLBACK_FITLER = new CallbackFilter() {
+ private static final CallbackFilter CALLBACK_FILTER = new CallbackFilter() {
public int accept(Method method) {
- return method.getName().equals("getObject") ? 0 : 1;
+ return (method.getName().equals("getObject") ? 0 : 1);
}
};
-
private final ConfigurableBeanFactory beanFactory;
-
public BeanMethodInterceptor(ConfigurableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@@ -229,7 +223,6 @@ class ConfigurationClassEnhancer {
/**
* Enhance a {@link Bean @Bean} method to check the supplied BeanFactory for the
* existence of this bean object.
- *
* @throws Throwable as a catch-all for any exception that may be thrown when
* invoking the super implementation of the proxied method i.e., the actual
* {@code @Bean} method.
@@ -255,8 +248,8 @@ class ConfigurationClassEnhancer {
// proxy that intercepts calls to getObject() and returns any cached bean instance.
// this ensures that the semantics of calling a FactoryBean from within @Bean methods
// is the same as that of referring to a FactoryBean within XML. See SPR-6602.
- if (factoryContainsBean('&'+beanName) && factoryContainsBean(beanName)) {
- Object factoryBean = this.beanFactory.getBean('&'+beanName);
+ if (factoryContainsBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName) && factoryContainsBean(beanName)) {
+ Object factoryBean = this.beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
if (factoryBean instanceof ScopedProxyFactoryBean) {
// pass through - scoped proxy factory beans are a special case and should not
// be further proxied
@@ -267,9 +260,7 @@ class ConfigurationClassEnhancer {
}
}
- boolean factoryIsCaller = beanMethod.equals(SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod());
- boolean factoryAlreadyContainsSingleton = this.beanFactory.containsSingleton(beanName);
- if (factoryIsCaller && !factoryAlreadyContainsSingleton) {
+ if (isCurrentlyInvokedFactoryMethod(beanMethod) && !this.beanFactory.containsSingleton(beanName)) {
// the factory is calling the bean method in order to instantiate and register the bean
// (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
// create the bean instance.
@@ -306,7 +297,7 @@ class ConfigurationClassEnhancer {
}
/**
- * Check the beanFactory to see whether the bean named beanName already
+ * Check the BeanFactory to see whether the bean named beanName already
* exists. Accounts for the fact that the requested bean may be "in creation", i.e.:
* we're in the middle of servicing the initial request for this bean. From an enhanced
* factory method's perspective, this means that the bean does not actually yet exist,
@@ -319,9 +310,19 @@ class ConfigurationClassEnhancer {
* @return whether beanName already exists in the factory
*/
private boolean factoryContainsBean(String beanName) {
- boolean containsBean = this.beanFactory.containsBean(beanName);
- boolean currentlyInCreation = this.beanFactory.isCurrentlyInCreation(beanName);
- return (containsBean && !currentlyInCreation);
+ return (this.beanFactory.containsBean(beanName) && !this.beanFactory.isCurrentlyInCreation(beanName));
+ }
+
+ /**
+ * Check whether the given method corresponds to the container's currently invoked
+ * factory method. Compares method name and parameter types only in order to work
+ * around a potential problem with covariant return types (currently only known
+ * to happen on Groovy classes).
+ */
+ private boolean isCurrentlyInvokedFactoryMethod(Method method) {
+ Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
+ return (currentlyInvoked != null && method.getName().equals(currentlyInvoked.getName()) &&
+ Arrays.equals(method.getParameterTypes(), currentlyInvoked.getParameterTypes()));
}
/**
@@ -335,13 +336,12 @@ class ConfigurationClassEnhancer {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(fbClass);
enhancer.setUseFactory(false);
- enhancer.setCallbackFilter(CALLBACK_FITLER);
+ enhancer.setCallbackFilter(CALLBACK_FILTER);
// Callback instances must be ordered in the same way as CALLBACK_TYPES and CALLBACK_FILTER
Callback[] callbackInstances = new Callback[] {
new GetObjectMethodInterceptor(this.beanFactory, beanName),
NoOp.INSTANCE
};
-
enhancer.setCallbackTypes(CALLBACK_TYPES);
Class> fbSubclass = enhancer.createClass();
Enhancer.registerCallbacks(fbSubclass, callbackInstances);