Polishing

This commit is contained in:
Juergen Hoeller 2013-12-02 16:32:02 +01:00
parent 1dc79f7f9c
commit 5639eb66b6
7 changed files with 63 additions and 64 deletions

View File

@ -38,7 +38,7 @@ public abstract class ScopedProxyUtils {
/** /**
* Generates a scoped proxy for the supplied target bean, registering the target * Generate a scoped proxy for the supplied target bean, registering the target
* bean with an internal name and setting 'targetBeanName' on the scoped proxy. * bean with an internal name and setting 'targetBeanName' on the scoped proxy.
* @param definition the original bean definition * @param definition the original bean definition
* @param registry the bean definition registry * @param registry the bean definition registry
@ -63,7 +63,7 @@ public abstract class ScopedProxyUtils {
if (proxyTargetClass) { if (proxyTargetClass) {
targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE); targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
// ScopedFactoryBean's "proxyTargetClass" default is TRUE, so we don't need to set it explicitly here. // ScopedProxyFactoryBean's "proxyTargetClass" default is TRUE, so we don't need to set it explicitly here.
} }
else { else {
proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE); proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);

View File

@ -50,15 +50,15 @@ import org.springframework.util.Assert;
*/ */
class ConfigurationClassEnhancer { class ConfigurationClassEnhancer {
private static final Log logger = LogFactory.getLog(ConfigurationClassEnhancer.class);
private static final CallbackFilter CALLBACK_FILTER = new ConfigurationClassCallbackFilter();
private static final Callback DISPOSABLE_BEAN_METHOD_INTERCEPTOR = new DisposableBeanMethodInterceptor(); private static final Callback DISPOSABLE_BEAN_METHOD_INTERCEPTOR = new DisposableBeanMethodInterceptor();
private static final Class<?>[] CALLBACK_TYPES = private static final Class<?>[] CALLBACK_TYPES =
{BeanMethodInterceptor.class, DisposableBeanMethodInterceptor.class, NoOp.class}; {BeanMethodInterceptor.class, DisposableBeanMethodInterceptor.class, NoOp.class};
private static final CallbackFilter CALLBACK_FILTER = new ConfigurationClassCallbackFilter();
private static final Log logger = LogFactory.getLog(ConfigurationClassEnhancer.class);
private final Callback[] callbackInstances; private final Callback[] callbackInstances;
@ -103,7 +103,7 @@ class ConfigurationClassEnhancer {
private Enhancer newEnhancer(Class<?> superclass) { private Enhancer newEnhancer(Class<?> superclass) {
Enhancer enhancer = new Enhancer(); Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(superclass); enhancer.setSuperclass(superclass);
enhancer.setInterfaces(new Class[] {EnhancedConfiguration.class}); enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
enhancer.setUseFactory(false); enhancer.setUseFactory(false);
enhancer.setCallbackFilter(CALLBACK_FILTER); enhancer.setCallbackFilter(CALLBACK_FILTER);
enhancer.setCallbackTypes(CALLBACK_TYPES); enhancer.setCallbackTypes(CALLBACK_TYPES);
@ -116,13 +116,13 @@ class ConfigurationClassEnhancer {
*/ */
private Class<?> createClass(Enhancer enhancer) { private Class<?> createClass(Enhancer enhancer) {
Class<?> subclass = enhancer.createClass(); Class<?> subclass = enhancer.createClass();
// registering callbacks statically (as opposed to threadlocal) is critical for usage in an OSGi env (SPR-5932) // Registering callbacks statically (as opposed to thread-local)
// is critical for usage in an OSGi environment (SPR-5932)...
Enhancer.registerStaticCallbacks(subclass, this.callbackInstances); Enhancer.registerStaticCallbacks(subclass, this.callbackInstances);
return subclass; return subclass;
} }
/** /**
* 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)}
@ -192,8 +192,8 @@ class ConfigurationClassEnhancer {
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);
} }
@ -242,7 +242,7 @@ class ConfigurationClassEnhancer {
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);
@ -251,27 +251,27 @@ 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.FACTORY_BEAN_PREFIX + beanName) && factoryContainsBean(beanName)) { if (factoryContainsBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName) && factoryContainsBean(beanName)) {
Object factoryBean = this.beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName); Object factoryBean = this.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(), beanName); return enhanceFactoryBean(factoryBean.getClass(), beanName);
} }
} }
if (isCurrentlyInvokedFactoryMethod(beanMethod) && !this.beanFactory.containsSingleton(beanName)) { if (isCurrentlyInvokedFactoryMethod(beanMethod) && !this.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())) {
@ -286,7 +286,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.
@ -303,7 +303,6 @@ class ConfigurationClassEnhancer {
} }
} }
} }
} }
/** /**

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2013 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.
@ -25,6 +25,7 @@ import org.springframework.context.annotation.ImportAware;
import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
/** /**
* Abstract base {@code Configuration} class providing common structure for enabling * Abstract base {@code Configuration} class providing common structure for enabling
@ -38,16 +39,33 @@ import org.springframework.util.Assert;
public abstract class AbstractAsyncConfiguration implements ImportAware { public abstract class AbstractAsyncConfiguration implements ImportAware {
protected AnnotationAttributes enableAsync; protected AnnotationAttributes enableAsync;
protected Executor executor; protected Executor executor;
public void setImportMetadata(AnnotationMetadata importMetadata) { public void setImportMetadata(AnnotationMetadata importMetadata) {
this.enableAsync = AnnotationAttributes.fromMap( this.enableAsync = AnnotationAttributes.fromMap(
importMetadata.getAnnotationAttributes(EnableAsync.class.getName(), false)); importMetadata.getAnnotationAttributes(EnableAsync.class.getName(), false));
Assert.notNull(this.enableAsync, Assert.notNull(this.enableAsync,
"@EnableAsync is not present on importing class " + "@EnableAsync is not present on importing class " + importMetadata.getClassName());
importMetadata.getClassName());
} }
/**
* Collect any {@link AsyncConfigurer} beans through autowiring.
*/
@Autowired(required = false)
void setConfigurers(Collection<AsyncConfigurer> configurers) {
if (CollectionUtils.isEmpty(configurers)) {
return;
}
if (configurers.size() > 1) {
throw new IllegalStateException("Only one AsyncConfigurer may exist");
}
AsyncConfigurer configurer = configurers.iterator().next();
this.executor = configurer.getAsyncExecutor();
}
/** /**
* The component that will apply async execution advice to beans annotated with * The component that will apply async execution advice to beans annotated with
* the async annotation. Subclasses will provide either a BeanPostProcessor in * the async annotation. Subclasses will provide either a BeanPostProcessor in
@ -55,20 +73,4 @@ public abstract class AbstractAsyncConfiguration implements ImportAware {
*/ */
public abstract Object asyncAdvisor(); public abstract Object asyncAdvisor();
/**
* Collect any {@link AsyncConfigurer} beans through autowiring.
*/
@Autowired(required = false)
void setConfigurers(Collection<AsyncConfigurer> configurers) {
if (configurers == null || configurers.isEmpty()) {
return;
}
if (configurers.size() > 1) {
throw new IllegalStateException("only one AsyncConfigurer may exist");
}
AsyncConfigurer configurer = configurers.iterator().next();
this.executor = configurer.getAsyncExecutor();
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2011 the original author or authors. * Copyright 2002-2013 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.
@ -24,8 +24,8 @@ package org.springframework.core.env;
* property resolution and profile-related operations, this implementation configures two * property resolution and profile-related operations, this implementation configures two
* default property sources, to be searched in the following order: * default property sources, to be searched in the following order:
* <ul> * <ul>
* <li>{@linkplain AbstractEnvironment#getSystemProperties() system properties} * <li>{@linkplain AbstractEnvironment#getSystemProperties() system properties}
* <li>{@linkplain AbstractEnvironment#getSystemEnvironment() system environment variables} * <li>{@linkplain AbstractEnvironment#getSystemEnvironment() system environment variables}
* </ul> * </ul>
* *
* That is, if the key "xyz" is present both in the JVM system properties as well as in * That is, if the key "xyz" is present both in the JVM system properties as well as in
@ -41,7 +41,7 @@ package org.springframework.core.env;
* instance available from {@link #getPropertySources()}. See * instance available from {@link #getPropertySources()}. See
* {@link ConfigurableEnvironment} Javadoc for usage examples. * {@link ConfigurableEnvironment} Javadoc for usage examples.
* *
* <p>See {@link SystemEnvironmentPropertySource} Javadoc for details on special handling * <p>See {@link SystemEnvironmentPropertySource} javadoc for details on special handling
* of property names in shell environments (e.g. Bash) that disallow period characters in * of property names in shell environments (e.g. Bash) that disallow period characters in
* variable names. * variable names.
* *
@ -61,8 +61,8 @@ public class StandardEnvironment extends AbstractEnvironment {
/** /**
* Customize the set of property sources with those appropriate for any standard Java * Customize the set of property sources with those appropriate for any standard
* environment: * Java environment:
* <ul> * <ul>
* <li>{@value #SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME} * <li>{@value #SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME}
* <li>{@value #SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME} * <li>{@value #SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2013 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.
@ -17,12 +17,12 @@
package org.springframework.test.context.support; package org.springframework.test.context.support;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ApplicationContextInitializer;
@ -120,12 +120,11 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected void prepareContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedConfig) { protected void prepareContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedConfig) {
context.getEnvironment().setActiveProfiles(mergedConfig.getActiveProfiles()); context.getEnvironment().setActiveProfiles(mergedConfig.getActiveProfiles());
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses = mergedConfig.getContextInitializerClasses(); Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses =
mergedConfig.getContextInitializerClasses();
if (initializerClasses.size() == 0) { if (initializerClasses.isEmpty()) {
// no ApplicationContextInitializers have been declared -> nothing to do // no ApplicationContextInitializers have been declared -> nothing to do
return; return;
} }
@ -144,7 +143,7 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
initializerInstances.add((ApplicationContextInitializer<ConfigurableApplicationContext>) BeanUtils.instantiateClass(initializerClass)); initializerInstances.add((ApplicationContextInitializer<ConfigurableApplicationContext>) BeanUtils.instantiateClass(initializerClass));
} }
Collections.sort(initializerInstances, new AnnotationAwareOrderComparator()); AnnotationAwareOrderComparator.sort(initializerInstances);
for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : initializerInstances) { for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : initializerInstances) {
initializer.initialize(context); initializer.initialize(context);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2013 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.
@ -25,6 +25,7 @@ import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.AnnotationMetadata;
import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
/** /**
* Abstract base {@code @Configuration} class providing common structure for enabling * Abstract base {@code @Configuration} class providing common structure for enabling
@ -38,26 +39,25 @@ import org.springframework.util.Assert;
public abstract class AbstractTransactionManagementConfiguration implements ImportAware { public abstract class AbstractTransactionManagementConfiguration implements ImportAware {
protected AnnotationAttributes enableTx; protected AnnotationAttributes enableTx;
protected PlatformTransactionManager txManager; protected PlatformTransactionManager txManager;
public void setImportMetadata(AnnotationMetadata importMetadata) { public void setImportMetadata(AnnotationMetadata importMetadata) {
this.enableTx = AnnotationAttributes.fromMap( this.enableTx = AnnotationAttributes.fromMap(
importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false)); importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false));
Assert.notNull(this.enableTx, Assert.notNull(this.enableTx,
"@EnableTransactionManagement is not present on importing class " + "@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName());
importMetadata.getClassName());
} }
@Autowired(required=false) @Autowired(required=false)
void setConfigurers(Collection<TransactionManagementConfigurer> configurers) { void setConfigurers(Collection<TransactionManagementConfigurer> configurers) {
if (configurers == null || configurers.isEmpty()) { if (CollectionUtils.isEmpty(configurers)) {
return; return;
} }
if (configurers.size() > 1) { if (configurers.size() > 1) {
throw new IllegalStateException("only one TransactionManagementConfigurer may exist"); throw new IllegalStateException("Only one TransactionManagementConfigurer may exist");
} }
TransactionManagementConfigurer configurer = configurers.iterator().next(); TransactionManagementConfigurer configurer = configurers.iterator().next();
this.txManager = configurer.annotationDrivenTransactionManager(); this.txManager = configurer.annotationDrivenTransactionManager();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2011 the original author or authors. * Copyright 2002-2013 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.
@ -45,13 +45,12 @@ public class TransactionManagementConfigurationSelector
protected String[] selectImports(AdviceMode adviceMode) { protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) { switch (adviceMode) {
case PROXY: case PROXY:
return new String[] { AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName() }; return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ: case ASPECTJ:
return new String[] { TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME }; return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
default: default:
return null; return null;
} }
} }
} }