Browse Source

Polishing

pull/423/head
Juergen Hoeller 12 years ago committed by unknown
parent
commit
eb8b5c435c
  1. 91
      spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java

91
spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java

@ -59,10 +59,10 @@ import org.springframework.util.ReflectionUtils;
class ConfigurationClassEnhancer { class ConfigurationClassEnhancer {
private static final Callback[] CALLBACKS = new Callback[] { private static final Callback[] CALLBACKS = new Callback[] {
new BeanMethodInterceptor(), new BeanMethodInterceptor(),
new DisposableBeanMethodInterceptor(), new DisposableBeanMethodInterceptor(),
new BeanFactoryAwareMethodInterceptor(), new BeanFactoryAwareMethodInterceptor(),
NoOp.INSTANCE NoOp.INSTANCE
}; };
private static final ConditionalCallbackFilter CALLBACK_FILTER = new ConditionalCallbackFilter(CALLBACKS); private static final ConditionalCallbackFilter CALLBACK_FILTER = new ConditionalCallbackFilter(CALLBACKS);
@ -137,7 +137,6 @@ class ConfigurationClassEnhancer {
} }
/** /**
* Marker interface to be implemented by all @Configuration CGLIB subclasses. * Marker interface to be implemented by all @Configuration CGLIB subclasses.
* Facilitates idempotent behavior for {@link ConfigurationClassEnhancer#enhance(Class)} * Facilitates idempotent behavior for {@link ConfigurationClassEnhancer#enhance(Class)}
@ -160,6 +159,7 @@ class ConfigurationClassEnhancer {
* @see ConditionalCallbackFilter * @see ConditionalCallbackFilter
*/ */
private static interface ConditionalCallback extends Callback { private static interface ConditionalCallback extends Callback {
boolean isMatch(Method candidateMethod); boolean isMatch(Method candidateMethod);
} }
@ -178,24 +178,23 @@ class ConfigurationClassEnhancer {
this.callbacks = callbacks; this.callbacks = callbacks;
this.callbackTypes = new Class<?>[callbacks.length]; this.callbackTypes = new Class<?>[callbacks.length];
for (int i = 0; i < callbacks.length; i++) { for (int i = 0; i < callbacks.length; i++) {
callbackTypes[i] = callbacks[i].getClass(); this.callbackTypes[i] = callbacks[i].getClass();
} }
} }
@Override @Override
public int accept(Method method) { public int accept(Method method) {
for (int i = 0; i < callbacks.length; i++) { for (int i = 0; i < this.callbacks.length; i++) {
if (!(callbacks[i] instanceof ConditionalCallback) || if (!(this.callbacks[i] instanceof ConditionalCallback) ||
((ConditionalCallback) callbacks[i]).isMatch(method)) { ((ConditionalCallback) this.callbacks[i]).isMatch(method)) {
return i; return i;
} }
} }
throw new IllegalStateException("No callback available for method " throw new IllegalStateException("No callback available for method " + method.getName());
+ method.getName());
} }
public Class<?>[] getCallbackTypes() { public Class<?>[] getCallbackTypes() {
return callbackTypes; return this.callbackTypes;
} }
} }
@ -208,24 +207,23 @@ class ConfigurationClassEnhancer {
*/ */
private static class DisposableBeanMethodInterceptor implements MethodInterceptor, ConditionalCallback { private static class DisposableBeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {
@Override
public boolean isMatch(Method candidateMethod) {
return candidateMethod.getName().equals("destroy")
&& candidateMethod.getParameterTypes().length == 0
&& DisposableBean.class.isAssignableFrom(candidateMethod.getDeclaringClass());
}
@Override @Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Enhancer.registerStaticCallbacks(obj.getClass(), null); Enhancer.registerStaticCallbacks(obj.getClass(), null);
// does the actual (non-CGLIB) superclass actually implement DisposableBean? // Does the actual (non-CGLIB) superclass actually implement DisposableBean?
// if so, call its dispose() method. If not, just exit. // If so, call its dispose() method. If not, just exit.
if (DisposableBean.class.isAssignableFrom(obj.getClass().getSuperclass())) { if (DisposableBean.class.isAssignableFrom(obj.getClass().getSuperclass())) {
return proxy.invokeSuper(obj, args); return proxy.invokeSuper(obj, args);
} }
return null; return null;
} }
@Override
public boolean isMatch(Method candidateMethod) {
return candidateMethod.getName().equals("destroy") &&
candidateMethod.getParameterTypes().length == 0 &&
DisposableBean.class.isAssignableFrom(candidateMethod.getDeclaringClass());
}
} }
@ -237,27 +235,27 @@ class ConfigurationClassEnhancer {
*/ */
private static class BeanFactoryAwareMethodInterceptor implements MethodInterceptor, ConditionalCallback { private static class BeanFactoryAwareMethodInterceptor implements MethodInterceptor, ConditionalCallback {
@Override
public boolean isMatch(Method candidateMethod) {
return candidateMethod.getName().equals("setBeanFactory") &&
candidateMethod.getParameterTypes().length == 1 &&
candidateMethod.getParameterTypes()[0].equals(BeanFactory.class) &&
BeanFactoryAware.class.isAssignableFrom(candidateMethod.getDeclaringClass());
}
@Override @Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Field field = obj.getClass().getDeclaredField(BEAN_FACTORY_FIELD); Field field = obj.getClass().getDeclaredField(BEAN_FACTORY_FIELD);
Assert.state(field != null, "Unable to find generated bean factory field"); Assert.state(field != null, "Unable to find generated BeanFactory field");
field.set(obj, args[0]); field.set(obj, args[0]);
// does the actual (non-CGLIB) superclass actually implement BeanFactoryAware? // Does the actual (non-CGLIB) superclass actually implement BeanFactoryAware?
// if so, call its setBeanFactory() method. If not, just exit. // If so, call its setBeanFactory() method. If not, just exit.
if (BeanFactoryAware.class.isAssignableFrom(obj.getClass().getSuperclass())) { if (BeanFactoryAware.class.isAssignableFrom(obj.getClass().getSuperclass())) {
return proxy.invokeSuper(obj, args); return proxy.invokeSuper(obj, args);
} }
return null; return null;
} }
@Override
public boolean isMatch(Method candidateMethod) {
return candidateMethod.getName().equals("setBeanFactory") &&
candidateMethod.getParameterTypes().length == 1 &&
candidateMethod.getParameterTypes()[0].equals(BeanFactory.class) &&
BeanFactoryAware.class.isAssignableFrom(candidateMethod.getDeclaringClass());
}
} }
@ -269,11 +267,6 @@ class ConfigurationClassEnhancer {
*/ */
private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback { private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {
@Override
public boolean isMatch(Method candidateMethod) {
return BeanAnnotationHelper.isBeanAnnotated(candidateMethod);
}
/** /**
* Enhance a {@link Bean @Bean} method to check the supplied BeanFactory for the * Enhance a {@link Bean @Bean} method to check the supplied BeanFactory for the
* existence of this bean object. * existence of this bean object.
@ -288,7 +281,7 @@ class ConfigurationClassEnhancer {
ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance); ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod); String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
// determine whether this bean is a scoped-proxy // Determine whether this bean is a scoped-proxy
Scope scope = AnnotationUtils.findAnnotation(beanMethod, Scope.class); Scope scope = AnnotationUtils.findAnnotation(beanMethod, Scope.class);
if (scope != null && scope.proxyMode() != ScopedProxyMode.NO) { if (scope != null && scope.proxyMode() != ScopedProxyMode.NO) {
String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName); String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
@ -297,28 +290,28 @@ class ConfigurationClassEnhancer {
} }
} }
// to handle the case of an inter-bean method reference, we must explicitly check the // To handle the case of an inter-bean method reference, we must explicitly check the
// container for already cached instances // container for already cached instances.
// first, check to see if the requested bean is a FactoryBean. If so, create a subclass // First, check to see if the requested bean is a FactoryBean. If so, create a subclass
// proxy that intercepts calls to getObject() and returns any cached bean instance. // 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 // 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. // is the same as that of referring to a FactoryBean within XML. See SPR-6602.
if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) && if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
factoryContainsBean(beanFactory, beanName)) { factoryContainsBean(beanFactory, beanName)) {
Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName); Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
if (factoryBean instanceof ScopedProxyFactoryBean) { if (factoryBean instanceof ScopedProxyFactoryBean) {
// pass through - scoped proxy factory beans are a special case and should not // Pass through - scoped proxy factory beans are a special case and should not
// be further proxied // be further proxied
} }
else { else {
// it is a candidate FactoryBean - go ahead with enhancement // It is a candidate FactoryBean - go ahead with enhancement
return enhanceFactoryBean(factoryBean.getClass(), beanFactory, beanName); return enhanceFactoryBean(factoryBean.getClass(), beanFactory, beanName);
} }
} }
if (isCurrentlyInvokedFactoryMethod(beanMethod) && !beanFactory.containsSingleton(beanName)) { if (isCurrentlyInvokedFactoryMethod(beanMethod) && !beanFactory.containsSingleton(beanName)) {
// the factory is calling the bean method in order to instantiate and register the bean // 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 // (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
// create the bean instance. // create the bean instance.
if (BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) { if (BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
@ -333,7 +326,7 @@ class ConfigurationClassEnhancer {
return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs); return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
} }
else { else {
// the user (i.e. not the factory) is requesting this bean through a // The user (i.e. not the factory) is requesting this bean through a
// call to the bean method, direct or indirect. The bean may have already been // call to the bean method, direct or indirect. The bean may have already been
// marked as 'in creation' in certain autowiring scenarios; if so, temporarily // marked as 'in creation' in certain autowiring scenarios; if so, temporarily
// set the in-creation status to false in order to avoid an exception. // set the in-creation status to false in order to avoid an exception.
@ -390,6 +383,7 @@ class ConfigurationClassEnhancer {
*/ */
private Object enhanceFactoryBean(Class<?> fbClass, final ConfigurableBeanFactory beanFactory, private Object enhanceFactoryBean(Class<?> fbClass, final ConfigurableBeanFactory beanFactory,
final String beanName) throws InstantiationException, IllegalAccessException { final String beanName) throws InstantiationException, IllegalAccessException {
Enhancer enhancer = new Enhancer(); Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(fbClass); enhancer.setSuperclass(fbClass);
enhancer.setUseFactory(false); enhancer.setUseFactory(false);
@ -413,6 +407,11 @@ class ConfigurationClassEnhancer {
Assert.state(beanFactory instanceof ConfigurableBeanFactory, "Injected BeanFactory is not a ConfigurableBeanFactory"); Assert.state(beanFactory instanceof ConfigurableBeanFactory, "Injected BeanFactory is not a ConfigurableBeanFactory");
return (ConfigurableBeanFactory) beanFactory; return (ConfigurableBeanFactory) beanFactory;
} }
@Override
public boolean isMatch(Method candidateMethod) {
return BeanAnnotationHelper.isBeanAnnotated(candidateMethod);
}
} }
} }

Loading…
Cancel
Save