Prior to this commit, @EnableMBeanExport was declared in the
jmx.export.annotation package. This makes logical sense, but
nevertheless creates a package cycle, because @EnableMBeanExport depends
on MBeanExportConfiguration which in turn depends on context.annotation
types like @Configuration, @Bean, and @Role.
context.annotation.config.MBeanExportBeanDefinitionParser, on the other
hand already has dependencies on types in jmx.support. Together, this
means that a package cycle was introduced.
The solution to this is simple: move @EnableMBeanExport and friends from
jmx.export.annotation => context.annotation. This has been the strategy
for other @Enable annotations and for the same reasons. It also makes a
kind of logical sense: just like you find <context:mbean-export> and
<context:load-time-weaver> under the context: XML namespace, so too do
you find their @Enable* counterparts under the context.annotation
namespace.
Issue: SPR-8943
Add support for @EnableMBeanExport annotation allowing @Configuration
classes to easily export all MBeans and @ManagedResources from the
Spring application context. The annotation is functionally equivalent
to the XML <context:mbean-export/> element.
Issue: SPR-8943
Reverted change for @Bean methods that declare FactoryBean as their return type: The effects of trying to create the FactoryBean to find out about its implementation type are too far-reaching. It's better to recommend declaring a specific return type in the method signature if you want the container to specifically react to your implementation type.
Issue: SPR-9857
Includes a change for factory methods that declare their return type as FactoryBean: When asked for a specific type match (e.g. LoadTimeWeaverAware), we do check early singleton instances as well (reusing the instances that we create for getObjectType checks). This is necessary in order to make @Bean method introspection as capable as XML bean definition introspection, even in case of the @Bean method using a generic FactoryBean declaration for its return type (instead of the FactoryBean impl class).
Issue: SPR-9857
Includes a change for factory methods that declare their return type as FactoryBean: When asked for a specific type match (e.g. LoadTimeWeaverAware), we do check early singleton instances as well (reusing the instances that we create for getObjectType checks). This is necessary in order to make @Bean method introspection as capable as XML bean definition introspection, even in case of the @Bean method using a generic FactoryBean declaration for its return type (instead of the FactoryBean impl class).
Issue: SPR-9857
Refactor ConfigurationClassEnhancer to allow cglib caching of
generated classes. Prior to this commit each enhanced @Configuration
class would consume permgen space when created.
The CallbackFilter and Callback Types are now defined as static final
members so that they can be shared by all enhancers. Only the
callbackInstances remain specific to a @Configuration class and
these are not used by cglib as part of the cache key.
Issue: SPR-9851
Aside from minor polishing, this change sets the "systemProperties" and "systemEnvironment" beans at each factory level as well.
Issue: SPR-9756
Issue: SPR-9764
These features require Java 6 or higher due to their dependency on the ResourceBundle.Control class. To some degree, ResourceBundleMessageSource catches up with ReloadableResourceBundleMessageSource now. However, as noted in the javadoc, there are still severe limitations in the standard ResourceBundle class that justify an ongoing investment in our own ReloadableResourceBundleMessageSource (based on the Spring resource abstraction, with manual parsing of properties files).
Issue: SPR-7392
LiveBeansView includes MBean exposure as well as Servlet exposure, with JSON as the initial output format. In order to identify an MBean per application, a new "getApplicationName()" method got introduced on the ApplicationContext interface, returning the Servlet container context path in case of a web application and defaulting to the empty String. MBean exposure can be driven by the "spring.liveBeansView.mbeanDomain" property, e.g. specifying "liveBeansView" as its value, leading to "liveBeansView:application=" or "liveBeansView:application=/myapp" style names for the per-application MBean.
Issue: SPR-9662
Prior to this change, @ComponentScan required the declaration of
exactly one of the #value, #basePackage or #basePackageClasses
attributes in order to determine which package(s) to scan.
This commit introduces support for base package inference, relaxing the
above requirement and falling back to scanning the package in which the
@ComponentScan-annotated class is declared.
Issue: SPR-9586
Class#getDeclaredMembers returns arbitrary results under JDK7. This
results in non-deterministic execution of JUnit test methods, often
revealing unintended dependencies between methods that rely on a
specific order to succeed.
JUnit 4.11 contains support for predictable test ordering [1], but at
the time of this commit, JUnit 4.11 has not yet been released.
Therefore we are testing against a snapshot version [2], which has been
uploaded to repo.springsource.org [3] for easy access. Note that this
artifact may be removed when JUnit 4.11 goes GA.
- Care has been taken to ensure that spring-test's compile-time
dependency on JUnit remains at 4.10. This means that the spring-test
pom.xml will continue to have an optional <dependency> on JUnit
4.10, instead of the 4.11 snapshot.
- For reasons not fully understood, the upgrade to the 4.11 snapshot
of junit-dep caused NoSuchMethodErrors around certain Hamcrest
types, particularly CoreMatchers and Matchers. import statements
have been updated accordingly throughout affected test cases.
- Runtime errors also occurred around uses of JUnit @Rule and
ExpectedException. These have been reverted to use simpler
mechanisms like @Test(expected) in the meantime.
- Some test methods with order-based dependencies on one another have
been renamed in order to fall in line with JUnit 4.11's new method
ordering (as opposed to actually fixing the inter-test
dependencies). In other areas, the fix was as simple as adding a
tearDown method and cleaning up state.
- For no apparent reason, the timeout in AspectJAutoProxyCreatorTests'
testAspectsAndAdvisorNotAppliedToPrototypeIsFastEnough method begins
to be exceeded. Prior to this commit the timeout value was 3000 ms;
on the CI server under Linux/JDK6 and JDK7, the test begins taking
anywhere from 3500-5500 ms with this commit. It is presumed that
this is an incidental artifact of the upgrade to JUnit 4.11. In any
case, there are no changes to src/main in this commit, so this
should not actually represent a performance risk for Spring
Framework users. The timeout has been increased to 6000 ms to
accommodate this situation.
[1]: https://github.com/KentBeck/junit/pull/293
[2]: https://github.com/downloads/KentBeck/junit/junit-dep-4.11-SNAPSHOT-20120805-1225.jar
[3]: https://repo.springsource.org/simple/ext-release-local/junit/junit-dep/4.11.20120805.1225
Issue: SPR-9783
- Allow reset of GlobalAdvisorAdapterRegistry
Provide a reset() method allowing the GlobalAdvisorAdapterRegistry
instance to be replaced with a fresh instance. This method has
primarily been added to allow unit tests to leave the registry
in a known state.
- Protect against the fact that calls to configuration class methods
my occur in a random order.
Issue: SPR-9779
This commit avoids eager creation of Environment instances, favoring
delegation of already existing Environment objects where possible. For
example, FrameworkServlet creates an ApplicationContext; both require
a StandardServletEnvironment instance, and prior to this change, two
instances were created where one would suffice - indeed these two
instances may reasonably be expected to be the same. Now, the
FrameworkServlet defers creation of its Environment, allowing users to
supply a custom instance via its #setEnvironment method (e.g. within a
WebApplicationInitializer); the FrameworkServlet then takes care to
delegate that instance to the ApplicationContext created
in #createWebApplicationContext.
This behavior produces more consistent behavior with regard to
delegation of the environment, saves unnecessary cycles by avoiding
needless instantiation and calls to methods like
StandardServletEnvironment#initPropertySources and leads to better
logging output, as the user sees only one Environment created and
initialized when working with the FrameworkServlet/DispatcherServlet.
This commit also mirrors these changes across the corresponding
Portlet* classes.
Issue: SPR-9763
Prior to this change, AbstractApplicationContext#prepareBeanFactory
registered a bean named 'environment' once and only once within a given
ApplicationContext hierarchy. This worked fine with the expectation
that the Environment object is always delegated downward to children of
that hierarchy. However, with SPR-9444 and the introduction of
ConfigurableEnvironment#merge, this expectation was violated; each
member of an application context hierarchy now maintains its own
distinct Environment instance, which means that by extension that each
application context's underlying BeanFactory should have its own
'environment' bean pointing to that context's environment instance.
This problem could manifest in getting the wrong environment instance
when calling #getBean(Environment) or when @Autowiring an Environment
instance, for example into a @Configuration class. As reported in
SPR-9756, this could result in false negative property lookups or
incorrect results when checking whether a profile is active.
This commit ensures that every bean factory in an application
hierarchy has an 'environment' bean referring to the object returned
from the enclosing ApplicationContext#getEnvironment method.
Issue: SPR-9756, SPR-9444
CGLIB 3 has been released in order to depend on ASM 4, which Spring now
depends on internally (see previous commit).
This commit eliminates spring-beans' optional dependency on cglib-nodep
v2.2 and instead repackages net.sf.cglib => org.springframework.cglib
much in the same way we have historically done with ASM.
This change is beneficial to users in several ways:
- Eliminates the need to manually add CGLIB to the application
classpath; especially important for the growing number of
@Configuration class users. Java-based configuration functionality,
along with proxy-target-class and method injection features now
work 'out of the box' in Spring 3.2.
- Eliminates the possibility of conflicts with other libraries that
may dependend on differing versions of CGLIB, e.g. Hibernate
3.3.1.ga and its dependency on CGLIB 2.1.3 would easily cause a
conflict if the application were depending on CGLIB 3 for
Spring-related purposes.
- Picks up CGLIB 3's changes to support ASM 4, meaning that CGLIB is
that much less likely to work well in a Java 7 environment due to
ASM 4's support for transforming classes with invokedynamic
bytecode instructions.
On CGLIB and ASM:
CGLIB's own dependency on ASM is also transformed along the way to
depend on Spring's repackaged org.springframework.asm, primarily to
eliminate unnecessary duplication of ASM classfiles in spring-core and
in the process save around 100K in the final spring-core JAR file size.
It is coincidental that spring-core and CGLIB currently depend on the
exact same version of ASM (4.0), but it is also unlikely to change any
time soon. If this change does occur and versions of ASM drift, then
the size optimization mentioned above will have to be abandoned. This
would have no compatibility impact, however, so this is a reasonable
solution now and for the forseeable future.
On a mysterious NoClassDefFoundError:
During the upgrade to CGLIB 3.0, Spring test cases began failing due to
NoClassDefFoundErrors being thrown from CGLIB's DebuggingClassWriter
regarding its use of asm-util's TraceClassVisitor type. previous
versions of cglib-nodep, particularly 2.2, did not cause this behavior,
even though cglib-nodep has never actually repackaged and bundled
asm-util classes. The reason for these NoClassDefFoundErrors occurring
now is still not fully understood, but appears to be due to subtle JVM
bytecode preverification rules. The hypothesis is that due to minor
changes in DebuggingClassWriter such as additional casts, access to
instance variables declared in the superclass, and indeed a change in
the superclass hierarchy, preverification may be kicking in on the
toByteArray method body, at which point the reference to the missing
TraceClassVisitor type is noticed and the NCDFE is thrown. For this
reason, a dummy implementation of TraceClassVisitor has been added to
spring-core in the org.springframework.asm.util package. This class
simply ensures that Spring's own tests never result in the NCDFE
described above, and more importantly that Spring's users never
encounter the same.
Other changes include:
- rename package-private Cglib2AopProxy => CglibAopProxy
- eliminate all 'cglibAvailable' checks, warnings and errors
- eliminate all 'CGLIB2' language in favor of 'CGLIB'
- eliminate all mention in reference and java docs of needing to add
cglib(-nodep) to one's application classpath
Issue: SPR-9669
For legacy reasons, a MockEnvironment implementation already exists in multiple places within Spring's test suite; however, it is not available to the general public.
This commit promotes MockEnvironment to a first-class citizen in the spring-test module, alongside the existing MockPropertySource.
In addition, the following house cleaning has been performed.
- deleted MockPropertySource from the spring-expression module
- deleted MockEnvironment from the "spring" integration testing module
- updated test copies of MockPropertySource and MockEnvironment
- documented MockEnvironment and MockPropertySource in the testing
chapter of the reference manual
Issue: SPR-9492
@Async executor qualification has been backported to 3.1.2. This commit
updates all @since tags appropriately, as well as carrying over the
changes backported to the spring-task-3.1 schema.
Issue: SPR-6847, SPR-9443
The following syntax is now supported
<beans profile="p1,!p2">
@Profile("p1", "!p2")
indicating that the <beans> element or annotated component should
be processed only if profile 'p1' is active or profile 'p2' is not
active.
Issue: SPR-8728
Prior to this change, AbstractApplicationContext#setParent replaced the
child context's Environment with the parent's Environment if available.
This has the negative effect of potentially changing the type of the
child context's Environment, and in any case causes property sources
added directly against the child environment to be ignored. This
situation could easily occur if a WebApplicationContext child had a
non-web ApplicationContext set as its parent. In this case the parent
Environment type would (likely) be StandardEnvironment, while the child
Environment type would (likely) be StandardServletEnvironment. By
directly inheriting the parent environment, critical property sources
such as ServletContextPropertySource are lost entirely.
This commit introduces the concept of merging an environment through
the new ConfigurableEnvironment#merge method. Instead of replacing the
child's environment with the parent's,
AbstractApplicationContext#setParent now merges property sources as
well as active and default profile names from the parent into the
child. In this way, distinct environment objects are maintained with
specific types and property sources preserved. See #merge Javadoc for
additional details.
Issue: SPR-9444, SPR-9439
java.util.concurrent's ScheduledExecutorService and its #schedule*
methods allow for an 'initialDelay' parameter in milliseconds.
Similarly, Spring's TaskExecutor abstraction allows for a concrete
'startTime' expressed as a Date. However, Spring's <task:scheduled> XML
element and @Scheduled annotation have, to date, not allowed for an
initial delay parameter that can be propagated down to the underlying
TaskScheduler/ScheduledExecutorService.
This commit introduces initial-delay and #initialDelay attributes to
task:scheduled and @Scheduled respectively, both indicating the number
of milliseconds to wait before the first invocation of the method in
question. Specifying a delay in this fashion is only valid in
conjunction with fixed-rate and fixed-delay tasks (i.e. not with cron
or trigger tasks).
The principal changes required to support these new attributes lie in
ScheduledTaskRegistrar, which previously supported registration of
tasks in the form of a Runnable and a Long parameter indicating (in the
case of fixed-rate and fixed-delay tasks), the interval with which the
task should be executed. In order to accommodate a third (and optional)
'initialDelay' parameter, the IntervalTask class has been added as a
holder for the Runnable to be executed, the interval in which to run
it, and the optional initial delay. For symmetry, a TriggerTask and
CronTask have also been added, the latter subclassing the former. And a
'Task' class has been added as a common ancestor for all the above.
One oddity of the implementation is in the naming of the new
setters in ScheduledTaskRegistrar. Prior to this commit, the setters
were named #setFixedDelayTasks, #setFixedRateTasks, etc, each accepting
a Map<Runnable, long>. In adding new setters for each task type, each
accepting a List<IntervalTask>, List<CronTask> etc, naturally the
approach would be to use method overloading and to introduce methods
of the same name but with differing parameter types. Unfortunately
however, Spring does not support injection against overloaded methods
(due to fundamental limitations of the underlying JDK Introspector).
This is not a problem when working with the ScheduledTaskRegistrar
directly, e.g. from within a @Configuration class that implements
SchedulingConfigurer, but is a problem from the point of view of the
ScheduledTasksBeanDefinitionParser which parses the <task:scheduled>
element - here the ScheduledTaskRegistrar is treated as a Spring bean
and is thus subject to these limitations. The solution to this problem
was simply to avoid overloading altogether, thus the naming of the new
methods ending in "List", e.g. #setFixedDelayTasksList, etc. These
methods exist primarily for use by the BeanDefinitionParser and are
not really intended for use by application developers. The Javadoc for
each of the new methods makes note of this.
Issue: SPR-7022
In anticipation of substantive changes required to implement "initial
delay" support in the <task:scheduled> element and @Scheduled
annotation, the following updates have been made to the components and
infrastructure supporting scheduled task execution:
- Fix code style violations
- Fix compiler warnings
- Add Javadoc where missing, update to use {@code} tags, etc.
- Organize imports to follow conventions
Prior to this change, Spring's @Async annotation support was tied to a
single AsyncTaskExecutor bean, meaning that all methods marked with
@Async were forced to use the same executor. This is an undesirable
limitation, given that certain methods may have different priorities,
etc. This leads to the need to (optionally) qualify which executor
should handle each method.
This is similar to the way that Spring's @Transactional annotation was
originally tied to a single PlatformTransactionManager, but in Spring
3.0 was enhanced to allow for a qualifier via the #value attribute, e.g.
@Transactional("ptm1")
public void m() { ... }
where "ptm1" is either the name of a PlatformTransactionManager bean or
a qualifier value associated with a PlatformTransactionManager bean,
e.g. via the <qualifier> element in XML or the @Qualifier annotation.
This commit introduces the same approach to @Async and its relationship
to underlying executor beans. As always, the following syntax remains
supported
@Async
public void m() { ... }
indicating that calls to #m will be delegated to the "default" executor,
i.e. the executor provided to
<task:annotation-driven executor="..."/>
or the executor specified when authoring a @Configuration class that
implements AsyncConfigurer and its #getAsyncExecutor method.
However, it now also possible to qualify which executor should be used
on a method-by-method basis, e.g.
@Async("e1")
public void m() { ... }
indicating that calls to #m will be delegated to the executor bean
named or otherwise qualified as "e1". Unlike the default executor
which is specified up front at configuration time as described above,
the "e1" executor bean is looked up within the container on the first
execution of #m and then cached in association with that method for the
lifetime of the container.
Class-level use of Async#value behaves as expected, indicating that all
methods within the annotated class should be executed with the named
executor. In the case of both method- and class-level annotations, any
method-level #value overrides any class level #value.
This commit introduces the following major changes:
- Add @Async#value attribute for executor qualification
- Introduce AsyncExecutionAspectSupport as a common base class for
both MethodInterceptor- and AspectJ-based async aspects. This base
class provides common structure for specifying the default executor
(#setExecutor) as well as logic for determining (and caching) which
executor should execute a given method (#determineAsyncExecutor) and
an abstract method to allow subclasses to provide specific strategies
for executor qualification (#getExecutorQualifier).
- Introduce AnnotationAsyncExecutionInterceptor as a specialization of
the existing AsyncExecutionInterceptor to allow for introspection of
the @Async annotation and its #value attribute for a given method.
Note that this new subclass was necessary for packaging reasons -
the original AsyncExecutionInterceptor lives in
org.springframework.aop and therefore does not have visibility to
the @Async annotation in org.springframework.scheduling.annotation.
This new subclass replaces usage of AsyncExecutionInterceptor
throughout the framework, though the latter remains usable and
undeprecated for compatibility with any existing third-party
extensions.
- Add documentation to spring-task-3.2.xsd and reference manual
explaining @Async executor qualification
- Add tests covering all new functionality
Note that the public API of all affected components remains backward-
compatible.
Issue: SPR-6847
In anticipation of substantive changes required to implement @Async
executor qualification, the following updates have been made to the
components and infrastructure supporting @Async functionality:
- Fix trailing whitespace and indentation errors
- Fix generics warnings
- Add Javadoc where missing, update to use {@code} tags, etc.
- Avoid NPE in AopUtils#canApply
- Organize imports to follow conventions
- Remove System.out.println statements from tests
- Correct various punctuation and grammar problems
Updated the "@Bean Lite Mode" section in order to properly document
scoping and lifecycle semantics.
Also fleshed out the discussion of the non-applicability of 'inter-bean
references' in lite mode.
Issue: SPR-9425