Commit 1cb0ad9c authored by Emmanuel Bourg's avatar Emmanuel Bourg

New upstream version 4.3.13

parent 86ee2f0c
......@@ -40,7 +40,7 @@ configure(allprojects) { project ->
ext.ejbVersion = "3.0"
ext.fileuploadVersion = "1.3.3"
ext.freemarkerVersion = "2.3.23"
ext.groovyVersion = "2.4.12"
ext.groovyVersion = "2.4.13"
ext.gsonVersion = "2.8.2"
ext.guavaVersion = "20.0"
ext.hamcrestVersion = "1.3"
......@@ -62,7 +62,7 @@ configure(allprojects) { project ->
ext.jtaVersion = "1.2"
ext.junitVersion = "4.12"
ext.log4jVersion = "1.2.17"
ext.nettyVersion = "4.1.16.Final"
ext.nettyVersion = "4.1.17.Final"
ext.okhttpVersion = "2.7.5"
ext.okhttp3Version = "3.8.1"
ext.openjpaVersion = "2.4.2"
......@@ -77,7 +77,7 @@ configure(allprojects) { project ->
ext.tiles3Version = "3.0.7"
ext.tomcatVersion = "8.5.23"
ext.tyrusVersion = "1.3.5" // constrained by WebLogic 12.1.3 support
ext.undertowVersion = "1.3.31.Final"
ext.undertowVersion = "1.3.33.Final"
ext.xmlunitVersion = "1.6"
ext.xstreamVersion = "1.4.9"
......
version=4.3.12.RELEASE
version=4.3.13.RELEASE
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
......@@ -23,29 +23,33 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marks a constructor, field, setter method or config method as to be
* autowired by Spring's dependency injection facilities.
* Marks a constructor, field, setter method or config method as to be autowired
* by Spring's dependency injection facilities.
*
* <p>Only one constructor (at max) of any given bean class may carry this
* annotation, indicating the constructor to autowire when used as a Spring
* bean. Such a constructor does not have to be public.
* <p>Only one constructor (at max) of any given bean class may carry this annotation,
* indicating the constructor to autowire when used as a Spring bean. Such a
* constructor does not have to be public.
*
* <p>Fields are injected right after construction of a bean, before any
* config methods are invoked. Such a config field does not have to be public.
* <p>Fields are injected right after construction of a bean, before any config
* methods are invoked. Such a config field does not have to be public.
*
* <p>Config methods may have an arbitrary name and any number of arguments;
* each of those arguments will be autowired with a matching bean in the
* Spring container. Bean property setter methods are effectively just
* a special case of such a general config method. Such config methods
* do not have to be public.
* <p>Config methods may have an arbitrary name and any number of arguments; each of
* those arguments will be autowired with a matching bean in the Spring container.
* Bean property setter methods are effectively just a special case of such a general
* config method. Such config methods do not have to be public.
*
* <p>In the case of multiple argument methods, the 'required' parameter is
* applicable for all arguments.
* <p>In the case of a multi-arg constructor or method, the 'required' parameter is
* applicable to all arguments. Individual parameters may be declared as Java-8-style
* {@link java.util.Optional}, overriding the base required semantics.
*
* <p>In case of a {@link java.util.Collection} or {@link java.util.Map}
* dependency type, the container will autowire all beans matching the
* declared value type. In case of a Map, the keys must be declared as
* type String and will be resolved to the corresponding bean names.
* <p>In case of a {@link java.util.Collection} or {@link java.util.Map} dependency type,
* the container autowires all beans matching the declared value type. For such purposes,
* the map keys must be declared as type String which will be resolved to the corresponding
* bean names. Such a container-provided collection will be ordered, taking into account
* {@link org.springframework.core.Ordered}/{@link org.springframework.core.annotation.Order}
* values of the target components, otherwise following their registration order in the
* container. Alternatively, a single matching target bean may also be a generally typed
* {@code Collection} or {@code Map} itself, getting injected as such.
*
* <p>Note that actual injection is performed through a
* {@link org.springframework.beans.factory.config.BeanPostProcessor
......
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2017 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.
......@@ -140,7 +140,7 @@ public class MethodInvokingFactoryBeanTests {
mcfb.setTargetMethod("voidRetvalMethod");
mcfb.afterPropertiesSet();
Class<?> objType = mcfb.getObjectType();
assertTrue(objType.equals(void.class));
assertSame(objType, void.class);
// verify that we can call a method with args that are subtypes of the
// target method arg types
......@@ -148,7 +148,7 @@ public class MethodInvokingFactoryBeanTests {
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetClass(TestClass1.class);
mcfb.setTargetMethod("supertypes");
mcfb.setArguments(new Object[] {new ArrayList<Object>(), new ArrayList<Object>(), "hello"});
mcfb.setArguments(new ArrayList<>(), new ArrayList<Object>(), "hello");
mcfb.afterPropertiesSet();
mcfb.getObjectType();
......@@ -157,7 +157,7 @@ public class MethodInvokingFactoryBeanTests {
mcfb.registerCustomEditor(String.class, new StringTrimmerEditor(false));
mcfb.setTargetClass(TestClass1.class);
mcfb.setTargetMethod("supertypes");
mcfb.setArguments(new Object[] {"1", new Object()});
mcfb.setArguments("1", new Object());
try {
mcfb.afterPropertiesSet();
fail("Should have thrown NoSuchMethodException");
......@@ -225,7 +225,7 @@ public class MethodInvokingFactoryBeanTests {
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetClass(TestClass1.class);
mcfb.setTargetMethod("supertypes");
mcfb.setArguments(new Object[] {new ArrayList<Object>(), new ArrayList<Object>(), "hello"});
mcfb.setArguments(new ArrayList<>(), new ArrayList<Object>(), "hello");
// should pass
mcfb.afterPropertiesSet();
}
......@@ -235,7 +235,7 @@ public class MethodInvokingFactoryBeanTests {
MethodInvokingFactoryBean mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetClass(TestClass1.class);
mcfb.setTargetMethod("supertypes");
mcfb.setArguments(new Object[] {new ArrayList<Object>(), new ArrayList<Object>(), "hello", "bogus"});
mcfb.setArguments(new ArrayList<>(), new ArrayList<Object>(), "hello", "bogus");
try {
mcfb.afterPropertiesSet();
fail("Matched method with wrong number of args");
......@@ -247,7 +247,7 @@ public class MethodInvokingFactoryBeanTests {
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetClass(TestClass1.class);
mcfb.setTargetMethod("supertypes");
mcfb.setArguments(new Object[] {1, new Object()});
mcfb.setArguments(1, new Object());
try {
mcfb.afterPropertiesSet();
mcfb.getObject();
......@@ -260,14 +260,14 @@ public class MethodInvokingFactoryBeanTests {
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetClass(TestClass1.class);
mcfb.setTargetMethod("supertypes2");
mcfb.setArguments(new Object[] {new ArrayList<Object>(), new ArrayList<Object>(), "hello", "bogus"});
mcfb.setArguments(new ArrayList<>(), new ArrayList<Object>(), "hello", "bogus");
mcfb.afterPropertiesSet();
assertEquals("hello", mcfb.getObject());
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetClass(TestClass1.class);
mcfb.setTargetMethod("supertypes2");
mcfb.setArguments(new Object[] {new ArrayList<Object>(), new ArrayList<Object>(), new Object()});
mcfb.setArguments(new ArrayList<>(), new ArrayList<Object>(), new Object());
try {
mcfb.afterPropertiesSet();
fail("Matched method when shouldn't have matched");
......@@ -292,14 +292,14 @@ public class MethodInvokingFactoryBeanTests {
ArgumentConvertingMethodInvoker methodInvoker = new ArgumentConvertingMethodInvoker();
methodInvoker.setTargetClass(TestClass1.class);
methodInvoker.setTargetMethod("intArgument");
methodInvoker.setArguments(new Object[] {5});
methodInvoker.setArguments(5);
methodInvoker.prepare();
methodInvoker.invoke();
methodInvoker = new ArgumentConvertingMethodInvoker();
methodInvoker.setTargetClass(TestClass1.class);
methodInvoker.setTargetMethod("intArgument");
methodInvoker.setArguments(new Object[] {"5"});
methodInvoker.setArguments(5);
methodInvoker.prepare();
methodInvoker.invoke();
}
......@@ -309,37 +309,37 @@ public class MethodInvokingFactoryBeanTests {
MethodInvokingBean methodInvoker = new MethodInvokingBean();
methodInvoker.setTargetClass(TestClass1.class);
methodInvoker.setTargetMethod("intArguments");
methodInvoker.setArguments(new Object[]{new Integer[] {5, 10}});
methodInvoker.setArguments(new Object[] {new Integer[] {5, 10}});
methodInvoker.afterPropertiesSet();
methodInvoker = new MethodInvokingBean();
methodInvoker.setTargetClass(TestClass1.class);
methodInvoker.setTargetMethod("intArguments");
methodInvoker.setArguments(new Object[]{new String[]{"5", "10"}});
methodInvoker.setArguments(new Object[] {new String[] {"5", "10"}});
methodInvoker.afterPropertiesSet();
methodInvoker = new MethodInvokingBean();
methodInvoker.setTargetClass(TestClass1.class);
methodInvoker.setTargetMethod("intArguments");
methodInvoker.setArguments(new Object[]{new Integer[] {5, 10}});
methodInvoker.setArguments(new Object[] {new Integer[] {5, 10}});
methodInvoker.afterPropertiesSet();
methodInvoker = new MethodInvokingBean();
methodInvoker.setTargetClass(TestClass1.class);
methodInvoker.setTargetMethod("intArguments");
methodInvoker.setArguments(new String[]{"5", "10"});
methodInvoker.setArguments("5", "10");
methodInvoker.afterPropertiesSet();
methodInvoker = new MethodInvokingBean();
methodInvoker.setTargetClass(TestClass1.class);
methodInvoker.setTargetMethod("intArguments");
methodInvoker.setArguments(new Object[]{new Integer[] {5, 10}});
methodInvoker.setArguments(new Object[] {new Integer[] {5, 10}});
methodInvoker.afterPropertiesSet();
methodInvoker = new MethodInvokingBean();
methodInvoker.setTargetClass(TestClass1.class);
methodInvoker.setTargetMethod("intArguments");
methodInvoker.setArguments(new Object[]{"5", "10"});
methodInvoker.setArguments("5", "10");
methodInvoker.afterPropertiesSet();
}
......
......@@ -24,7 +24,8 @@ import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
* Models a simple mail message, including data such as the from, to, cc, subject, and text fields.
* Models a simple mail message, including data such as the from, to, cc, subject,
* and text fields.
*
* <p>Consider {@code JavaMailSender} and JavaMail {@code MimeMessages} for creating
* more sophisticated messages, for example messages with attachments, special
......@@ -179,10 +180,9 @@ public class SimpleMailMessage implements MailMessage, Serializable {
/**
* Copy the contents of this message to the given target message.
* @param target the {@code MailMessage} to copy to
* @throws IllegalArgumentException if the supplied {@code target} is {@code null}
*/
public void copyTo(MailMessage target) {
Assert.notNull(target, "The 'target' message argument cannot be null");
Assert.notNull(target, "'target' message argument must not be null");
if (getFrom() != null) {
target.setFrom(getFrom());
}
......
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
......@@ -148,15 +148,19 @@ import org.springframework.core.Ordered;
* can be useful if you do not need to customize everything. See {@link CachingConfigurer}
* Javadoc for further details.
*
* <p>The {@link #mode()} attribute controls how advice is applied; if the mode is
* {@link AdviceMode#PROXY} (the default), then the other attributes such as
* {@link #proxyTargetClass()} control the behavior of the proxying.
* <p>The {@link #mode} attribute controls how advice is applied: If the mode is
* {@link AdviceMode#PROXY} (the default), then the other attributes control the behavior
* of the proxying. Please note that proxy mode allows for interception of calls through
* the proxy only; local calls within the same class cannot get intercepted that way.
*
* <p>If the {@linkplain #mode} is set to {@link AdviceMode#ASPECTJ}, then the
* {@link #proxyTargetClass()} attribute is obsolete. Note also that in this case the
* {@code spring-aspects} module JAR must be present on the classpath.
* <p>Note that if the {@linkplain #mode} is set to {@link AdviceMode#ASPECTJ}, then the
* value of the {@link #proxyTargetClass} attribute will be ignored. Note also that in
* this case the {@code spring-aspects} module JAR must be present on the classpath, with
* compile-time weaving or load-time weaving applying the aspect to the affected classes.
* There is no proxy involved in such a scenario; local calls will be intercepted as well.
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1
* @see CachingConfigurer
* @see CachingConfigurationSelector
......@@ -183,16 +187,21 @@ public @interface EnableCaching {
boolean proxyTargetClass() default false;
/**
* Indicate how caching advice should be applied. The default is
* {@link AdviceMode#PROXY}.
* @see AdviceMode
* Indicate how caching advice should be applied.
* <p><b>The default is {@link AdviceMode#PROXY}.</b>
* Please note that proxy mode allows for interception of calls through the proxy
* only. Local calls within the same class cannot get intercepted that way;
* a caching annotation on such a method within a local call will be ignored
* since Spring's interceptor does not even kick in for such a runtime scenario.
* For a more advanced mode of interception, consider switching this to
* {@link AdviceMode#ASPECTJ}.
*/
AdviceMode mode() default AdviceMode.PROXY;
/**
* Indicate the ordering of the execution of the caching advisor
* when multiple advices are applied at a specific joinpoint.
* The default is {@link Ordered#LOWEST_PRECEDENCE}.
* <p>The default is {@link Ordered#LOWEST_PRECEDENCE}.
*/
int order() default Ordered.LOWEST_PRECEDENCE;
......
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
......@@ -60,15 +60,16 @@ import org.springframework.core.annotation.AliasFor;
* }
* </pre>
*
* <h3>Scope, DependsOn, Primary, and Lazy</h3>
* <h3>Profile, Scope, Lazy, DependsOn, Primary, Order</h3>
*
* <p>Note that the {@code @Bean} annotation does not provide attributes for scope,
* depends-on, primary, or lazy. Rather, it should be used in conjunction with
* {@link Scope @Scope}, {@link DependsOn @DependsOn}, {@link Primary @Primary},
* and {@link Lazy @Lazy} annotations to achieve those semantics. For example:
* <p>Note that the {@code @Bean} annotation does not provide attributes for profile,
* scope, lazy, depends-on or primary. Rather, it should be used in conjunction with
* {@link Scope @Scope}, {@link Lazy @Lazy}, {@link DependsOn @DependsOn} and
* {@link Primary @Primary} annotations to declare those semantics. For example:
*
* <pre class="code">
* &#064;Bean
* &#064;Profile("production")
* &#064;Scope("prototype")
* public MyBean myBean() {
* // instantiate and configure MyBean obj
......@@ -76,6 +77,33 @@ import org.springframework.core.annotation.AliasFor;
* }
* </pre>
*
* The semantics of the above-mentioned annotations match their use at the component
* class level: {@code Profile} allows for selective inclusion of certain beans.
* {@code @Scope} changes the bean's scope from singleton to the specified scope.
* {@code @Lazy} only has an actual effect in case of the default singleton scope.
* {@code @DependsOn} enforces the creation of specific other beans before this
* bean will be created, in addition to any dependencies that the bean expressed
* through direct references, which is typically helpful for singleton startup.
* {@code @Primary} is a mechanism to resolve ambiguity at the injection point level
* if a single target component needs to be injected but several beans match by type.
*
* <p>Additionally, {@code @Bean} methods may also declare qualifier annotations
* and {@link org.springframework.core.annotation.Order @Order} values, to be
* taken into account during injection point resolution just like corresponding
* annotations on the corresponding component classes but potentially being very
* individual per bean definition (in case of multiple definitions with the same
* bean class). Qualifiers narrow the set of candidates after the initial type match;
* order values determine the order of resolved elements in case of collection
* injection points (with several target beans matching by type and qualifier).
*
* <p><b>NOTE:</b> {@code @Order} values may influence priorities at injection points
* but please be aware that they do not influence singleton startup order which is an
* orthogonal concern determined by dependency relationships and {@code @DependsOn}
* declarations as mentioned above. Also, {@link javax.annotation.Priority} is not
* available at this level since it cannot be declared on methods; its semantics can
* be modelled through {@code @Order} values in combination with {@code @Primary} on
* a single bean per type.
*
* <h3>{@code @Bean} Methods in {@code @Configuration} Classes</h3>
*
* <p>Typically, {@code @Bean} methods are declared within {@code @Configuration}
......@@ -143,7 +171,7 @@ import org.springframework.core.annotation.AliasFor;
*
* <h3>Bootstrapping</h3>
*
* <p>See @{@link Configuration} Javadoc for further details including how to bootstrap
* <p>See the @{@link Configuration} javadoc for further details including how to bootstrap
* the container using {@link AnnotationConfigApplicationContext} and friends.
*
* <h3>{@code BeanFactoryPostProcessor}-returning {@code @Bean} methods</h3>
......@@ -157,8 +185,8 @@ import org.springframework.core.annotation.AliasFor;
*
* <pre class="code">
* &#064;Bean
* public static PropertyPlaceholderConfigurer ppc() {
* // instantiate, configure and return ppc ...
* public static PropertySourcesPlaceholderConfigurer pspc() {
* // instantiate, configure and return pspc ...
* }
* </pre>
*
......@@ -228,6 +256,8 @@ public @interface Bean {
* Not commonly used, given that the method may be called programmatically directly
* within the body of a Bean-annotated method.
* <p>The default value is {@code ""}, indicating no init method to be called.
* @see org.springframework.beans.factory.InitializingBean
* @see org.springframework.context.ConfigurableApplicationContext#refresh()
*/
String initMethod() default "";
......@@ -248,12 +278,14 @@ public @interface Bean {
* creation time).
* <p>To disable destroy method inference for a particular {@code @Bean}, specify an
* empty string as the value, e.g. {@code @Bean(destroyMethod="")}. Note that the
* {@link org.springframework.beans.factory.DisposableBean} and the
* {@link java.io.Closeable}/{@link java.lang.AutoCloseable} interfaces will
* nevertheless get detected and the corresponding destroy/close method invoked.
* {@link org.springframework.beans.factory.DisposableBean} callback interface will
* nevertheless get detected and the corresponding destroy method invoked: In other
* words, {@code destroyMethod=""} only affects custom close/shutdown methods and
* {@link java.io.Closeable}/{@link java.lang.AutoCloseable} declared close methods.
* <p>Note: Only invoked on beans whose lifecycle is under the full control of the
* factory, which is always the case for singletons but not guaranteed for any
* other scope.
* @see org.springframework.beans.factory.DisposableBean
* @see org.springframework.context.ConfigurableApplicationContext#close()
*/
String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;
......
......@@ -412,7 +412,7 @@ public @interface Configuration {
* component scanning or supplied directly to a {@link AnnotationConfigApplicationContext}.
* If the Configuration class is registered as a traditional XML bean definition,
* the name/id of the bean element will take precedence.
* @return the specified bean name, if any
* @return the suggested component name, if any (or empty String otherwise)
* @see org.springframework.beans.factory.support.DefaultBeanNameGenerator
*/
String value() default "";
......
......@@ -48,18 +48,18 @@ import java.lang.annotation.Target;
* }
*
* &#064;Component
* public class JdbcFooRepository {
* public class JdbcFooRepository extends FooRepository {
*
* public JdbcFooService(DataSource dataSource) {
* public JdbcFooRepository(DataSource dataSource) {
* // ...
* }
* }
*
* &#064;Primary
* &#064;Component
* public class HibernateFooRepository {
* public class HibernateFooRepository extends FooRepository {
*
* public HibernateFooService(SessionFactory sessionFactory) {
* public HibernateFooRepository(SessionFactory sessionFactory) {
* // ...
* }
* }
......
......@@ -31,7 +31,6 @@ import org.springframework.aop.framework.autoproxy.AutoProxyUtils;
import org.springframework.aop.scope.ScopedObject;
import org.springframework.aop.scope.ScopedProxyUtils;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.context.ApplicationContext;
......@@ -65,7 +64,7 @@ public class EventListenerMethodProcessor implements SmartInitializingSingleton,
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
public void setApplicationContext(ApplicationContext applicationContext) {
Assert.isTrue(applicationContext instanceof ConfigurableApplicationContext,
"ApplicationContext does not implement ConfigurableApplicationContext");
this.applicationContext = (ConfigurableApplicationContext) applicationContext;
......@@ -119,9 +118,9 @@ public class EventListenerMethodProcessor implements SmartInitializingSingleton,
*/
protected List<EventListenerFactory> getEventListenerFactories() {
Map<String, EventListenerFactory> beans = this.applicationContext.getBeansOfType(EventListenerFactory.class);
List<EventListenerFactory> allFactories = new ArrayList<EventListenerFactory>(beans.values());
AnnotationAwareOrderComparator.sort(allFactories);
return allFactories;
List<EventListenerFactory> factories = new ArrayList<EventListenerFactory>(beans.values());
AnnotationAwareOrderComparator.sort(factories);
return factories;
}
protected void processBean(final List<EventListenerFactory> factories, final String beanName, final Class<?> targetType) {
......
......@@ -381,7 +381,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
else {
applicationEvent = new PayloadApplicationEvent<Object>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
eventType = ((PayloadApplicationEvent) applicationEvent).getResolvableType();
}
}
......@@ -995,11 +995,13 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
}
// Stop all Lifecycle beans, to avoid delays during individual destruction.
try {
getLifecycleProcessor().onClose();
}
catch (Throwable ex) {
logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
if (this.lifecycleProcessor != null) {
try {
this.lifecycleProcessor.onClose();
}
catch (Throwable ex) {
logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
}
}
// Destroy all cached singletons in the context's BeanFactory.
......
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
......@@ -94,9 +94,14 @@ class ApplicationListenerDetector implements DestructionAwareBeanPostProcessor,
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) {
if (this.applicationContext != null && bean instanceof ApplicationListener) {
ApplicationEventMulticaster multicaster = this.applicationContext.getApplicationEventMulticaster();
multicaster.removeApplicationListener((ApplicationListener<?>) bean);
multicaster.removeApplicationListenerBean(beanName);
try {
ApplicationEventMulticaster multicaster = this.applicationContext.getApplicationEventMulticaster();
multicaster.removeApplicationListener((ApplicationListener<?>) bean);
multicaster.removeApplicationListenerBean(beanName);
}
catch (IllegalStateException ex) {
// ApplicationEventMulticaster not initialized yet - no need to remove a listener
}
}
}
......
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
......@@ -58,14 +58,6 @@ import org.springframework.core.Ordered;
* }
* }</pre>
*
* <p>The {@link #mode} attribute controls how advice is applied; if the mode is
* {@link AdviceMode#PROXY} (the default), then the other attributes control the behavior
* of the proxying.
*
* <p>Note that if the {@linkplain #mode} is set to {@link AdviceMode#ASPECTJ}, then the
* value of the {@link #proxyTargetClass} attribute will be ignored. Note also that in
* this case the {@code spring-aspects} module JAR must be present on the classpath.
*
* <p>By default, Spring will be searching for an associated thread pool definition:
* either a unique {@link org.springframework.core.task.TaskExecutor} bean in the context,
* or an {@link java.util.concurrent.Executor} bean named "taskExecutor" otherwise. If
......@@ -140,6 +132,17 @@ import org.springframework.core.Ordered;
* demonstrates how the JavaConfig-based approach allows for maximum configurability
* through direct access to actual componentry.
*
* <p>The {@link #mode} attribute controls how advice is applied: If the mode is
* {@link AdviceMode#PROXY} (the default), then the other attributes control the behavior
* of the proxying. Please note that proxy mode allows for interception of calls through
* the proxy only; local calls within the same class cannot get intercepted that way.
*
* <p>Note that if the {@linkplain #mode} is set to {@link AdviceMode#ASPECTJ}, then the
* value of the {@link #proxyTargetClass} attribute will be ignored. Note also that in
* this case the {@code spring-aspects} module JAR must be present on the classpath, with
* compile-time weaving or load-time weaving applying the aspect to the affected classes.
* There is no proxy involved in such a scenario; local calls will be intercepted as well.
*
* @author Chris Beams
* @author Juergen Hoeller
* @author Stephane Nicoll
......@@ -182,8 +185,13 @@ public @interface EnableAsync {
/**
* Indicate how async advice should be applied.
* <p>The default is {@link AdviceMode#PROXY}.
* @see AdviceMode
* <p><b>The default is {@link AdviceMode#PROXY}.</b>
* Please note that proxy mode allows for interception of calls through the proxy
* only. Local calls within the same class cannot get intercepted that way; an
* {@link Async} annotation on such a method within a local call will be ignored
* since Spring's interceptor does not even kick in for such a runtime scenario.
* For a more advanced mode of interception, consider switching this to
* {@link AdviceMode#ASPECTJ}.
*/
AdviceMode mode() default AdviceMode.PROXY;
......
......@@ -17,10 +17,12 @@
package org.springframework.scheduling.annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
......@@ -53,6 +55,7 @@ import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.MethodIntrospector;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.config.CronTask;
......@@ -207,9 +210,11 @@ public class ScheduledAnnotationBeanPostProcessor
}
if (this.beanFactory instanceof ListableBeanFactory) {
Map<String, SchedulingConfigurer> configurers =
Map<String, SchedulingConfigurer> beans =
((ListableBeanFactory) this.beanFactory).getBeansOfType(SchedulingConfigurer.class);