Compare commits

...

98 Commits

Author SHA1 Message Date
Spring Builds c9a55a34ce Release v5.3.11 2021-10-14 09:22:04 +00:00
Rossen Stoyanchev 0705454ce0 Fix typo in Javadoc
See gh-27484
2021-10-14 09:42:40 +01:00
Rossen Stoyanchev a178bbe86f DefaultResponseErrorHandler shows full error details
Closes gh-27552
2021-10-13 20:51:34 +01:00
Sam Brannen fcf4315e02 Indent with tabs instead of spaces 2021-10-13 20:04:40 +02:00
Sam Brannen 89c7797ffb Commit in DatabasePopulatorUtils if Connection has auto-commit=false
Prior to this commit, DatabasePopulatorUtils.execute(...) did not
perform a commit for the current Connection. This works for most use
cases; however, when DatabasePopulatorUtils is used to execute
initialization scripts without a managed transaction -- for example,
via a DataSourceInitializer configured as a bean in the
ApplicationContext or via Spring Boot configuration in
application.properties -- if the underlying database is configured with
auto-commit=false, the results of executing the SQL scripts are not
committed to the database which can lead to data being silently lost.

This commit addresses this issue by committing the Connection for the
supplied DataSource if the connection is not configured for auto-commit
and is not transactional. Existing use cases running with a managed
transaction should therefore not be affected by this change.

Closes gh-27008
2021-10-13 19:10:09 +02:00
Rossen Stoyanchev 4dac8339ff Filter non-existing static resource locations
Same as a2c52a97ba, on the WebFlux side.

See gh-27538
2021-10-13 14:40:34 +01:00
Rossen Stoyanchev 0436dd04bf Correctly handle coroutine with ResponseEntity
ResponseEntityResultHandler nests correctly, only once for the ResponseEntity,
when there is a Mono adapted from a Kotlin Continuation.

Closes gh-27292
2021-10-13 14:40:34 +01:00
Hantsy Bai 1e3996ea78 Upgrade SmallRye Mutiny to 1.1.1
Closes gh-27555
2021-10-13 15:27:02 +02:00
Koen Punt 50b92118a9 Include correct keyword in CookieAssertions failure messages
Closes gh-27550
2021-10-13 14:02:55 +02:00
Juergen Hoeller b1c7f7d127 Polishing 2021-10-13 12:48:47 +02:00
Juergen Hoeller 0f36569d75 Remove dead fallback code 2021-10-13 12:38:39 +02:00
Juergen Hoeller 2cbba0923b Upgrade to Netty 4.1.69, Jetty 9.4.44, Kotlin 1.5.31 2021-10-13 12:38:06 +02:00
Rossen Stoyanchev 800922266a Upgrade to Reactor 2021.0.12
Closes gh-27527
2021-10-12 16:23:18 +01:00
Juergen Hoeller eda3ca5fbc Remove unnecessary final declarations at method level 2021-10-12 15:17:44 +02:00
Juergen Hoeller e4934a90eb Use TriggerContext's Clock instead of new Date()
Closes gh-27546
2021-10-12 15:17:18 +02:00
Juergen Hoeller 715f300fa1 Avoid expensive isReadable() check during classpath scan
Closes gh-25741
See gh-21372
2021-10-12 15:15:51 +02:00
Juergen Hoeller b53275f2d2 Add efficient existence check to ClassPathResource.isReadable()
Includes reduced isReadable() check in PathResourceLookupFunction, aligned with PathResourceResolver.

Closes gh-27538
See gh-21372
2021-10-12 15:13:05 +02:00
Juergen Hoeller 1490d27d75 Decouple urlResourceWithCharset test from existence of tmp directory
See gh-25738
2021-10-12 15:10:19 +02:00
Rossen Stoyanchev a2c52a97ba Filter non-existing static resource locations
See gh-27538
2021-10-12 11:59:55 +01:00
Sam Brannen 5bd90538b3 Introduce test for gh-27499 and polish contribution 2021-10-12 12:22:24 +02:00
Nick 50ccb1bfcd Avoid duplicate JCacheOperationSource bean registration in <cache:annotation-driven />
In our application we use XML context and <cache:annotation-driven />
declaration. Also we disable bean definition duplication by setting
GenericApplicationContext.setAllowBeanDefinitionOverriding(false) in an
ApplicationContextInitializer. This combination leads to a
BeanDefinitionOverrideException because the
DefaultJCacheOperationSource bean is registered twice.

 - once for: parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
 - once for: parserContext.registerBeanComponent(new BeanComponentDefinition(sourceDef, sourceName));

This commit refactors JCacheCachingConfigurer.registerCacheAspect(...)
so that the JCacheOperationSource bean is registered only once.

Closes gh-27499
2021-10-12 12:05:30 +02:00
Stephane Nicoll 83eac9af18 Upgrade CI to github-release resource 1.5.5
Closes gh-27459
2021-10-11 16:18:35 +02:00
Sam Brannen eb07dea795 Polish contribution
See gh-27544
2021-10-11 15:31:40 +02:00
Сергей Цыпанов 114fa47171 Use Arrays.hashCode() in ByteArrayResource.hashCode() 2021-10-11 15:28:50 +02:00
Sam Brannen 63fac1b7c8 Allow default CacheAwareContextLoaderDelegate configuration via system property
Prior to this commit, the default CacheAwareContextLoaderDelegate could
be configured by extending AbstractTestContextBootstrapper and
overriding getCacheAwareContextLoaderDelegate(); however, this required
that the user configure the custom TestContextBootstrapper via
@BootstrapWith.

This commit introduces a new
"spring.test.context.default.CacheAwareContextLoaderDelegate" property
that can be configured via a JVM system property or via the
SpringProperties mechanism. BootstrapUtils uses this new property to
load the default CacheAwareContextLoaderDelegate. If the property is
not defined, BootstrapUtils will fall back to creating a
DefaultCacheAwareContextLoaderDelegate as it did previously.

This allows third parties to configure the default
CacheAwareContextLoaderDelegate transparently for the user -- for
example, to intercept context loading in order to load the context in a
different manner -- for example, to make use of ahead of time (AOT)
techniques for implementing a different type of ApplicationContext at
build time.

Closes gh-27540
2021-10-11 14:59:09 +02:00
Rossen Stoyanchev e8f6cd10a5 Apply value formatting to resolved exceptions 2021-10-11 11:14:02 +01:00
Sam Brannen 47b8e8d528 Upgrade to Mockito 4 2021-10-10 23:26:07 +02:00
Sam Brannen bdfd983bb4 Fix example code formatting in @EnableWebMvc 2021-10-08 21:30:39 +02:00
Juergen Hoeller 87aaf5049b Polishing 2021-10-08 20:41:51 +02:00
Juergen Hoeller 4b01370f54 UriTemplateRequestEntity overrides equals/hashCode
Closes gh-27531
2021-10-08 20:41:18 +02:00
Rossen Stoyanchev b6111d04a5 Ensure WebClientResponseException for malformed response
Closes gh-27262
2021-10-07 16:50:53 +01:00
Ashley Scopes 9bd989f1bb WebClient tests for socket and response format issues
Added test case for malformed response chunk, which is
now failing as expected.

See gh-27262
2021-10-07 16:50:53 +01:00
Stephane Nicoll d5597a75a6 Start building against Reactor 2020.0.12 snapshots
See gh-27527
2021-10-07 08:51:32 +02:00
Rossen Stoyanchev 90fdcf88d8 Generalize formatValue
Provide an overload for additional control and compact output.
2021-10-06 21:27:56 +01:00
Sam Brannen 5d3b16cd3a Indent with tabs instead of spaces 2021-10-06 15:42:52 +02:00
Sam Brannen 41ae9632d1 Upgrade to Checkstyle 9.0 and spring-javaformat 0.0.29
This commit upgrades the Gradle build to use Checkstyle 9.0 and
spring-javaformat 0.0.29 (which internally uses Checkstyle 8.45.1).

Closes gh-27520
2021-10-06 12:11:19 +02:00
Sam Brannen 47b0da6b25 Polishing 2021-10-06 11:48:30 +02:00
Arjen Poutsma c99210c01f Propagate Reactor Context when using FluxSink
This commit makes sure that the Reactor context from a given mono or
flux is propagated to the Flux returned by a FluxSink. This change
affects both DataBufferUtils::write and internal classes used by the
DefaultPartHttpMessageReader.

Closes gh-27517
2021-10-05 16:30:49 +02:00
Rossen Stoyanchev 7b9848a352 Replace deprecated Reactor Context related methods 2021-10-05 14:33:52 +01:00
Sam Brannen 0e83466023 Reference Hamcrest Javadoc via javadoc.io
Due to an SSL/TLS issue with hamcrest.org, the Dokka task fails with the
following.

> Failed to download package-list from https://hamcrest.org/JavaHamcrest/javadoc/2.1/package-list,
> this might suggest that remote resource is not available, module is
> empty or dokka output got corrupted

See: https://github.com/hamcrest/JavaHamcrest/issues/280

As a workaround, this commit switches to javadoc.io to reference the
Hamcrest Javadoc APIs.
2021-10-05 15:23:44 +02:00
Sam Brannen 48a507a993 Clean up warnings 2021-10-05 14:35:32 +02:00
Sam Brannen be3bc4c164 Comment out unused fudgeFactor 2021-10-05 14:24:18 +02:00
Rossen Stoyanchev e68219c1ac ResponseStatusExceptionHandler logs exception message only
No need to log the full exception for a resolved exception, and as the
comment suggests that it mirrors Spring MVC equivalent, which also
logs the message only.
2021-10-05 12:12:17 +01:00
Stephane Nicoll 151852b164 Upgrade to GitHub Changelog Generator 0.0.7 in CI
Closes gh-27512
2021-10-03 07:09:24 +02:00
Juergen Hoeller 49427b0c3c Upgrade to Apache Johnzon 1.2.14, Vavr 0.10.4, WebJars Locator 0.48, HtmlUnit 2.53 2021-10-02 12:08:09 +02:00
Juergen Hoeller bf373c5065 Skip all flaky StopWatch time assertions 2021-10-02 12:04:13 +02:00
Sam Brannen 678fd8344e Polishing 2021-10-01 14:37:07 +02:00
Juergen Hoeller f632165dec Invoke bean-derived (Auto)Closeable.close() method directly
Closes gh-27504
2021-10-01 13:26:25 +02:00
Sam Brannen fd11789db9 Polish JSR-107 caching ref docs 2021-10-01 12:51:52 +02:00
Jens Schauder d6ec6f0fe9 Remove remark about missing caching API. 2021-10-01 11:56:36 +02:00
Sam Brannen 7311ae19be Fix build by disabling linking to JUnit 5.8.1 Javadoc
The `package-list` file no longer exists at
https://junit.org/junit5/docs/5.8.1/api/, due to the following commit.

https://github.com/junit-team/junit5/commit/67ad4e545518b0ce2b0e7c96df31a669866d5003
2021-10-01 11:09:59 +02:00
Sam Brannen f0aa4f4857 Escape closing curly braces in regular expressions for Android support
PR gh-24470 introduced a regression for Android users by no longer
escaping closing curly braces in regular expressions.

This commit therefore partially reverts the changes made in 273812f9c5
for closing curly braces (`}`).

Closes gh27467
2021-10-01 10:35:28 +02:00
Juergen Hoeller f64f07049d Upgrade to SLF4J 1.7.32 2021-09-30 18:12:10 +02:00
Juergen Hoeller 24bcb52b2f Polishing 2021-09-30 18:09:07 +02:00
Juergen Hoeller 4f44ae3f28 Polishing 2021-09-30 17:34:22 +02:00
Juergen Hoeller a295a28e4b Defensively handle fast class generation failure for individual methods
Includes rethrowing of last actual defineClass exception encountered.

Closes gh-27490
2021-09-30 17:33:58 +02:00
Arjen Poutsma bfa01b35df Polishing
See gh-27488
2021-09-30 17:09:03 +02:00
Arjen Poutsma 388c8e4aa5 Make sure that MediaType comparators are transitive
Previous to this commit, the specificity and quality comparators
(used by MediaType::sortByQualityValue and MediaType::sortBySpecificity)
could result in IllegalArgumentExceptions when used for sorting.
The underlying reason was that the comparators were not transitive, and
both media types with the same type, and types with the same amount of
parameters, would be considered identical by the comparator (result 0).

This commit ensures that the comparators are transitive.

Closes gh-27488
2021-09-30 16:15:38 +02:00
Sam Brannen 96e4d3a530 Fail Gradle build for Javadoc warnings
In order to catch Javadoc errors in the build, we now enable the
`Xwerror` flag for the `javadoc` tool. In addition, we now use
`Xdoclint:syntax` instead of `Xdoclint:none` in order to validate
syntax within our Javadoc.

This commit fixes all resulting Javadoc errors and warnings.

This commit also upgrades to Undertow 2.2.12.Final and fixes the
artifact names for exclusions for the Servlet and annotations APIs.

The incorrect exclusion of the Servlet API resulted in the Servlet API
being on the classpath twice for the javadoc task, which resulted in the
following warnings in previous builds.

javadoc: warning - Multiple sources of package comments found for package "javax.servlet"
javadoc: warning - Multiple sources of package comments found for package "javax.servlet.http"
javadoc: warning - Multiple sources of package comments found for package "javax.servlet.descriptor"
javadoc: warning - Multiple sources of package comments found for package "javax.servlet.annotation"

Closes gh-27480
2021-09-29 14:02:37 +02:00
Juergen Hoeller 040445612f Polishing 2021-09-28 18:15:56 +02:00
Juergen Hoeller 86b010a6b2 Defensive reference to JNDI API for JDK 9+ (optional java.naming module)
Closes gh-27483
2021-09-28 18:15:22 +02:00
Juergen Hoeller 2feedb98cc Remove lineSeparator LF requirement (accept LF/CR/CRLF by default)
See gh-27481
2021-09-28 18:15:00 +02:00
Arjen Poutsma 3be2b32e21 Remove only leading space for SSE data
Prior to this commit, all white space was trimmed from Server Sent Event
data. After this commit, only a leading space is removed (if present).

Closes gh-27473
2021-09-28 14:56:39 +02:00
Sam Brannen 85bdea6f47 Fix code formatting in Javadoc
See gh-27480
2021-09-28 13:41:25 +02:00
Sam Brannen bfdc99ab79 Fix Javadoc errors
See gh-27480
2021-09-28 11:44:12 +02:00
Sam Brannen 2567b20949 Upgrade to spring-javaformat 0.0.28 and downgrade to Checkstyle 8.41
In order to be able to use text blocks and other new Java language
features, we are upgrading to a recent version of Checkstyle.

The latest version of spring-javaformat-checkstyle (0.0.28) is built
against Checkstyle 8.32 which does not include support for language
features such as text blocks. Support for text blocks was added in
Checkstyle 8.36.

In addition, there is a binary compatibility issue between
spring-javaformat-checkstyle 0.0.28 and Checkstyle 8.42. Thus we cannot
use Checkstyle 8.42 or higher.

In this commit, we therefore upgrade to spring-javaformat-checkstyle
0.0.28 and downgrade to Checkstyle 8.41.

This change is being applied to `5.3.x` as well as `main` in order to
benefit from the enhanced checking provided in more recent versions of
Checkstyle.

Closes gh-27481
2021-09-28 10:29:31 +02:00
Juergen Hoeller 119c78b1c9 Skip flaky StopWatch time assertions 2021-09-27 17:11:12 +02:00
Juergen Hoeller d8e18f56e1 Upgrade to Protobuf 3.18, Rome 1.16, BlockHound 1.0.6, Caffeine 2.9.2, Groovy 3.0.9, Tomcat 9.0.53 2021-09-27 17:01:18 +02:00
Juergen Hoeller 211f0bbf88 Fix invalid characters in source files
Closes gh-27475
2021-09-27 16:57:54 +02:00
Juergen Hoeller b0c424b376 Deprecate RxJava 2 in favor of RxJava 3
Closes gh-27474
2021-09-27 16:56:28 +02:00
Juergen Hoeller 9ff0d717f2 Restore lenient fallback in case of several non-public constructors
See gh-27437
2021-09-27 16:52:11 +02:00
Rossen Stoyanchev 93f8706dd3 Update docs for ControllerAdvice
In 5.3 it became possible to handle exceptions from any handler through
ExceptionHandler's in a ControllerAdvice class, but this is not
mentioned in the docs

See gh-22619, gh-27338
2021-09-24 15:57:15 +01:00
Juergen Hoeller e29cfa3501 Polishing 2021-09-23 15:57:43 +02:00
Juergen Hoeller 208fafa4a3 Fix contract violations in ConcurrentReferenceHashMap's EntrySet/Iterator
Closes gh-27454
2021-09-23 15:56:49 +02:00
Juergen Hoeller 5cbc972a0d Log rejected listener container tasks at warn level
Closes gh-27451
2021-09-23 15:56:06 +02:00
Juergen Hoeller 58898de542 Provide accessors for externallyManagedConfigMembers and Init/DestroyMethods
Closes gh-27449
2021-09-23 15:54:40 +02:00
Juergen Hoeller f9d63e7bb1 BeanUtils.getResolvableConstructor falls back to single non-public constructor
Closes gh-27437
2021-09-23 15:53:54 +02:00
Sam Brannen 134c0e2916 Upgrade to JUnit 5.8.1
Closes gh-27450
2021-09-22 22:08:38 +02:00
Juergen Hoeller 1f8c233dfc Polishing 2021-09-21 17:43:03 +02:00
Juergen Hoeller 0dc5d2794f Avoid early ConversionService determination in StandardBeanExpressionResolver
Closes gh-27446
2021-09-21 17:42:50 +02:00
Juergen Hoeller 49d003857d Skip CGLIB class validation in case of optimize flag
Closes gh-27439
2021-09-21 17:42:19 +02:00
Juergen Hoeller eabe946a53 Skip readStream optimization for compatibility with misbehaving InputStreams
Closes gh-27429
2021-09-21 17:41:56 +02:00
Sam Brannen 09a1b87d37 About notes about AJDT and Kotlin not supported in Eclipse 4.21
See gh-27407
2021-09-21 14:23:02 +02:00
Sam Brannen 34abc8f577 The Kotlin plugin is no longer required for development in Eclipse
As documented, it's only required if you with to run Kotlin tests or
develop Kotlin extensions.

See gh-27407
2021-09-21 13:04:29 +02:00
Sam Brannen b0dceb484a Remove Eclipse Web Tools Platform (WTP) configuration
Since the team no longer needs the ability to treat Eclipse projects as
WTP modules, this commit removes the obsolete custom WTP configuration
for importing projects into Eclipse IDE.

See gh-27407
2021-09-21 12:37:51 +02:00
Sam Brannen 65c1eac115 Fix formatting in Eclipse/STS Project Import Guide
See gh-27407
2021-09-21 12:16:06 +02:00
Sam Brannen a37dde9a1c Revise Eclipse/STS Project Import Guide based on status quo
See gh-27407
2021-09-21 12:11:27 +02:00
Sam Brannen 28496059bc Make TestNG test methods public due to bug in TestNG TestEngine
This commit makes all test methods in our TestNG test classes public
due to the following bug in the TestNG engine for the JUnit Platform.

https://github.com/junit-team/testng-engine/issues/16

See gh-27407
2021-09-21 10:35:34 +02:00
Sam Brannen 40c51efee8 Introduce @Suite for TestNG tests
In order to allow developers to execute TestNG tests in Eclipse IDE
without installing the TestNG plugin for Eclipse, this commit introduces
a JUnit Platform @Suite class that can be executed within the IDE.

See gh-27407
2021-09-21 10:33:25 +02:00
Sam Brannen e439d6f64d Upgrade to AssertJ 3.21.0 2021-09-20 14:54:25 +02:00
Marc Philipp e29867b96e Exclude TestCase classes in spring-test build
When not excluded, TestNG will pick up nested TestCase classes and run
them.

This commit therefore filters out `*TestCase` test classes from the
build since these are not intended to be executed with the build.

See gh-27406
2021-09-20 14:02:06 +02:00
Sam Brannen 0b552a3534 Migrate to TestNG Engine for the JUnit Platform in spring-test
Prior to this commit, we had configured separate test tasks for JUnit
and TestNG. In addition, we configured a standard `test` task that
depended on the `junit` and `testNG` tasks, and we had an additional
`aggregateTestReports` task that aggregated the reports from the JUnit
and TestNG test tasks.

Thanks to the introduction of the "TestNG Engine for the JUnit
Platform", this commit simplifies our Gradle build in the spring-test
module by running JUnit 4, JUnit Jupiter, and TestNG tests on the JUnit
Platform in a single Gradle `test` task.

See gh-27406
2021-09-20 14:02:06 +02:00
Brian Clozel a50537fbaf Polish "Fix collectionToDelimitedString failure for null elements."
Fixes gh-27419
2021-09-17 15:15:51 +02:00
Koy 0d6cc12274 Fix collectionToDelimitedString failure for null elements.
Prior to this commit, calling `StringUtils#collectionToDelimitedString`
would fail with an NPE if the collection contains null elements.

This commit ensures that null elements are converted as `"null"` in the
resulting String without failure.

See gh-27419
2021-09-17 15:15:26 +02:00
Sam Brannen 008aa48d5c Fix formatting for SQL IN clause example in ref docs
See gh-27388
2021-09-16 14:10:54 +02:00
Brian Clozel 00eef79e5c Upgrade to JApicmp Gradle Plugin 0.3.0
Fixes gh-27414
2021-09-15 14:40:42 +02:00
Brian Clozel 7907478d36 Watch 5.3.x branch in the CI pipeline
Main branch has moved to the 6.0.x line, so this commit updates this CI
pipeline to the new 5.3.x maintenance branch.
2021-09-15 12:17:07 +02:00
Spring Builds c7cca2e879 Next development version (v5.3.11-SNAPSHOT) 2021-09-15 07:24:10 +00:00
460 changed files with 2560 additions and 1714 deletions
+35 -33
View File
@@ -1,17 +1,17 @@
plugins {
id 'io.spring.dependency-management' version '1.0.11.RELEASE' apply false
id 'io.spring.nohttp' version '0.0.10'
id 'org.jetbrains.kotlin.jvm' version '1.5.30' apply false
id "io.freefair.aspectj" version '6.2.0' apply false
id 'org.jetbrains.dokka' version '1.5.0' apply false
id 'org.jetbrains.kotlin.jvm' version '1.5.31' apply false
id "org.jetbrains.kotlin.plugin.serialization" version "1.5.31" apply false
id 'org.asciidoctor.jvm.convert' version '3.3.2'
id 'org.asciidoctor.jvm.pdf' version '3.3.2'
id 'de.undercouch.download' version '4.1.2'
id "io.freefair.aspectj" version '6.1.0' apply false
id "org.unbroken-dome.xjc" version '2.0.0' apply false
id "com.github.ben-manes.versions" version '0.39.0'
id "com.github.johnrengelman.shadow" version '7.0.0' apply false
id 'de.undercouch.download' version '4.1.2'
id "me.champeau.jmh" version "0.6.6" apply false
id "org.jetbrains.kotlin.plugin.serialization" version "1.5.30" apply false
id "org.unbroken-dome.xjc" version '2.0.0' apply false
}
ext {
@@ -28,15 +28,15 @@ configure(allprojects) { project ->
dependencyManagement {
imports {
mavenBom "com.fasterxml.jackson:jackson-bom:2.12.5"
mavenBom "io.netty:netty-bom:4.1.68.Final"
mavenBom "io.projectreactor:reactor-bom:2020.0.11"
mavenBom "io.netty:netty-bom:4.1.69.Final"
mavenBom "io.projectreactor:reactor-bom:2020.0.12"
mavenBom "io.r2dbc:r2dbc-bom:Arabba-SR10"
mavenBom "io.rsocket:rsocket-bom:1.1.1"
mavenBom "org.eclipse.jetty:jetty-bom:9.4.43.v20210629"
mavenBom "org.jetbrains.kotlin:kotlin-bom:1.5.30"
mavenBom "org.eclipse.jetty:jetty-bom:9.4.44.v20210927"
mavenBom "org.jetbrains.kotlin:kotlin-bom:1.5.31"
mavenBom "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.5.2"
mavenBom "org.jetbrains.kotlinx:kotlinx-serialization-bom:1.2.2"
mavenBom "org.junit:junit-bom:5.8.0"
mavenBom "org.junit:junit-bom:5.8.1"
}
dependencies {
dependencySet(group: 'org.apache.logging.log4j', version: '2.14.1') {
@@ -45,7 +45,7 @@ configure(allprojects) { project ->
entry 'log4j-jul'
entry 'log4j-slf4j-impl'
}
dependency "org.slf4j:slf4j-api:1.7.30"
dependency "org.slf4j:slf4j-api:1.7.32"
dependency("com.google.code.findbugs:findbugs:3.0.1") {
exclude group: "dom4j", name: "dom4j"
}
@@ -56,7 +56,7 @@ configure(allprojects) { project ->
entry 'aspectjtools'
entry 'aspectjweaver'
}
dependencySet(group: 'org.codehaus.groovy', version: '3.0.8') {
dependencySet(group: 'org.codehaus.groovy', version: '3.0.9') {
entry 'groovy'
entry 'groovy-jsr223'
entry 'groovy-templates' // requires findbugs for warning-free compilation
@@ -68,8 +68,8 @@ configure(allprojects) { project ->
dependency "io.reactivex:rxjava-reactive-streams:1.2.1"
dependency "io.reactivex.rxjava2:rxjava:2.2.21"
dependency "io.reactivex.rxjava3:rxjava:3.1.1"
dependency "io.smallrye.reactive:mutiny:1.0.0"
dependency "io.projectreactor.tools:blockhound:1.0.4.RELEASE"
dependency "io.smallrye.reactive:mutiny:1.1.1"
dependency "io.projectreactor.tools:blockhound:1.0.6.RELEASE"
dependency "com.caucho:hessian:4.0.63"
dependency "com.fasterxml:aalto-xml:1.3.0"
@@ -77,13 +77,13 @@ configure(allprojects) { project ->
exclude group: "stax", name: "stax-api"
}
dependency "com.google.code.gson:gson:2.8.8"
dependency "com.google.protobuf:protobuf-java-util:3.17.3"
dependency "com.google.protobuf:protobuf-java-util:3.18.0"
dependency "com.googlecode.protobuf-java-format:protobuf-java-format:1.4"
dependency("com.thoughtworks.xstream:xstream:1.4.18") {
exclude group: "xpp3", name: "xpp3_min"
exclude group: "xmlpull", name: "xmlpull"
}
dependency "org.apache.johnzon:johnzon-jsonb:1.2.10"
dependency "org.apache.johnzon:johnzon-jsonb:1.2.14"
dependency("org.codehaus.jettison:jettison:1.3.8") {
exclude group: "stax", name: "stax-api"
}
@@ -95,11 +95,11 @@ configure(allprojects) { project ->
dependency "org.yaml:snakeyaml:1.29"
dependency "com.h2database:h2:1.4.200"
dependency "com.github.ben-manes.caffeine:caffeine:2.9.1"
dependency "com.github.ben-manes.caffeine:caffeine:2.9.2"
dependency "com.github.librepdf:openpdf:1.3.26"
dependency "com.rometools:rome:1.15.0"
dependency "com.rometools:rome:1.16.0"
dependency "commons-io:commons-io:2.5"
dependency "io.vavr:vavr:0.10.3"
dependency "io.vavr:vavr:0.10.4"
dependency "net.sf.jopt-simple:jopt-simple:5.0.4"
dependencySet(group: 'org.apache.activemq', version: '5.16.2') {
entry 'activemq-broker'
@@ -125,28 +125,28 @@ configure(allprojects) { project ->
dependency "org.ehcache:ehcache:3.4.0"
dependency "org.hibernate:hibernate-core:5.4.32.Final"
dependency "org.hibernate:hibernate-validator:6.2.0.Final"
dependency "org.webjars:webjars-locator-core:0.47"
dependency "org.webjars:webjars-locator-core:0.48"
dependency "org.webjars:underscorejs:1.8.3"
dependencySet(group: 'org.apache.tomcat', version: '9.0.52') {
dependencySet(group: 'org.apache.tomcat', version: '9.0.53') {
entry 'tomcat-util'
entry('tomcat-websocket') {
exclude group: "org.apache.tomcat", name: "tomcat-websocket-api"
exclude group: "org.apache.tomcat", name: "tomcat-servlet-api"
}
}
dependencySet(group: 'org.apache.tomcat.embed', version: '9.0.52') {
dependencySet(group: 'org.apache.tomcat.embed', version: '9.0.53') {
entry 'tomcat-embed-core'
entry 'tomcat-embed-websocket'
}
dependencySet(group: 'io.undertow', version: '2.2.10.Final') {
dependencySet(group: 'io.undertow', version: '2.2.12.Final') {
entry 'undertow-core'
entry('undertow-websockets-jsr') {
exclude group: "org.jboss.spec.javax.websocket", name: "jboss-websocket-api_1.1_spec"
}
entry('undertow-servlet') {
exclude group: "org.jboss.spec.javax.servlet", name: "jboss-servlet-api_3.1_spec"
exclude group: "org.jboss.spec.javax.annotation", name: "jboss-annotations-api_1.2_spec"
exclude group: "org.jboss.spec.javax.servlet", name: "jboss-servlet-api_4.0_spec"
exclude group: "org.jboss.spec.javax.annotation", name: "jboss-annotations-api_1.3_spec"
}
}
@@ -188,16 +188,17 @@ configure(allprojects) { project ->
exclude group: "junit", name: "junit"
}
dependency "org.testng:testng:7.4.0"
dependency "org.junit.support:testng-engine:1.0.1"
dependency "org.hamcrest:hamcrest:2.1"
dependency "org.awaitility:awaitility:3.1.6"
dependency "org.assertj:assertj-core:3.20.2"
dependency "org.assertj:assertj-core:3.21.0"
dependencySet(group: 'org.xmlunit', version: '2.8.2') {
entry 'xmlunit-assertj'
entry('xmlunit-matchers') {
exclude group: "org.hamcrest", name: "hamcrest-core"
}
}
dependencySet(group: 'org.mockito', version: '3.12.4') {
dependencySet(group: 'org.mockito', version: '4.0.0') {
entry('mockito-core') {
exclude group: "org.hamcrest", name: "hamcrest-core"
}
@@ -205,10 +206,10 @@ configure(allprojects) { project ->
}
dependency "io.mockk:mockk:1.12.0"
dependency("net.sourceforge.htmlunit:htmlunit:2.52.0") {
dependency("net.sourceforge.htmlunit:htmlunit:2.53.0") {
exclude group: "commons-logging", name: "commons-logging"
}
dependency("org.seleniumhq.selenium:htmlunit-driver:2.52.0") {
dependency("org.seleniumhq.selenium:htmlunit-driver:2.53.0") {
exclude group: "commons-logging", name: "commons-logging"
}
dependency("org.seleniumhq.selenium:selenium-java:3.141.59") {
@@ -339,7 +340,7 @@ configure([rootProject] + javaProjects) { project ->
}
checkstyle {
toolVersion = "8.45.1"
toolVersion = "9.0"
configDirectory.set(rootProject.file("src/checkstyle"))
}
@@ -361,7 +362,7 @@ configure([rootProject] + javaProjects) { project ->
// JSR-305 only used for non-required meta-annotations
compileOnly("com.google.code.findbugs:jsr305")
testCompileOnly("com.google.code.findbugs:jsr305")
checkstyle("io.spring.javaformat:spring-javaformat-checkstyle:0.0.15")
checkstyle("io.spring.javaformat:spring-javaformat-checkstyle:0.0.29")
}
ext.javadocLinks = [
@@ -369,7 +370,6 @@ configure([rootProject] + javaProjects) { project ->
"https://docs.oracle.com/javaee/7/api/",
"https://docs.oracle.com/cd/E13222_01/wls/docs90/javadocs/", // CommonJ
"https://www.ibm.com/docs/api/v1/content/SSEQTP_8.5.5/com.ibm.websphere.javadoc.doc/web/apidocs/",
"https://glassfish.java.net/nonav/docs/v3/api/",
"https://docs.jboss.org/jbossas/javadoc/4.0.5/connector/",
"https://docs.jboss.org/jbossas/javadoc/7.1.2.Final/",
"https://tiles.apache.org/tiles-request/apidocs/",
@@ -383,7 +383,9 @@ configure([rootProject] + javaProjects) { project ->
"https://hc.apache.org/httpcomponents-client-5.1.x/current/httpclient5/apidocs/",
"https://projectreactor.io/docs/test/release/api/",
"https://junit.org/junit4/javadoc/4.13.2/",
"https://junit.org/junit5/docs/5.8.0/api/",
// Disabling linking to JUnit 5.8.1, since the `package-list` file no longer exists due to
// https://github.com/junit-team/junit5/commit/67ad4e545518b0ce2b0e7c96df31a669866d5003.
// "https://junit.org/junit5/docs/5.8.1/api/",
"https://www.reactive-streams.org/reactive-streams-1.0.3-javadoc/",
"https://javadoc.io/static/io.rsocket/rsocket-core/1.1.1/",
"https://r2dbc.io/spec/0.8.5.RELEASE/api/"
+1 -2
View File
@@ -8,8 +8,7 @@ repositories {
}
dependencies {
implementation "me.champeau.gradle:japicmp-gradle-plugin:0.2.8"
implementation "com.google.guava:guava:28.2-jre" // required by japicmp-gradle-plugin
implementation "me.champeau.gradle:japicmp-gradle-plugin:0.3.0"
}
gradlePlugin {
+1 -1
View File
@@ -5,7 +5,7 @@ github-repo: "https://github.com/spring-projects/spring-framework.git"
github-repo-name: "spring-projects/spring-framework"
docker-hub-organization: "springci"
artifactory-server: "https://repo.spring.io"
branch: "main"
branch: "5.3.x"
milestone: "5.3.x"
build-name: "spring-framework"
pipeline-name: "spring-framework"
+5
View File
@@ -46,6 +46,11 @@ resource_types:
source:
repository: springio/artifactory-resource
tag: 0.0.17
- name: github-release
type: registry-image
source:
repository: concourse/github-release-resource
tag: 1.5.5
- name: github-status-resource
type: registry-image
source:
+1 -1
View File
@@ -4,7 +4,7 @@ image_resource:
type: registry-image
source:
repository: springio/github-changelog-generator
tag: '0.0.6'
tag: '0.0.7'
inputs:
- name: git-repo
- name: artifactory-repo
+1 -1
View File
@@ -1,4 +1,4 @@
version=5.3.10-SNAPSHOT
version=5.3.11
org.gradle.jvmargs=-Xmx1536M
org.gradle.caching=true
org.gradle.parallel=true
+5 -5
View File
@@ -1,7 +1,7 @@
tasks.findByName("dokkaHtmlPartial")?.configure {
outputDirectory.set(new File(buildDir, "docs/kdoc"))
dokkaSourceSets {
configureEach {
outputDirectory.set(new File(buildDir, "docs/kdoc"))
dokkaSourceSets {
configureEach {
sourceRoots.setFrom(file("src/main/kotlin"))
classpath.from(sourceSets["main"].runtimeClasspath)
externalDocumentationLink {
@@ -17,7 +17,7 @@ tasks.findByName("dokkaHtmlPartial")?.configure {
url.set(new URL("https://kotlin.github.io/kotlinx.coroutines/"))
}
externalDocumentationLink {
url.set(new URL("https://hamcrest.org/JavaHamcrest/javadoc/2.1/"))
url.set(new URL("https://javadoc.io/doc/org.hamcrest/hamcrest/2.1/"))
}
externalDocumentationLink {
url.set(new URL("https://javadoc.io/doc/javax.servlet/javax.servlet-api/latest/"))
@@ -26,5 +26,5 @@ tasks.findByName("dokkaHtmlPartial")?.configure {
url.set(new URL("https://javadoc.io/static/io.rsocket/rsocket-core/1.1.1/"))
}
}
}
}
}
+3 -2
View File
@@ -46,8 +46,9 @@ task api(type: Javadoc) {
stylesheetFile = file("src/docs/api/stylesheet.css")
splitIndex = true
links(project.ext.javadocLinks)
addStringOption('Xdoclint:none', '-quiet')
if(JavaVersion.current().isJava9Compatible()) {
addBooleanOption('Xdoclint:syntax', true) // only check syntax with doclint
addBooleanOption('Xwerror', true) // fail build on Javadoc warnings
if (JavaVersion.current().isJava9Compatible()) {
addBooleanOption('html5', true)
}
}
+4 -26
View File
@@ -69,42 +69,20 @@ eclipse.classpath.file.whenMerged {
}
}
// Allow projects to be used as WTP modules
eclipse.project.natures 'org.eclipse.wst.common.project.facet.core.nature'
// Include project specific settings
task eclipseSettings(type: Copy) {
from rootProject.files(
'src/eclipse/org.eclipse.jdt.ui.prefs',
'src/eclipse/org.eclipse.wst.common.project.facet.core.xml')
'src/eclipse/org.eclipse.jdt.core.prefs',
'src/eclipse/org.eclipse.jdt.ui.prefs')
into project.file('.settings/')
outputs.upToDateWhen { false }
}
task eclipseJdtSettings(type: Copy) {
from rootProject.file('src/eclipse/org.eclipse.jdt.core.prefs')
into project.file('.settings/')
outputs.upToDateWhen { false }
}
task eclipseBuildship {
dependsOn eclipseSettings, eclipseJdtSettings
}
task eclipseWstComponentSettings(type: Copy) {
from rootProject.files('src/eclipse/org.eclipse.wst.common.component')
into project.file('.settings/')
expand(deployname: project.name)
outputs.upToDateWhen { false }
}
task cleanEclipseSettings(type: Delete) {
delete project.file('.settings/org.eclipse.jdt.core.prefs')
delete project.file('.settings/org.eclipse.jdt.ui.prefs')
delete project.file('.settings/org.eclipse.wst.common.component')
delete project.file('.settings/org.eclipse.wst.common.project.facet.core.xml')
}
tasks['eclipse'].dependsOn(eclipseSettings, eclipseJdtSettings, eclipseWstComponentSettings)
tasks['eclipseJdt'].dependsOn(eclipseJdtSettings)
tasks['eclipse'].dependsOn(eclipseSettings)
tasks['eclipseJdt'].dependsOn(eclipseSettings)
tasks['cleanEclipse'].dependsOn(cleanEclipseSettings)
+24 -20
View File
@@ -3,11 +3,11 @@
This document will guide you through the process of importing the Spring Framework
projects into Eclipse or the Spring Tool Suite (_STS_). It is recommended that you
have a recent version of Eclipse. As a bare minimum you will need Eclipse with full Java
8 support, Eclipse Buildship, the Kotlin plugin, and the Groovy plugin.
8 support, Eclipse Buildship, and the Groovy plugin.
The following instructions have been tested against [STS](https://spring.io/tools) 4.3.2
([download](https://github.com/spring-projects/sts4/wiki/Previous-Versions#spring-tools-432-changelog))
(based on Eclipse 4.12) with [Eclipse Buildship](https://projects.eclipse.org/projects/tools.buildship).
The following instructions have been tested against [STS](https://spring.io/tools) 4.12.0
([download](https://github.com/spring-projects/sts4/wiki/Previous-Versions#spring-tools-4120-changelog))
(based on Eclipse 4.21) with [Eclipse Buildship](https://projects.eclipse.org/projects/tools.buildship).
The instructions should work with the latest Eclipse distribution as long as you install
[Buildship](https://marketplace.eclipse.org/content/buildship-gradle-integration). Note
that STS 4 comes with Buildship preinstalled.
@@ -16,28 +16,32 @@ that STS 4 comes with Buildship preinstalled.
_When instructed to execute `./gradlew` from the command line, be sure to execute it within your locally cloned `spring-framework` working directory._
1. Ensure that Eclipse launches with JDK 8.
- For example, on Mac OS this can be configured in the `Info.plist` file located in the `Contents` folder of the installed Eclipse or STS application (e.g., the `Eclipse.app` file).
1. Install the [Kotlin Plugin for Eclipse](https://marketplace.eclipse.org/content/kotlin-plugin-eclipse) in Eclipse.
1. Install the [Eclipse Groovy Development Tools](https://github.com/groovy/groovy-eclipse/wiki) in Eclipse.
1. Switch to Groovy 2.5 (Preferences -> Groovy -> Compiler -> Switch to 2.5...) in Eclipse.
1. Change the _Forbidden reference (access rule)_ in Eclipse from Error to Warning
(Preferences -> Java -> Compiler -> Errors/Warnings -> Deprecated and restricted API -> Forbidden reference (access rule)).
1. Optionally install the [AspectJ Development Tools](https://marketplace.eclipse.org/content/aspectj-development-tools) (_AJDT_) if you need to work with the `spring-aspects` project. The AspectJ Development Tools available in the Eclipse Marketplace have been tested with these instructions using STS 4.5 (Eclipse 4.14).
1. Optionally install the [TestNG plugin](https://testng.org/doc/eclipse.html) in Eclipse if you need to execute TestNG tests in the `spring-test` module.
1. Install the [Groovy Development Tools](https://marketplace.eclipse.org/content/groovy-development-tools).
1. Switch to Groovy 3.0 in Eclipse (Preferences &#8594; Groovy &#8594; Compiler &#8594; Switch to 3.0...).
- If you encounter build errors stating something similar to _"Groovy: compiler mismatch: project level is 2.5, workspace level is 3.0"_, change the Groovy compiler version to 3.0 for each affected project.
1. Ensure that the _Forbidden reference (access rule)_ in Eclipse is set to `Info`
(Preferences &#8594; Java &#8594; Compiler &#8594; Errors/Warnings &#8594; Deprecated and restricted API &#8594; Forbidden reference (access rule)).
1. Optionally install the [Kotlin Plugin for Eclipse](https://marketplace.eclipse.org/content/kotlin-plugin-eclipse) if you need to execute Kotlin-based tests or develop Kotlin extensions.
- **NOTE**: As of September 21, 2021, it appears that the Kotlin Plugin for Eclipse does not yet work with Eclipse 4.21.
1. Optionally install the [AspectJ Development Tools](https://marketplace.eclipse.org/content/aspectj-development-tools) (_AJDT_) if you need to work with the `spring-aspects` project.
- **NOTE**: As of September 21, 2021, it appears that the AspectJ Development Tools do not yet work with Eclipse 4.21.
1. Optionally install the [TestNG plugin](https://testng.org/doc/eclipse.html) in Eclipse if you need to execute individual TestNG test classes or tests in the `spring-test` module.
- As an alternative to installing the TestNG plugin, you can execute the `org.springframework.test.context.testng.TestNGTestSuite` class as a "JUnit 5" test class in Eclipse.
1. Build `spring-oxm` from the command line with `./gradlew :spring-oxm:check`.
1. To apply project specific settings, run `./gradlew eclipseBuildship` from the command line.
1. Import into Eclipse (File -> Import -> Gradle -> Existing Gradle Project -> Navigate to the locally cloned `spring-framework` directory -> Select Finish).
1. To apply Spring Framework specific settings, run `./gradlew cleanEclipse eclipse` from the command line.
1. Import all projects into Eclipse (File &#8594; Import &#8594; Gradle &#8594; Existing Gradle Project &#8594; Navigate to the locally cloned `spring-framework` directory &#8594; Select Finish).
- If you have not installed AJDT, exclude the `spring-aspects` project from the import, if prompted, or close it after the import.
- If you run into errors during the import, you may need to set the _Java home_ for Gradle Buildship to the location of your JDK 8 installation in Eclipse (Preferences -> Gradle -> Java home).
1. If you need to execute JAXB-related tests in the `spring-oxm` project and wish to have the generated sources available, add the `build/generated-sources/jaxb` folder to the build path (right click on the `jaxb` folder and select `Build Path -> Use as Source Folder`).
- If you do not see the `build` folder in the `spring-oxm` project, ensure that the "Gradle build folder" is not filtered out from the view. This setting is available under "Filters" in the configuration of the Package Explorer (available by clicking on the small downward facing arrow in the upper right corner of the Package Explorer).
- If you run into errors during the import, you may need to set the _Java home_ for Gradle Buildship to the location of your JDK 8 installation in Eclipse (Preferences &#8594; Gradle &#8594; Java home).
1. If you need to execute JAXB-related tests in the `spring-oxm` project and wish to have the generated sources available, add the `build/generated-sources/jaxb` folder to the build path (right click on the `jaxb` folder and select "Build Path &#8594; Use as Source Folder").
- If you do not see the `build` folder in the `spring-oxm` project, ensure that the "Gradle build folder" is not filtered out from the view. This setting is available under "Filters" in the configuration of the Package Explorer (available by clicking on the _three vertical dots_ in the upper right corner of the Package Explorer).
1. Code away!
## Known Issues
1. `spring-core` and `spring-oxm` should be pre-compiled due to repackaged dependencies.
- See `*RepackJar` tasks in the build.
1. `spring-core` should be pre-compiled due to repackaged dependencies.
- See `*RepackJar` tasks in the `spring-core.gradle` build file.
1. `spring-oxm` should be pre-compiled due to JAXB types generated for tests.
- Note that executing `./gradlew :spring-oxm:check` as explained in the _Steps_ above will compile `spring-core` and generate JAXB types for `spring-oxm`.
1. `spring-aspects` does not compile due to references to aspect types unknown to Eclipse.
- If you installed _AJDT_ into Eclipse it should work.
1. While JUnit tests pass from the command line with Gradle, some may fail when run from
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@@ -237,7 +237,7 @@ class CglibAopProxy implements AopProxy, Serializable {
* validates it if not.
*/
private void validateClassIfNecessary(Class<?> proxySuperClass, @Nullable ClassLoader proxyClassLoader) {
if (logger.isWarnEnabled()) {
if (!this.advised.isOptimize() && logger.isInfoEnabled()) {
synchronized (validatedClasses) {
if (!validatedClasses.containsKey(proxySuperClass)) {
doValidateClass(proxySuperClass, proxyClassLoader,
@@ -679,13 +679,19 @@ class CglibAopProxy implements AopProxy, Serializable {
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
if (chain.isEmpty() && CglibMethodInvocation.isMethodProxyCompatible(method)) {
// We can skip creating a MethodInvocation: just invoke the target directly.
// Note that the final invoker must be an InvokerInterceptor, so we know
// it does nothing but a reflective operation on the target, and no hot
// swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
try {
retVal = methodProxy.invoke(target, argsToUse);
}
catch (CodeGenerationException ex) {
CglibMethodInvocation.logFastClassGenerationFailure(method);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
}
else {
// We need to create a method invocation...
@@ -737,10 +743,7 @@ class CglibAopProxy implements AopProxy, Serializable {
super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);
// Only use method proxy for public methods not derived from java.lang.Object
this.methodProxy = (Modifier.isPublic(method.getModifiers()) &&
method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&
!AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method) ?
methodProxy : null);
this.methodProxy = (isMethodProxyCompatible(method) ? methodProxy : null);
}
@Override
@@ -776,10 +779,25 @@ class CglibAopProxy implements AopProxy, Serializable {
@Override
protected Object invokeJoinpoint() throws Throwable {
if (this.methodProxy != null) {
return this.methodProxy.invoke(this.target, this.arguments);
try {
return this.methodProxy.invoke(this.target, this.arguments);
}
catch (CodeGenerationException ex) {
logFastClassGenerationFailure(this.method);
}
}
else {
return super.invokeJoinpoint();
return super.invokeJoinpoint();
}
static boolean isMethodProxyCompatible(Method method) {
return (Modifier.isPublic(method.getModifiers()) &&
method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&
!AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method));
}
static void logFastClassGenerationFailure(Method method) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to generate CGLIB fast class for method: " + method);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2021 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.
@@ -73,11 +73,9 @@ public class ProxyConfig implements Serializable {
* The exact meaning of "aggressive optimizations" will differ
* between proxies, but there is usually some tradeoff.
* Default is "false".
* <p>For example, optimization will usually mean that advice changes won't
* take effect after a proxy has been created. For this reason, optimization
* is disabled by default. An optimize value of "true" may be ignored
* if other settings preclude optimization: for example, if "exposeProxy"
* is set to "true" and that's not compatible with the optimization.
* <p>With Spring's current proxy options, this flag effectively
* enforces CGLIB proxies (similar to {@link #setProxyTargetClass})
* but without any class validation checks (for final methods etc).
*/
public void setOptimize(boolean optimize) {
this.optimize = optimize;
@@ -61,7 +61,7 @@ public class BeanNameAutoProxyCreator extends AbstractAutoProxyCreator {
* FactoryBean will get proxied. This default behavior applies as of Spring 2.0.
* If you intend to proxy a FactoryBean instance itself (a rare use case, but
* Spring 1.2's default behavior), specify the bean name of the FactoryBean
* including the factory-bean prefix "&": e.g. "&myFactoryBean".
* including the factory-bean prefix "&amp;": e.g. "&amp;myFactoryBean".
* @see org.springframework.beans.factory.FactoryBean
* @see org.springframework.beans.factory.BeanFactory#FACTORY_BEAN_PREFIX
*/
@@ -25,9 +25,11 @@ import org.springframework.lang.Nullable;
/**
* Convenient TargetSourceCreator using bean name prefixes to create one of three
* well-known TargetSource types:
* <li>: CommonsPool2TargetSource
* <li>% ThreadLocalTargetSource
* <li>! PrototypeTargetSource
* <ul>
* <li>: CommonsPool2TargetSource</li>
* <li>% ThreadLocalTargetSource</li>
* <li>! PrototypeTargetSource</li>
* </ul>
*
* @author Rod Johnson
* @author Stephane Nicoll
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@@ -146,7 +146,7 @@ public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher
@Override
public String toString() {
return getClass().getName() + ": class = " + this.clazz.getName() + "; methodName = " + methodName;
return getClass().getName() + ": class = " + this.clazz.getName() + "; methodName = " + this.methodName;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2021 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.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.aop.support;
import org.junit.jupiter.api.Test;
@@ -29,10 +30,10 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Rob Harrop
* @author Rick Evans
*/
public class ClassUtilsTests {
class ClassUtilsTests {
@Test
public void getShortNameForCglibClass() {
void getShortNameForCglibClass() {
TestBean tb = new TestBean();
ProxyFactory pf = new ProxyFactory();
pf.setTarget(tb);
@@ -41,4 +42,5 @@ public class ClassUtilsTests {
String className = ClassUtils.getShortName(proxy.getClass());
assertThat(className).as("Class name did not match").isEqualTo("TestBean");
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2021 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.
@@ -13,14 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.aspectj;
/**
* Marker interface for domain object that need DI through aspects.
* Marker interface for domain objects that need DI through aspects.
*
* @author Ramnivas Laddad
* @since 2.5
*/
public interface ConfigurableObject {
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2021 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.
@@ -22,13 +22,18 @@ import org.springframework.contextsupport.testfixture.jcache.AbstractJCacheAnnot
/**
* @author Stephane Nicoll
* @author Sam Brannen
*/
public class JCacheAspectJNamespaceConfigTests extends AbstractJCacheAnnotationTests {
@Override
protected ApplicationContext getApplicationContext() {
return new GenericXmlApplicationContext(
"/org/springframework/cache/config/annotation-jcache-aspectj.xml");
GenericXmlApplicationContext context = new GenericXmlApplicationContext();
// Disallow bean definition overriding to test https://github.com/spring-projects/spring-framework/pull/27499
context.setAllowBeanDefinitionOverriding(false);
context.load("/org/springframework/cache/config/annotation-jcache-aspectj.xml");
context.refresh();
return context;
}
}
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.transaction.aspectj;
import org.springframework.transaction.annotation.Transactional;
@@ -29,4 +30,5 @@ public class ClassWithPrivateAnnotatedMember {
@Transactional
private void doInTransaction() {}
}
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.transaction.aspectj;
import org.springframework.transaction.annotation.Transactional;
@@ -29,4 +30,5 @@ public class ClassWithProtectedAnnotatedMember {
@Transactional
protected void doInTransaction() {}
}
@@ -100,9 +100,9 @@ public abstract class BeanUtils {
* @param clazz class to instantiate
* @return the new instance
* @throws BeanInstantiationException if the bean cannot be instantiated
* @see Class#newInstance()
* @deprecated as of Spring 5.0, following the deprecation of
* {@link Class#newInstance()} in JDK 9
* @see Class#newInstance()
*/
@Deprecated
public static <T> T instantiate(Class<T> clazz) throws BeanInstantiationException {
@@ -226,32 +226,45 @@ public abstract class BeanUtils {
}
/**
* Return a resolvable constructor for the provided class, either a primary constructor
* or single public constructor or simply a default constructor. Callers have to be
* prepared to resolve arguments for the returned constructor's parameters, if any.
* Return a resolvable constructor for the provided class, either a primary or single
* public constructor with arguments, or a single non-public constructor with arguments,
* or simply a default constructor. Callers have to be prepared to resolve arguments
* for the returned constructor's parameters, if any.
* @param clazz the class to check
* @throws IllegalStateException in case of no unique constructor found at all
* @since 5.3
* @see #findPrimaryConstructor
*/
@SuppressWarnings("unchecked")
public static <T> Constructor<T> getResolvableConstructor(Class<T> clazz) {
Constructor<T> ctor = findPrimaryConstructor(clazz);
if (ctor == null) {
Constructor<?>[] ctors = clazz.getConstructors();
if (ctor != null) {
return ctor;
}
Constructor<?>[] ctors = clazz.getConstructors();
if (ctors.length == 1) {
// A single public constructor
return (Constructor<T>) ctors[0];
}
else if (ctors.length == 0){
ctors = clazz.getDeclaredConstructors();
if (ctors.length == 1) {
ctor = (Constructor<T>) ctors[0];
}
else {
try {
ctor = clazz.getDeclaredConstructor();
}
catch (NoSuchMethodException ex) {
throw new IllegalStateException("No primary or single public constructor found for " +
clazz + " - and no default constructor found either");
}
// A single non-public constructor, e.g. from a non-public record type
return (Constructor<T>) ctors[0];
}
}
return ctor;
// Several constructors -> let's try to take the default constructor
try {
return clazz.getDeclaredConstructor();
}
catch (NoSuchMethodException ex) {
// Giving up...
}
// No unique constructor at all
throw new IllegalStateException("No primary or single unique constructor found for " + clazz);
}
/**
@@ -527,7 +540,7 @@ public abstract class BeanUtils {
/**
* Find a JavaBeans PropertyEditor following the 'Editor' suffix convention
* (e.g. "mypackage.MyDomainClass" -> "mypackage.MyDomainClassEditor").
* (e.g. "mypackage.MyDomainClass" &rarr; "mypackage.MyDomainClassEditor").
* <p>Compatible to the standard JavaBeans convention as implemented by
* {@link java.beans.PropertyEditorManager} but isolated from the latter's
* registered default editors for primitive types.
@@ -134,8 +134,8 @@ public abstract class PropertyAccessorUtils {
/**
* Determine the canonical name for the given property path.
* Removes surrounding quotes from map keys:<br>
* {@code map['key']} -> {@code map[key]}<br>
* {@code map["key"]} -> {@code map[key]}
* {@code map['key']} &rarr; {@code map[key]}<br>
* {@code map["key"]} &rarr; {@code map[key]}
* @param propertyName the bean property path
* @return the canonical representation of the property path
*/
@@ -539,8 +539,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
*/
@SuppressWarnings({"deprecation", "cast"})
protected boolean determineRequiredStatus(MergedAnnotation<?> ann) {
// The following (AnnotationAttributes) cast is required on JDK 9+.
return determineRequiredStatus((AnnotationAttributes)
return determineRequiredStatus(
ann.asMap(mergedAnnotation -> new AnnotationAttributes(mergedAnnotation.getType())));
}
@@ -47,17 +47,17 @@ import org.springframework.util.ClassUtils;
* which uses this class to call a static initialization method:
*
* <pre class="code">
* &lt;bean id="myObject" class="org.springframework.beans.factory.config.MethodInvokingBean">
* &lt;property name="staticMethod" value="com.whatever.MyClass.init"/>
* &lt;/bean></pre>
* &lt;bean id="myObject" class="org.springframework.beans.factory.config.MethodInvokingBean"&gt;
* &lt;property name="staticMethod" value="com.whatever.MyClass.init"/&gt;
* &lt;/bean&gt;</pre>
*
* <p>An example of calling an instance method to start some server bean:
*
* <pre class="code">
* &lt;bean id="myStarter" class="org.springframework.beans.factory.config.MethodInvokingBean">
* &lt;property name="targetObject" ref="myServer"/>
* &lt;property name="targetMethod" value="start"/>
* &lt;/bean></pre>
* &lt;bean id="myStarter" class="org.springframework.beans.factory.config.MethodInvokingBean"&gt;
* &lt;property name="targetObject" ref="myServer"/&gt;
* &lt;property name="targetMethod" value="start"/&gt;
* &lt;/bean&gt;</pre>
*
* @author Juergen Hoeller
* @since 4.0.3
@@ -56,24 +56,24 @@ import org.springframework.lang.Nullable;
* which uses this class to call a static factory method:
*
* <pre class="code">
* &lt;bean id="myObject" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
* &lt;property name="staticMethod" value="com.whatever.MyClassFactory.getInstance"/>
* &lt;/bean></pre>
* &lt;bean id="myObject" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"&gt;
* &lt;property name="staticMethod" value="com.whatever.MyClassFactory.getInstance"/&gt;
* &lt;/bean&gt;</pre>
*
* <p>An example of calling a static method then an instance method to get at a
* Java system property. Somewhat verbose, but it works.
*
* <pre class="code">
* &lt;bean id="sysProps" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
* &lt;property name="targetClass" value="java.lang.System"/>
* &lt;property name="targetMethod" value="getProperties"/>
* &lt;/bean>
* &lt;bean id="sysProps" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"&gt;
* &lt;property name="targetClass" value="java.lang.System"/&gt;
* &lt;property name="targetMethod" value="getProperties"/&gt;
* &lt;/bean&gt;
*
* &lt;bean id="javaVersion" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
* &lt;property name="targetObject" ref="sysProps"/>
* &lt;property name="targetMethod" value="getProperty"/>
* &lt;property name="arguments" value="java.version"/>
* &lt;/bean></pre>
* &lt;bean id="javaVersion" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"&gt;
* &lt;property name="targetObject" ref="sysProps"/&gt;
* &lt;property name="targetMethod" value="getProperty"/&gt;
* &lt;property name="arguments" value="java.version"/&gt;
* &lt;/bean&gt;</pre>
*
* @author Colin Sampaleanu
* @author Juergen Hoeller
@@ -83,22 +83,22 @@ import org.springframework.util.StringUtils;
* <p>A sample config in an XML-based
* {@link org.springframework.beans.factory.BeanFactory} might look as follows:
*
* <pre class="code">&lt;beans>
* <pre class="code">&lt;beans&gt;
*
* &lt;!-- Prototype bean since we have state -->
* &lt;bean id="myService" class="a.b.c.MyService" singleton="false"/>
* &lt;!-- Prototype bean since we have state --&gt;
* &lt;bean id="myService" class="a.b.c.MyService" singleton="false"/&gt;
*
* &lt;!-- will lookup the above 'myService' bean by *TYPE* -->
* &lt;!-- will lookup the above 'myService' bean by *TYPE* --&gt;
* &lt;bean id="myServiceFactory"
* class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean">
* &lt;property name="serviceLocatorInterface" value="a.b.c.ServiceFactory"/>
* &lt;/bean>
* class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean"&gt;
* &lt;property name="serviceLocatorInterface" value="a.b.c.ServiceFactory"/&gt;
* &lt;/bean&gt;
*
* &lt;bean id="clientBean" class="a.b.c.MyClientBean">
* &lt;property name="myServiceFactory" ref="myServiceFactory"/>
* &lt;/bean>
* &lt;bean id="clientBean" class="a.b.c.MyClientBean"&gt;
* &lt;property name="myServiceFactory" ref="myServiceFactory"/&gt;
* &lt;/bean&gt;
*
*&lt;/beans></pre>
*&lt;/beans&gt;</pre>
*
* <p>The attendant {@code MyClientBean} class implementation might then
* look something like this:
@@ -135,22 +135,22 @@ import org.springframework.util.StringUtils;
* <p>A sample config in an XML-based
* {@link org.springframework.beans.factory.BeanFactory} might look as follows:
*
* <pre class="code">&lt;beans>
* <pre class="code">&lt;beans&gt;
*
* &lt;!-- Prototype beans since we have state (both extend MyService) -->
* &lt;bean id="specialService" class="a.b.c.SpecialService" singleton="false"/>
* &lt;bean id="anotherService" class="a.b.c.AnotherService" singleton="false"/>
* &lt;!-- Prototype beans since we have state (both extend MyService) --&gt;
* &lt;bean id="specialService" class="a.b.c.SpecialService" singleton="false"/&gt;
* &lt;bean id="anotherService" class="a.b.c.AnotherService" singleton="false"/&gt;
*
* &lt;bean id="myServiceFactory"
* class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean">
* &lt;property name="serviceLocatorInterface" value="a.b.c.ServiceFactory"/>
* &lt;/bean>
* class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean"&gt;
* &lt;property name="serviceLocatorInterface" value="a.b.c.ServiceFactory"/&gt;
* &lt;/bean&gt;
*
* &lt;bean id="clientBean" class="a.b.c.MyClientBean">
* &lt;property name="myServiceFactory" ref="myServiceFactory"/>
* &lt;/bean>
* &lt;bean id="clientBean" class="a.b.c.MyClientBean"&gt;
* &lt;property name="myServiceFactory" ref="myServiceFactory"/&gt;
* &lt;/bean&gt;
*
*&lt;/beans></pre>
*&lt;/beans&gt;</pre>
*
* <p>The attendant {@code MyClientBean} class implementation might then
* look something like this:
@@ -86,7 +86,7 @@ public abstract class YamlProcessor {
* </pre>
* when mapped with
* <pre class="code">
* setDocumentMatchers(properties ->
* setDocumentMatchers(properties -&gt;
* ("prod".equals(properties.getProperty("environment")) ? MatchStatus.FOUND : MatchStatus.NOT_FOUND));
* </pre>
* would end up as
@@ -75,18 +75,18 @@ import org.springframework.util.StringUtils;
*
* def reader = new GroovyBeanDefinitionReader(myApplicationContext)
* reader.beans {
* dataSource(BasicDataSource) { // <--- invokeMethod
* dataSource(BasicDataSource) { // &lt;--- invokeMethod
* driverClassName = "org.hsqldb.jdbcDriver"
* url = "jdbc:hsqldb:mem:grailsDB"
* username = "sa" // <-- setProperty
* username = "sa" // &lt;-- setProperty
* password = ""
* settings = [mynew:"setting"]
* }
* sessionFactory(SessionFactory) {
* dataSource = dataSource // <-- getProperty for retrieving references
* dataSource = dataSource // &lt;-- getProperty for retrieving references
* }
* myService(MyService) {
* nestedBean = { AnotherBean bean -> // <-- setProperty with closure for nested bean
* nestedBean = { AnotherBean bean -&gt; // &lt;-- setProperty with closure for nested bean
* dataSource = dataSource
* }
* }
@@ -113,7 +113,7 @@ import org.springframework.util.StringUtils;
* dataSource = dataSource
* }
* myService(MyService) {
* nestedBean = { AnotherBean bean ->
* nestedBean = { AnotherBean bean -&gt;
* dataSource = dataSource
* }
* }
@@ -1342,7 +1342,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param explicitArgs argument values passed in programmatically via the getBean method,
* or {@code null} if none (-> use constructor argument values from bean definition)
* or {@code null} if none (implying the use of constructor argument values from bean definition)
* @return a BeanWrapper for the new instance
* @see #getBean(String, Object[])
*/
@@ -1363,7 +1363,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
* @param mbd the bean definition for the bean
* @param ctors the chosen candidate constructors
* @param explicitArgs argument values passed in programmatically via the getBean method,
* or {@code null} if none (-> use constructor argument values from bean definition)
* or {@code null} if none (implying the use of constructor argument values from bean definition)
* @return a BeanWrapper for the new instance
*/
protected BeanWrapper autowireConstructor(
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@@ -361,7 +361,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
@@ -61,6 +61,8 @@ import org.springframework.util.StringUtils;
@SuppressWarnings("serial")
class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
private static final String DESTROY_METHOD_NAME = "destroy";
private static final String CLOSE_METHOD_NAME = "close";
private static final String SHUTDOWN_METHOD_NAME = "shutdown";
@@ -72,12 +74,11 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
private final String beanName;
private final boolean invokeDisposableBean;
private final boolean nonPublicAccessAllowed;
@Nullable
private final AccessControlContext acc;
private final boolean invokeDisposableBean;
private boolean invokeAutoCloseable;
@Nullable
private String destroyMethodName;
@@ -88,6 +89,9 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
@Nullable
private final List<DestructionAwareBeanPostProcessor> beanPostProcessors;
@Nullable
private final AccessControlContext acc;
/**
* Create a new DisposableBeanAdapter for the given bean.
@@ -103,38 +107,45 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
Assert.notNull(bean, "Disposable bean must not be null");
this.bean = bean;
this.beanName = beanName;
this.invokeDisposableBean =
(this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"));
this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
this.acc = acc;
this.invokeDisposableBean = (bean instanceof DisposableBean &&
!beanDefinition.isExternallyManagedDestroyMethod(DESTROY_METHOD_NAME));
String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
if (destroyMethodName != null &&
!(this.invokeDisposableBean && DESTROY_METHOD_NAME.equals(destroyMethodName)) &&
!beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
this.destroyMethodName = destroyMethodName;
Method destroyMethod = determineDestroyMethod(destroyMethodName);
if (destroyMethod == null) {
if (beanDefinition.isEnforceDestroyMethod()) {
throw new BeanDefinitionValidationException("Could not find a destroy method named '" +
destroyMethodName + "' on bean with name '" + beanName + "'");
}
}
else {
if (destroyMethod.getParameterCount() > 0) {
Class<?>[] paramTypes = destroyMethod.getParameterTypes();
if (paramTypes.length > 1) {
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
beanName + "' has more than one parameter - not supported as destroy method");
}
else if (paramTypes.length == 1 && boolean.class != paramTypes[0]) {
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
beanName + "' has a non-boolean parameter - not supported as destroy method");
this.invokeAutoCloseable = (bean instanceof AutoCloseable && CLOSE_METHOD_NAME.equals(destroyMethodName));
if (!this.invokeAutoCloseable) {
this.destroyMethodName = destroyMethodName;
Method destroyMethod = determineDestroyMethod(destroyMethodName);
if (destroyMethod == null) {
if (beanDefinition.isEnforceDestroyMethod()) {
throw new BeanDefinitionValidationException("Could not find a destroy method named '" +
destroyMethodName + "' on bean with name '" + beanName + "'");
}
}
destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod);
else {
if (destroyMethod.getParameterCount() > 0) {
Class<?>[] paramTypes = destroyMethod.getParameterTypes();
if (paramTypes.length > 1) {
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
beanName + "' has more than one parameter - not supported as destroy method");
}
else if (paramTypes.length == 1 && boolean.class != paramTypes[0]) {
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
beanName + "' has a non-boolean parameter - not supported as destroy method");
}
}
destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod);
}
this.destroyMethod = destroyMethod;
}
this.destroyMethod = destroyMethod;
}
this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
this.acc = acc;
}
/**
@@ -149,26 +160,27 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
Assert.notNull(bean, "Disposable bean must not be null");
this.bean = bean;
this.beanName = bean.getClass().getName();
this.invokeDisposableBean = (this.bean instanceof DisposableBean);
this.nonPublicAccessAllowed = true;
this.acc = acc;
this.invokeDisposableBean = (this.bean instanceof DisposableBean);
this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
this.acc = acc;
}
/**
* Create a new DisposableBeanAdapter for the given bean.
*/
private DisposableBeanAdapter(Object bean, String beanName, boolean invokeDisposableBean,
boolean nonPublicAccessAllowed, @Nullable String destroyMethodName,
private DisposableBeanAdapter(Object bean, String beanName, boolean nonPublicAccessAllowed,
boolean invokeDisposableBean, boolean invokeAutoCloseable, @Nullable String destroyMethodName,
@Nullable List<DestructionAwareBeanPostProcessor> postProcessors) {
this.bean = bean;
this.beanName = beanName;
this.invokeDisposableBean = invokeDisposableBean;
this.nonPublicAccessAllowed = nonPublicAccessAllowed;
this.acc = null;
this.invokeDisposableBean = invokeDisposableBean;
this.invokeAutoCloseable = invokeAutoCloseable;
this.destroyMethodName = destroyMethodName;
this.beanPostProcessors = postProcessors;
this.acc = null;
}
@@ -211,7 +223,32 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
}
}
if (this.destroyMethod != null) {
if (this.invokeAutoCloseable) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking close() on bean with name '" + this.beanName + "'");
}
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((AutoCloseable) this.bean).close();
return null;
}, this.acc);
}
else {
((AutoCloseable) this.bean).close();
}
}
catch (Throwable ex) {
String msg = "Invocation of close method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex);
}
else {
logger.warn(msg + ": " + ex);
}
}
}
else if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
@@ -259,7 +296,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
args[0] = Boolean.TRUE;
}
if (logger.isTraceEnabled()) {
logger.trace("Invoking destroy method '" + this.destroyMethodName +
logger.trace("Invoking custom destroy method '" + this.destroyMethodName +
"' on bean with name '" + this.beanName + "'");
}
try {
@@ -282,7 +319,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
}
}
catch (InvocationTargetException ex) {
String msg = "Destroy method '" + this.destroyMethodName + "' on bean with name '" +
String msg = "Custom destroy method '" + this.destroyMethodName + "' on bean with name '" +
this.beanName + "' threw an exception";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex.getTargetException());
@@ -292,7 +329,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
}
}
catch (Throwable ex) {
logger.warn("Failed to invoke destroy method '" + this.destroyMethodName +
logger.warn("Failed to invoke custom destroy method '" + this.destroyMethodName +
"' on bean with name '" + this.beanName + "'", ex);
}
}
@@ -312,8 +349,9 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
}
}
}
return new DisposableBeanAdapter(this.bean, this.beanName, this.invokeDisposableBean,
this.nonPublicAccessAllowed, this.destroyMethodName, serializablePostProcessors);
return new DisposableBeanAdapter(
this.bean, this.beanName, this.nonPublicAccessAllowed, this.invokeDisposableBean,
this.invokeAutoCloseable, this.destroyMethodName, serializablePostProcessors);
}
@@ -323,10 +361,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
* @param beanDefinition the corresponding bean definition
*/
public static boolean hasDestroyMethod(Object bean, RootBeanDefinition beanDefinition) {
if (bean instanceof DisposableBean || bean instanceof AutoCloseable) {
return true;
}
return inferDestroyMethodIfNecessary(bean, beanDefinition) != null;
return (bean instanceof DisposableBean || inferDestroyMethodIfNecessary(bean, beanDefinition) != null);
}
@@ -348,21 +383,27 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
String destroyMethodName = beanDefinition.resolvedDestroyMethodName;
if (destroyMethodName == null) {
destroyMethodName = beanDefinition.getDestroyMethodName();
boolean autoCloseable = (bean instanceof AutoCloseable);
if (AbstractBeanDefinition.INFER_METHOD.equals(destroyMethodName) ||
(destroyMethodName == null && bean instanceof AutoCloseable)) {
// Only perform destroy method inference or Closeable detection
// in case of the bean not explicitly implementing DisposableBean
(destroyMethodName == null && autoCloseable)) {
// Only perform destroy method inference in case of the bean
// not explicitly implementing the DisposableBean interface
destroyMethodName = null;
if (!(bean instanceof DisposableBean)) {
try {
destroyMethodName = bean.getClass().getMethod(CLOSE_METHOD_NAME).getName();
if (autoCloseable) {
destroyMethodName = CLOSE_METHOD_NAME;
}
catch (NoSuchMethodException ex) {
else {
try {
destroyMethodName = bean.getClass().getMethod(SHUTDOWN_METHOD_NAME).getName();
destroyMethodName = bean.getClass().getMethod(CLOSE_METHOD_NAME).getName();
}
catch (NoSuchMethodException ex2) {
// no candidate destroy method found
catch (NoSuchMethodException ex) {
try {
destroyMethodName = bean.getClass().getMethod(SHUTDOWN_METHOD_NAME).getName();
}
catch (NoSuchMethodException ex2) {
// no candidate destroy method found
}
}
}
}
@@ -21,7 +21,8 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.function.Supplier;
@@ -422,15 +423,21 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
return this.factoryMethodToIntrospect;
}
/**
* Register an externally managed configuration method or field.
*/
public void registerExternallyManagedConfigMember(Member configMember) {
synchronized (this.postProcessingLock) {
if (this.externallyManagedConfigMembers == null) {
this.externallyManagedConfigMembers = new HashSet<>(1);
this.externallyManagedConfigMembers = new LinkedHashSet<>(1);
}
this.externallyManagedConfigMembers.add(configMember);
}
}
/**
* Check whether the given method or field is an externally managed configuration member.
*/
public boolean isExternallyManagedConfigMember(Member configMember) {
synchronized (this.postProcessingLock) {
return (this.externallyManagedConfigMembers != null &&
@@ -438,15 +445,33 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
}
}
/**
* Return all externally managed configuration methods and fields (as an immutable Set).
* @since 5.3.11
*/
public Set<Member> getExternallyManagedConfigMembers() {
synchronized (this.postProcessingLock) {
return (this.externallyManagedConfigMembers != null ?
Collections.unmodifiableSet(new LinkedHashSet<>(this.externallyManagedConfigMembers)) :
Collections.emptySet());
}
}
/**
* Register an externally managed configuration initialization method.
*/
public void registerExternallyManagedInitMethod(String initMethod) {
synchronized (this.postProcessingLock) {
if (this.externallyManagedInitMethods == null) {
this.externallyManagedInitMethods = new HashSet<>(1);
this.externallyManagedInitMethods = new LinkedHashSet<>(1);
}
this.externallyManagedInitMethods.add(initMethod);
}
}
/**
* Check whether the given method name indicates an externally managed initialization method.
*/
public boolean isExternallyManagedInitMethod(String initMethod) {
synchronized (this.postProcessingLock) {
return (this.externallyManagedInitMethods != null &&
@@ -454,15 +479,33 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
}
}
/**
* Return all externally managed initialization methods (as an immutable Set).
* @since 5.3.11
*/
public Set<String> getExternallyManagedInitMethods() {
synchronized (this.postProcessingLock) {
return (this.externallyManagedInitMethods != null ?
Collections.unmodifiableSet(new LinkedHashSet<>(this.externallyManagedInitMethods)) :
Collections.emptySet());
}
}
/**
* Register an externally managed configuration destruction method.
*/
public void registerExternallyManagedDestroyMethod(String destroyMethod) {
synchronized (this.postProcessingLock) {
if (this.externallyManagedDestroyMethods == null) {
this.externallyManagedDestroyMethods = new HashSet<>(1);
this.externallyManagedDestroyMethods = new LinkedHashSet<>(1);
}
this.externallyManagedDestroyMethods.add(destroyMethod);
}
}
/**
* Check whether the given method name indicates an externally managed destruction method.
*/
public boolean isExternallyManagedDestroyMethod(String destroyMethod) {
synchronized (this.postProcessingLock) {
return (this.externallyManagedDestroyMethods != null &&
@@ -470,6 +513,18 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
}
}
/**
* Return all externally managed destruction methods (as an immutable Set).
* @since 5.3.11
*/
public Set<String> getExternallyManagedDestroyMethods() {
synchronized (this.postProcessingLock) {
return (this.externallyManagedDestroyMethods != null ?
Collections.unmodifiableSet(new LinkedHashSet<>(this.externallyManagedDestroyMethods)) :
Collections.emptySet());
}
}
@Override
public RootBeanDefinition cloneBeanDefinition() {
@@ -39,7 +39,7 @@ import org.springframework.util.xml.XmlValidationModeDetector;
* when starting your JVM. For example, to use the Oracle {@link DocumentBuilder},
* you might start your application like as follows:
*
* <pre code="class">java -Djavax.xml.parsers.DocumentBuilderFactory=oracle.xml.jaxp.JXDocumentBuilderFactory MyMainClass</pre>
* <pre class="code">java -Djavax.xml.parsers.DocumentBuilderFactory=oracle.xml.jaxp.JXDocumentBuilderFactory MyMainClass</pre>
*
* @author Rob Harrop
* @author Juergen Hoeller
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2021 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.
@@ -64,24 +64,24 @@ public final class ParserContext {
}
public final XmlReaderContext getReaderContext() {
public XmlReaderContext getReaderContext() {
return this.readerContext;
}
public final BeanDefinitionRegistry getRegistry() {
public BeanDefinitionRegistry getRegistry() {
return this.readerContext.getRegistry();
}
public final BeanDefinitionParserDelegate getDelegate() {
public BeanDefinitionParserDelegate getDelegate() {
return this.delegate;
}
@Nullable
public final BeanDefinition getContainingBeanDefinition() {
public BeanDefinition getContainingBeanDefinition() {
return this.containingBeanDefinition;
}
public final boolean isNested() {
public boolean isNested() {
return (this.containingBeanDefinition != null);
}
@@ -71,13 +71,13 @@ public class PluggableSchemaResolver implements EntityResolver {
private final String schemaMappingsLocation;
/** Stores the mapping of schema URL -> local schema path. */
/** Stores the mapping of schema URL &rarr; local schema path. */
@Nullable
private volatile Map<String, String> schemaMappings;
/**
* Loads the schema URL -> schema file location mappings using the default
* Loads the schema URL &rarr; schema file location mappings using the default
* mapping file pattern "META-INF/spring.schemas".
* @param classLoader the ClassLoader to use for loading
* (can be {@code null}) to use the default ClassLoader)
@@ -89,7 +89,7 @@ public class PluggableSchemaResolver implements EntityResolver {
}
/**
* Loads the schema URL -> schema file location mappings using the given
* Loads the schema URL &rarr; schema file location mappings using the given
* mapping file pattern.
* @param classLoader the ClassLoader to use for loading
* (can be {@code null}) to use the default ClassLoader)
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2021 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.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.support.security.support;
/**
@@ -27,4 +28,5 @@ public class CustomCallbackBean {
public void destroy() {
System.setProperty("security.destroy", "true");
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2021 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.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.support.security.support;
import org.springframework.beans.factory.DisposableBean;
@@ -26,4 +27,5 @@ public class DestroyBean implements DisposableBean {
public void destroy() throws Exception {
System.setProperty("security.destroy", "true");
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2021 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.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.support.security.support;
/**
@@ -33,4 +34,5 @@ public class FactoryBean {
System.getProperties();
return new Object();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2021 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.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.support.security.support;
import org.springframework.beans.factory.InitializingBean;
@@ -26,4 +27,5 @@ public class InitBean implements InitializingBean {
public void afterPropertiesSet() throws Exception {
System.getProperties();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2021 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.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.support.security.support;
/**
@@ -27,4 +28,5 @@ public class PropertyBean {
public void setProperty(Object property) {
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2021 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.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.testfixture.beans;
/**
@@ -65,4 +66,5 @@ public class DummyBean {
public TestBean getSpouse() {
return spouse;
}
}
@@ -896,7 +896,7 @@ public class MimeMessageHelper {
* <p><b>NOTE:</b> Invoke {@code addInline} <i>after</i> {@link #setText};
* else, mail readers might not be able to resolve inline references correctly.
* @param contentId the content ID to use. Will end up as "Content-ID" header
* in the body part, surrounded by angle brackets: e.g. "myId" -> "&lt;myId&gt;".
* in the body part, surrounded by angle brackets: e.g. "myId" &rarr; "&lt;myId&gt;".
* Can be referenced in HTML source via src="cid:myId" expressions.
* @param dataSource the {@code javax.activation.DataSource} to take
* the content from, determining the InputStream and the content type
@@ -923,7 +923,7 @@ public class MimeMessageHelper {
* <p><b>NOTE:</b> Invoke {@code addInline} <i>after</i> {@link #setText};
* else, mail readers might not be able to resolve inline references correctly.
* @param contentId the content ID to use. Will end up as "Content-ID" header
* in the body part, surrounded by angle brackets: e.g. "myId" -> "&lt;myId&gt;".
* in the body part, surrounded by angle brackets: e.g. "myId" &rarr; "&lt;myId&gt;".
* Can be referenced in HTML source via src="cid:myId" expressions.
* @param file the File resource to take the content from
* @throws MessagingException in case of errors
@@ -950,7 +950,7 @@ public class MimeMessageHelper {
* <p><b>NOTE:</b> Invoke {@code addInline} <i>after</i> {@link #setText};
* else, mail readers might not be able to resolve inline references correctly.
* @param contentId the content ID to use. Will end up as "Content-ID" header
* in the body part, surrounded by angle brackets: e.g. "myId" -> "&lt;myId&gt;".
* in the body part, surrounded by angle brackets: e.g. "myId" &rarr; "&lt;myId&gt;".
* Can be referenced in HTML source via src="cid:myId" expressions.
* @param resource the resource to take the content from
* @throws MessagingException in case of errors
@@ -976,7 +976,7 @@ public class MimeMessageHelper {
* <p><b>NOTE:</b> Invoke {@code addInline} <i>after</i> {@code setText};
* else, mail readers might not be able to resolve inline references correctly.
* @param contentId the content ID to use. Will end up as "Content-ID" header
* in the body part, surrounded by angle brackets: e.g. "myId" -> "&lt;myId&gt;".
* in the body part, surrounded by angle brackets: e.g. "myId" &rarr; "&lt;myId&gt;".
* Can be referenced in HTML source via src="cid:myId" expressions.
* @param inputStreamSource the resource to take the content from
* @param contentType the content type to use for the element
+1 -1
View File
@@ -34,8 +34,8 @@ dependencies {
testImplementation("org.codehaus.groovy:groovy-test")
testImplementation("org.codehaus.groovy:groovy-xml")
testImplementation("org.apache.commons:commons-pool2")
testImplementation("javax.inject:javax.inject-tck")
testImplementation("org.awaitility:awaitility")
testImplementation("javax.inject:javax.inject-tck")
testRuntimeOnly("javax.xml.bind:jaxb-api")
testRuntimeOnly("org.glassfish:javax.el")
// Substitute for javax.management:jmxremote_optional:1.0.1_04 (not available on Maven Central)
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2021 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.
@@ -244,17 +244,21 @@ class AnnotationDrivenCacheBeanDefinitionParser implements BeanDefinitionParser
private static void registerCacheAspect(Element element, ParserContext parserContext) {
if (!parserContext.getRegistry().containsBeanDefinition(CacheManagementConfigUtils.JCACHE_ASPECT_BEAN_NAME)) {
Object eleSource = parserContext.extractSource(element);
RootBeanDefinition def = new RootBeanDefinition();
def.setBeanClassName(JCACHE_ASPECT_CLASS_NAME);
def.setFactoryMethodName("aspectOf");
BeanDefinition sourceDef = createJCacheOperationSourceBeanDefinition(element, eleSource);
String sourceName =
parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
def.getPropertyValues().add("cacheOperationSource", new RuntimeBeanReference(sourceName));
Object source = parserContext.extractSource(element);
parserContext.registerBeanComponent(new BeanComponentDefinition(sourceDef, sourceName));
parserContext.registerBeanComponent(new BeanComponentDefinition(def, CacheManagementConfigUtils.JCACHE_ASPECT_BEAN_NAME));
BeanDefinition cacheOperationSourceDef = createJCacheOperationSourceBeanDefinition(element, source);
String cacheOperationSourceName = parserContext.getReaderContext().registerWithGeneratedName(cacheOperationSourceDef);
RootBeanDefinition jcacheAspectDef = new RootBeanDefinition();
jcacheAspectDef.setBeanClassName(JCACHE_ASPECT_CLASS_NAME);
jcacheAspectDef.setFactoryMethodName("aspectOf");
jcacheAspectDef.getPropertyValues().add("cacheOperationSource", new RuntimeBeanReference(cacheOperationSourceName));
parserContext.getRegistry().registerBeanDefinition(CacheManagementConfigUtils.JCACHE_ASPECT_BEAN_NAME, jcacheAspectDef);
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source);
compositeDef.addNestedComponent(new BeanComponentDefinition(cacheOperationSourceDef, cacheOperationSourceName));
compositeDef.addNestedComponent(new BeanComponentDefinition(jcacheAspectDef, CacheManagementConfigUtils.JCACHE_ASPECT_BEAN_NAME));
parserContext.registerComponent(compositeDef);
}
}
@@ -156,7 +156,7 @@ public class AnnotationBeanNameGenerator implements BeanNameGenerator {
/**
* Derive a default bean name from the given bean definition.
* <p>The default implementation simply builds a decapitalized version
* of the short class name: e.g. "mypackage.MyJdbcDao" -> "myJdbcDao".
* of the short class name: e.g. "mypackage.MyJdbcDao" &rarr; "myJdbcDao".
* <p>Note that inner classes will thus have names of the form
* "outerClassName.InnerClassName", which because of the period in the
* name may be an issue if you are autowiring by name.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@@ -16,6 +16,7 @@
package org.springframework.context.annotation;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
@@ -424,40 +425,38 @@ public class ClassPathScanningCandidateComponentProvider implements EnvironmentC
if (traceEnabled) {
logger.trace("Scanning " + resource);
}
if (resource.isReadable()) {
try {
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
candidates.add(sbd);
}
else {
if (debugEnabled) {
logger.debug("Ignored because not a concrete top-level class: " + resource);
}
try {
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
candidates.add(sbd);
}
else {
if (traceEnabled) {
logger.trace("Ignored because not matching any filter: " + resource);
if (debugEnabled) {
logger.debug("Ignored because not a concrete top-level class: " + resource);
}
}
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to read candidate component class: " + resource, ex);
else {
if (traceEnabled) {
logger.trace("Ignored because not matching any filter: " + resource);
}
}
}
else {
catch (FileNotFoundException ex) {
if (traceEnabled) {
logger.trace("Ignored because not readable: " + resource);
logger.trace("Ignored non-readable " + resource + ": " + ex.getMessage());
}
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to read candidate component class: " + resource, ex);
}
}
}
catch (IOException ex) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@@ -146,22 +146,27 @@ import org.springframework.util.StringValueResolver;
public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor
implements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable {
// Defensive reference to JNDI API for JDK 9+ (optional java.naming module)
private static final boolean jndiPresent = ClassUtils.isPresent(
"javax.naming.InitialContext", CommonAnnotationBeanPostProcessor.class.getClassLoader());
private static final Set<Class<? extends Annotation>> resourceAnnotationTypes = new LinkedHashSet<>(4);
@Nullable
private static final Class<? extends Annotation> webServiceRefClass;
@Nullable
private static final Class<? extends Annotation> ejbClass;
private static final Set<Class<? extends Annotation>> resourceAnnotationTypes = new LinkedHashSet<>(4);
static {
webServiceRefClass = loadAnnotationType("javax.xml.ws.WebServiceRef");
ejbClass = loadAnnotationType("javax.ejb.EJB");
resourceAnnotationTypes.add(Resource.class);
webServiceRefClass = loadAnnotationType("javax.xml.ws.WebServiceRef");
if (webServiceRefClass != null) {
resourceAnnotationTypes.add(webServiceRefClass);
}
ejbClass = loadAnnotationType("javax.ejb.EJB");
if (ejbClass != null) {
resourceAnnotationTypes.add(ejbClass);
}
@@ -174,7 +179,8 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
private boolean alwaysUseJndiLookup = false;
private transient BeanFactory jndiFactory = new SimpleJndiBeanFactory();
@Nullable
private transient BeanFactory jndiFactory;
@Nullable
private transient BeanFactory resourceFactory;
@@ -199,6 +205,11 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
setInitAnnotationType(PostConstruct.class);
setDestroyAnnotationType(PreDestroy.class);
ignoreResourceType("javax.xml.ws.WebServiceContext");
// java.naming module present on JDK 9+?
if (jndiPresent) {
this.jndiFactory = new SimpleJndiBeanFactory();
}
}
@@ -464,6 +475,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
public void releaseTarget(Object target) {
}
};
ProxyFactory pf = new ProxyFactory();
pf.setTargetSource(ts);
if (element.lookupType.isInterface()) {
@@ -484,12 +496,23 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
protected Object getResource(LookupElement element, @Nullable String requestingBeanName)
throws NoSuchBeanDefinitionException {
// JNDI lookup to perform?
String jndiName = null;
if (StringUtils.hasLength(element.mappedName)) {
return this.jndiFactory.getBean(element.mappedName, element.lookupType);
jndiName = element.mappedName;
}
if (this.alwaysUseJndiLookup) {
return this.jndiFactory.getBean(element.name, element.lookupType);
else if (this.alwaysUseJndiLookup) {
jndiName = element.name;
}
if (jndiName != null) {
if (this.jndiFactory == null) {
throw new NoSuchBeanDefinitionException(element.lookupType,
"No JNDI factory configured - specify the 'jndiFactory' property");
}
return this.jndiFactory.getBean(jndiName, element.lookupType);
}
// Regular resource autowiring
if (this.resourceFactory == null) {
throw new NoSuchBeanDefinitionException(element.lookupType,
"No resource factory configured - specify the 'resourceFactory' property");
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@@ -129,7 +129,7 @@ import org.springframework.stereotype.Component;
* &#064;Configuration
* public class AppConfig {
*
* &#064Autowired Environment env;
* &#064;Autowired Environment env;
*
* &#064;Bean
* public MyBean myBean() {
@@ -149,7 +149,7 @@ import org.springframework.stereotype.Component;
* &#064;PropertySource("classpath:/com/acme/app.properties")
* public class AppConfig {
*
* &#064Inject Environment env;
* &#064;Inject Environment env;
*
* &#064;Bean
* public MyBean myBean() {
@@ -170,7 +170,7 @@ import org.springframework.stereotype.Component;
* &#064;PropertySource("classpath:/com/acme/app.properties")
* public class AppConfig {
*
* &#064Value("${bean.name}") String beanName;
* &#064;Value("${bean.name}") String beanName;
*
* &#064;Bean
* public MyBean myBean() {
@@ -297,7 +297,7 @@ import org.springframework.stereotype.Component;
* &#064;ImportResource("classpath:/com/acme/database-config.xml")
* public class AppConfig {
*
* &#064Inject DataSource dataSource; // from XML
* &#064;Inject DataSource dataSource; // from XML
*
* &#064;Bean
* public MyBean myBean() {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2021 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.
@@ -98,7 +98,7 @@ import java.lang.annotation.Target;
* &#064;EnableAspectJAutoProxy
* public class AppConfig {
*
* // no explicit &#064Bean definitions required
* // no explicit &#064;Bean definitions required
* }</pre>
*
* <b>Note: {@code @EnableAspectJAutoProxy} applies to its local application context only,
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@@ -24,6 +24,7 @@ import org.springframework.beans.factory.BeanExpressionException;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.BeanExpressionResolver;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
@@ -156,10 +157,10 @@ public class StandardBeanExpressionResolver implements BeanExpressionResolver {
sec.addPropertyAccessor(new EnvironmentAccessor());
sec.setBeanResolver(new BeanFactoryResolver(evalContext.getBeanFactory()));
sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader()));
ConversionService conversionService = evalContext.getBeanFactory().getConversionService();
if (conversionService != null) {
sec.setTypeConverter(new StandardTypeConverter(conversionService));
}
sec.setTypeConverter(new StandardTypeConverter(() -> {
ConversionService cs = evalContext.getBeanFactory().getConversionService();
return (cs != null ? cs : DefaultConversionService.getSharedInstance());
}));
customizeEvaluationContext(sec);
this.evaluationCache.put(evalContext, sec);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2021 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.
@@ -46,18 +46,18 @@ import org.springframework.lang.Nullable;
*
* def context = new GenericGroovyApplicationContext()
* context.reader.beans {
* dataSource(BasicDataSource) { // <--- invokeMethod
* dataSource(BasicDataSource) { // &lt;--- invokeMethod
* driverClassName = "org.hsqldb.jdbcDriver"
* url = "jdbc:hsqldb:mem:grailsDB"
* username = "sa" // <-- setProperty
* username = "sa" // &lt;-- setProperty
* password = ""
* settings = [mynew:"setting"]
* }
* sessionFactory(SessionFactory) {
* dataSource = dataSource // <-- getProperty for retrieving references
* dataSource = dataSource // &lt;-- getProperty for retrieving references
* }
* myService(MyService) {
* nestedBean = { AnotherBean bean -> // <-- setProperty with closure for nested bean
* nestedBean = { AnotherBean bean -&gt; // &lt;-- setProperty with closure for nested bean
* dataSource = dataSource
* }
* }
@@ -84,7 +84,7 @@ import org.springframework.lang.Nullable;
* dataSource = dataSource
* }
* myService(MyService) {
* nestedBean = { AnotherBean bean ->
* nestedBean = { AnotherBean bean -&gt;
* dataSource = dataSource
* }
* }
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2021 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.
@@ -185,9 +185,9 @@ public class PropertySourcesPlaceholderConfigurer extends PlaceholderConfigurerS
/**
* Implemented for compatibility with
* {@link org.springframework.beans.factory.config.PlaceholderConfigurerSupport}.
* @throws UnsupportedOperationException in this implementation
* @deprecated in favor of
* {@link #processProperties(ConfigurableListableBeanFactory, ConfigurablePropertyResolver)}
* @throws UnsupportedOperationException in this implementation
*/
@Override
@Deprecated
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@@ -229,7 +229,7 @@ public class ReloadableResourceBundleMessageSource extends AbstractResourceBased
* for a Locale, after merging all specified resource bundles.
* Either fetches the holder from the cache or freshly loads it.
* <p>Only used when caching resource bundle contents forever, i.e.
* with cacheSeconds < 0. Therefore, merged properties are always
* with cacheSeconds &lt; 0. Therefore, merged properties are always
* cached forever.
*/
protected PropertiesHolder getMergedProperties(Locale locale) {
@@ -315,7 +315,7 @@ public class ReloadableResourceBundleMessageSource extends AbstractResourceBased
/**
* Calculate the filenames for the given bundle basename and Locale,
* appending language code, country code, and variant code.
* E.g.: basename "messages", Locale "de_AT_oo" -> "messages_de_AT_OO",
* <p>For example, basename "messages", Locale "de_AT_oo" &rarr; "messages_de_AT_OO",
* "messages_de_AT", "messages_de".
* <p>Follows the rules defined by {@link java.util.Locale#toString()}.
* @param basename the basename of the bundle
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2021 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.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.format;
import org.springframework.core.convert.converter.Converter;
@@ -37,7 +37,7 @@ import org.springframework.util.StringValueResolver;
* as {@code DefaultConversionService} exposes its own
* {@link DefaultConversionService#addDefaultConverters addDefaultConverters} method.
*
* <p>Automatically registers formatters for JSR-354 Money & Currency, JSR-310 Date-Time
* <p>Automatically registers formatters for JSR-354 Money &amp; Currency, JSR-310 Date-Time
* and/or Joda-Time 2.x, depending on the presence of the corresponding API on the classpath.
*
* @author Chris Beams
@@ -100,7 +100,7 @@ public class DefaultFormattingConversionService extends FormattingConversionServ
/**
* Add formatters appropriate for most environments: including number formatters,
* JSR-354 Money & Currency formatters, JSR-310 Date-Time and/or Joda-Time formatters,
* JSR-354 Money &amp; Currency formatters, JSR-310 Date-Time and/or Joda-Time formatters,
* depending on the presence of the corresponding API on the classpath.
* @param formatterRegistry the service to register default formatters with
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2021 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.
@@ -44,8 +44,8 @@ public interface JndiCallback<T> {
* <p>Implementations don't need to worry about error handling
* or cleanup, as the JndiTemplate class will handle this.
* @param ctx the current JNDI context
* @throws NamingException if thrown by JNDI methods
* @return a result object, or {@code null}
* @throws NamingException if thrown by JNDI methods
*/
@Nullable
T doInContext(Context ctx) throws NamingException;
@@ -56,7 +56,7 @@ import org.springframework.util.Assert;
* For example:
*
* <pre class="code">&lt;property name="jndiEnvironment"&gt;
* &lt;props>
* &lt;props&gt;
* &lt;prop key="java.naming.factory.initial"&gt;com.sun.jndi.cosnaming.CNCtxFactory&lt;/prop&gt;
* &lt;prop key="java.naming.provider.url"&gt;iiop://localhost:1050&lt;/prop&gt;
* &lt;/props&gt;
@@ -43,7 +43,7 @@ import org.springframework.util.ClassUtils;
* For example:
*
* <pre class="code">&lt;property name="jndiEnvironment"&gt;
* &lt;props>
* &lt;props&gt;
* &lt;prop key="java.naming.factory.initial"&gt;com.sun.jndi.cosnaming.CNCtxFactory&lt;/prop&gt;
* &lt;prop key="java.naming.provider.url"&gt;iiop://localhost:1050&lt;/prop&gt;
* &lt;/props&gt;
@@ -52,7 +52,7 @@ import org.springframework.util.ReflectionUtils;
* For example:
*
* <pre class="code">&lt;property name="jndiEnvironment"&gt;
* &lt;props>
* &lt;props&gt;
* &lt;prop key="java.naming.factory.initial"&gt;com.sun.jndi.cosnaming.CNCtxFactory&lt;/prop&gt;
* &lt;prop key="java.naming.provider.url"&gt;iiop://localhost:1050&lt;/prop&gt;
* &lt;/props&gt;
@@ -75,7 +75,6 @@ public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements B
* handle unexpected exception thrown by asynchronous method executions
* @see AnnotationAsyncExecutionInterceptor#getDefaultExecutor(BeanFactory)
*/
@SuppressWarnings("unchecked")
public AsyncAnnotationAdvisor(
@Nullable Executor executor, @Nullable AsyncUncaughtExceptionHandler exceptionHandler) {
@@ -171,7 +171,6 @@ public final class CronExpression {
* <li>{@code "@daily"} (or {@code "@midnight"}) to run once a day, i.e. {@code "0 0 0 * * *"},</li>
* <li>{@code "@hourly"} to run once an hour, i.e. {@code "0 0 * * * *"}.</li>
* </ul>
*
* @param expression the expression string to parse
* @return the parsed {@code CronExpression} object
* @throws IllegalArgumentException in the expression does not conform to
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2021 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.
@@ -105,11 +105,11 @@ public class CronTrigger implements Trigger {
}
}
else {
date = new Date();
date = new Date(triggerContext.getClock().millis());
}
ZonedDateTime dateTime = ZonedDateTime.ofInstant(date.toInstant(), this.zoneId);
ZonedDateTime next = this.expression.next(dateTime);
return next != null ? Date.from(next.toInstant()) : null;
return (next != null ? Date.from(next.toInstant()) : null);
}
@@ -87,7 +87,7 @@ public class ResourceBundleThemeSource implements HierarchicalThemeSource, BeanC
/**
* Set the prefix that gets applied to the ResourceBundle basenames,
* i.e. the theme names.
* E.g.: basenamePrefix="test.", themeName="theme" -> basename="test.theme".
* E.g.: basenamePrefix="test.", themeName="theme" &rarr; basename="test.theme".
* <p>Note that ResourceBundle names are effectively classpath locations: As a
* consequence, the JDK's standard ResourceBundle treats dots as package separators.
* This means that "test.theme" is effectively equivalent to "test/theme",
@@ -83,8 +83,8 @@ public interface Errors {
* {@code pushNestedPath(String)} call.
* <p>Using the nested path stack allows to set temporary nested paths
* for subobjects without having to worry about a temporary path holder.
* <p>For example: current path "spouse.", pushNestedPath("child") ->
* result path "spouse.child."; popNestedPath() -> "spouse." again.
* <p>For example: current path "spouse.", pushNestedPath("child") &rarr;
* result path "spouse.child."; popNestedPath() &rarr; "spouse." again.
* @param subPath the sub path to push onto the nested path stack
* @see #popNestedPath
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2021 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.
@@ -33,7 +33,7 @@ package org.springframework.validation;
* wholly of whitespace), and that any password that is present is
* at least {@code 'MINIMUM_PASSWORD_LENGTH'} characters in length.
*
* <pre class="code"> public class UserLoginValidator implements Validator {
* <pre class="code">public class UserLoginValidator implements Validator {
*
* private static final int MINIMUM_PASSWORD_LENGTH = 6;
*
@@ -46,7 +46,7 @@ package org.springframework.validation;
* ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "field.required");
* UserLogin login = (UserLogin) target;
* if (login.getPassword() != null
* && login.getPassword().trim().length() < MINIMUM_PASSWORD_LENGTH) {
* &amp;&amp; login.getPassword().trim().length() &lt; MINIMUM_PASSWORD_LENGTH) {
* errors.rejectValue("password", "field.min.length",
* new Object[]{Integer.valueOf(MINIMUM_PASSWORD_LENGTH)},
* "The password must be at least [" + MINIMUM_PASSWORD_LENGTH + "] characters in length.");
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2021 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.
@@ -47,6 +47,7 @@ import org.springframework.util.Assert;
public abstract class FooServiceImpl implements FooService {
// Just to test ASM5's bytecode parsing of INVOKESPECIAL/STATIC on interfaces
@SuppressWarnings("unused")
private static final Comparator<MessageBean> COMPARATOR_BY_MESSAGE = Comparator.comparing(MessageBean::getMessage);
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.aop.aspectj;
import org.aspectj.lang.ProceedingJoinPoint;
@@ -48,7 +48,6 @@ import org.springframework.core.NestedRuntimeException;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.lang.Nullable;
import org.springframework.util.StopWatch;
import static org.assertj.core.api.Assertions.assertThat;
@@ -310,12 +309,6 @@ public class AspectJAutoProxyCreatorTests {
return String.format("%s-%s", getClass().getSimpleName(), fileSuffix);
}
private void assertStopWatchTimeLimit(final StopWatch sw, final long maxTimeMillis) {
long totalTimeMillis = sw.getTotalTimeMillis();
assertThat(totalTimeMillis < maxTimeMillis).as("'" + sw.getLastTaskName() + "' took too long: expected less than<" + maxTimeMillis +
"> ms, actual<" + totalTimeMillis + "> ms.").isTrue();
}
}
@Aspect("pertarget(execution(* *.getSpouse()))")
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@@ -513,6 +513,7 @@ public class CglibProxyTests extends AbstractAopProxyTests implements Serializab
this.name = name;
}
@SuppressWarnings("unused")
public String getName() {
return this.name;
}
@@ -137,6 +137,7 @@ public class AggressiveFactoryBeanInstantiationTests {
static class ExceptionInInitializer {
@SuppressWarnings("unused")
private static final int ERROR = callInClinit();
private static int callInClinit() {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2021 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.
@@ -25,7 +25,6 @@ import org.springframework.beans.testfixture.beans.TestBean;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests cornering the issue reported in SPR-8080. If the product of a @Bean method
* was @Autowired into a configuration class while at the same time the declaring
@@ -34,7 +33,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* 'currently in creation' status of the autowired bean and result in creating multiple
* instances of the given @Bean, violating container scoping / singleton semantics.
*
* This is resolved through no longer relying on 'currently in creation' status, but
* <p>This is resolved through no longer relying on 'currently in creation' status, but
* rather on a thread local that informs the enhanced bean method implementation whether
* the factory is the caller or not.
*
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@@ -1956,6 +1956,7 @@ class ConfigurationClassPostProcessorTests {
}
// Unrelated, not to be considered as a factory method
@SuppressWarnings("unused")
private boolean testBean(boolean param) {
return param;
}
@@ -1985,6 +1986,7 @@ class ConfigurationClassPostProcessorTests {
}
// Unrelated, not to be considered as a factory method
@SuppressWarnings("unused")
private boolean testBean(boolean param) {
return param;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2021 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.
@@ -26,7 +26,6 @@ import org.springframework.context.support.GenericXmlApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Chris Beams
* @author Juergen Hoeller
@@ -47,6 +46,7 @@ public class DestroyMethodInferenceTests {
WithLocalShutdownMethod c7 = ctx.getBean("c7", WithLocalShutdownMethod.class);
WithInheritedCloseMethod c8 = ctx.getBean("c8", WithInheritedCloseMethod.class);
WithDisposableBean c9 = ctx.getBean("c9", WithDisposableBean.class);
WithAutoCloseable c10 = ctx.getBean("c10", WithAutoCloseable.class);
assertThat(c0.closed).as("c0").isFalse();
assertThat(c1.closed).as("c1").isFalse();
@@ -58,6 +58,8 @@ public class DestroyMethodInferenceTests {
assertThat(c7.closed).as("c7").isFalse();
assertThat(c8.closed).as("c8").isFalse();
assertThat(c9.closed).as("c9").isFalse();
assertThat(c10.closed).as("c10").isFalse();
ctx.close();
assertThat(c0.closed).as("c0").isTrue();
assertThat(c1.closed).as("c1").isTrue();
@@ -69,6 +71,7 @@ public class DestroyMethodInferenceTests {
assertThat(c7.closed).as("c7").isTrue();
assertThat(c8.closed).as("c8").isFalse();
assertThat(c9.closed).as("c9").isTrue();
assertThat(c10.closed).as("c10").isTrue();
}
@Test
@@ -80,21 +83,29 @@ public class DestroyMethodInferenceTests {
WithLocalCloseMethod x3 = ctx.getBean("x3", WithLocalCloseMethod.class);
WithNoCloseMethod x4 = ctx.getBean("x4", WithNoCloseMethod.class);
WithInheritedCloseMethod x8 = ctx.getBean("x8", WithInheritedCloseMethod.class);
WithDisposableBean x9 = ctx.getBean("x9", WithDisposableBean.class);
WithAutoCloseable x10 = ctx.getBean("x10", WithAutoCloseable.class);
assertThat(x1.closed).isFalse();
assertThat(x2.closed).isFalse();
assertThat(x3.closed).isFalse();
assertThat(x4.closed).isFalse();
assertThat(x8.closed).isFalse();
assertThat(x9.closed).isFalse();
assertThat(x10.closed).isFalse();
ctx.close();
assertThat(x1.closed).isFalse();
assertThat(x2.closed).isTrue();
assertThat(x3.closed).isTrue();
assertThat(x4.closed).isFalse();
assertThat(x8.closed).isFalse();
assertThat(x9.closed).isTrue();
assertThat(x10.closed).isTrue();
}
@Configuration
@Configuration(proxyBeanMethods = false)
static class Config {
@Bean(destroyMethod = "explicitClose")
@@ -155,6 +166,11 @@ public class DestroyMethodInferenceTests {
public WithDisposableBean c9() {
return new WithDisposableBean();
}
@Bean
public WithAutoCloseable c10() {
return new WithAutoCloseable();
}
}
@@ -189,17 +205,6 @@ public class DestroyMethodInferenceTests {
}
static class WithDisposableBean implements DisposableBean {
boolean closed = false;
@Override
public void destroy() {
closed = true;
}
}
static class WithNoCloseMethod {
boolean closed = false;
@@ -215,4 +220,26 @@ public class DestroyMethodInferenceTests {
}
}
static class WithDisposableBean implements DisposableBean {
boolean closed = false;
@Override
public void destroy() {
closed = true;
}
}
static class WithAutoCloseable implements AutoCloseable {
boolean closed = false;
@Override
public void close() {
closed = true;
}
}
}
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import org.junit.jupiter.api.Test;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2021 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.
@@ -61,7 +61,7 @@ public class ParserStrategyUtilsTests {
@BeforeEach
void setup() {
MockitoAnnotations.initMocks(this);
MockitoAnnotations.openMocks(this);
given(this.resourceLoader.getClassLoader()).willReturn(this.beanClassLoader);
}
@@ -74,6 +74,7 @@ public class Spr12278Tests {
private final String autowiredName;
// No @Autowired - implicit wiring
@SuppressWarnings("unused")
public SingleConstructorComponent(String autowiredName) {
this.autowiredName = autowiredName;
}
@@ -88,11 +89,13 @@ public class Spr12278Tests {
this.name = name;
}
@SuppressWarnings("unused")
public TwoConstructorsComponent() {
this("fallback");
}
}
@SuppressWarnings("unused")
private static class TwoSpecificConstructorsComponent {
private final Integer counter;
@@ -70,6 +70,7 @@ public class Spr16179Tests {
Assembler<Page<String>> assembler2;
@Autowired(required = false)
@SuppressWarnings("rawtypes")
Assembler<Page> assembler3;
@Autowired(required = false)
@@ -42,7 +42,6 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.config.ListFactoryBean;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
@@ -247,7 +246,9 @@ public class ConfigurationClassProcessingTests {
public void configurationWithPostProcessor() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(ConfigWithPostProcessor.class);
RootBeanDefinition placeholderConfigurer = new RootBeanDefinition(PropertyPlaceholderConfigurer.class);
@SuppressWarnings("deprecation")
RootBeanDefinition placeholderConfigurer = new RootBeanDefinition(
org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.class);
placeholderConfigurer.getPropertyValues().add("properties", "myProp=myValue");
ctx.registerBeanDefinition("placeholderConfigurer", placeholderConfigurer);
ctx.refresh();
@@ -536,6 +537,7 @@ public class ConfigurationClassProcessingTests {
String nameSuffix = "-processed-" + myProp;
@SuppressWarnings("unused")
public void setNameSuffix(String nameSuffix) {
this.nameSuffix = nameSuffix;
}
@@ -552,10 +554,6 @@ public class ConfigurationClassProcessingTests {
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
public int getOrder() {
return 0;
}
};
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2021 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.
@@ -25,7 +25,6 @@ import org.junit.jupiter.api.Test;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader;
import org.springframework.beans.testfixture.beans.TestBean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
@@ -166,8 +165,10 @@ public class ImportResourceTests {
}
}
@SuppressWarnings("deprecation")
@Configuration
@ImportResource(locations = "classpath:org/springframework/context/annotation/configuration/ImportNonXmlResourceConfig-context.properties", reader = PropertiesBeanDefinitionReader.class)
@ImportResource(locations = "classpath:org/springframework/context/annotation/configuration/ImportNonXmlResourceConfig-context.properties",
reader = org.springframework.beans.factory.support.PropertiesBeanDefinitionReader.class)
static class ImportNonXmlResourceConfig {
}
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2021 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.
@@ -59,6 +59,7 @@ public class ImportWithConditionTests {
protected static class ConditionalThenUnconditional {
@Autowired
@SuppressWarnings("unused")
private BeanOne beanOne;
}
@@ -68,6 +69,7 @@ public class ImportWithConditionTests {
protected static class UnconditionalThenConditional {
@Autowired
@SuppressWarnings("unused")
private BeanOne beanOne;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2021 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.
@@ -47,6 +47,7 @@ public class ImportedConfigurationClassEnhancementTests {
autowiredConfigClassIsEnhanced(ConfigThatDoesNotImport.class, ConfigToBeAutowired.class);
}
@SuppressWarnings("deprecation")
private void autowiredConfigClassIsEnhanced(Class<?>... configClasses) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(configClasses);
Config config = ctx.getBean(Config.class);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2021 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.
@@ -32,6 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat;
public class Spr7167Tests {
@SuppressWarnings("deprecation")
@Test
public void test() {
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfig.class);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2021 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.
@@ -22,7 +22,6 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
@@ -75,6 +74,7 @@ public class BeanFactoryPostProcessorTests {
}
@Test
@SuppressWarnings("deprecation")
public void testMultipleDefinedBeanFactoryPostProcessors() {
StaticApplicationContext ac = new StaticApplicationContext();
ac.registerSingleton("tb1", TestBean.class);
@@ -84,7 +84,7 @@ public class BeanFactoryPostProcessorTests {
ac.registerSingleton("bfpp1", TestBeanFactoryPostProcessor.class, pvs1);
MutablePropertyValues pvs2 = new MutablePropertyValues();
pvs2.add("properties", "key=value");
ac.registerSingleton("bfpp2", PropertyPlaceholderConfigurer.class, pvs2);
ac.registerSingleton("bfpp2", org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.class, pvs2);
ac.refresh();
TestBeanFactoryPostProcessor bfpp = (TestBeanFactoryPostProcessor) ac.getBean("bfpp1");
assertThat(bfpp.initValue).isEqualTo("value");
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2021 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.
@@ -38,6 +38,7 @@ import static org.mockito.Mockito.mock;
* @author Stephane Nicoll
* @author Sam Brannen
*/
@SuppressWarnings("deprecation")
class LiveBeansViewTests {
private final MockEnvironment environment = new MockEnvironment();
@@ -43,6 +43,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
* @author Sam Brannen
* @see org.springframework.beans.factory.config.PropertyResourceConfigurerTests
*/
@SuppressWarnings("deprecation")
public class PropertyResourceConfigurerIntegrationTests {
@Test
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2021 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.
@@ -46,7 +46,6 @@ import static org.springframework.beans.factory.support.BeanDefinitionBuilder.ro
*/
public class PropertySourcesPlaceholderConfigurerTests {
@Test
public void replacementFromEnvironmentProperties() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
@@ -397,6 +396,7 @@ public class PropertySourcesPlaceholderConfigurerTests {
return name;
}
@SuppressWarnings("unused")
public void setName(Optional<String> name) {
this.name = name;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2021 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,7 +23,6 @@ import java.util.Map;
import org.junit.jupiter.api.Test;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader;
import org.springframework.beans.testfixture.beans.TestBean;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ConfigurableApplicationContext;
@@ -48,6 +47,7 @@ public class StaticApplicationContextMulticasterTests extends AbstractApplicatio
protected StaticApplicationContext sac;
@SuppressWarnings("deprecation")
@Override
protected ConfigurableApplicationContext createContext() throws Exception {
StaticApplicationContext parent = new StaticApplicationContext();
@@ -67,7 +67,8 @@ public class StaticApplicationContextMulticasterTests extends AbstractApplicatio
sac.registerSingleton("beanThatListens", BeanThatListens.class, new MutablePropertyValues());
sac.registerSingleton("aca", ACATester.class, new MutablePropertyValues());
sac.registerPrototype("aca-prototype", ACATester.class, new MutablePropertyValues());
PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader(sac.getDefaultListableBeanFactory());
org.springframework.beans.factory.support.PropertiesBeanDefinitionReader reader =
new org.springframework.beans.factory.support.PropertiesBeanDefinitionReader(sac.getDefaultListableBeanFactory());
Resource resource = new ClassPathResource("testBeans.properties", getClass());
reader.loadBeanDefinitions(new EncodedResource(resource, "ISO-8859-1"));
sac.refresh();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2021 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,7 +23,6 @@ import java.util.Map;
import org.junit.jupiter.api.Test;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader;
import org.springframework.beans.testfixture.beans.TestBean;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.testfixture.AbstractApplicationContextTests;
@@ -40,6 +39,7 @@ public class StaticApplicationContextTests extends AbstractApplicationContextTes
protected StaticApplicationContext sac;
@SuppressWarnings("deprecation")
@Override
protected ConfigurableApplicationContext createContext() throws Exception {
StaticApplicationContext parent = new StaticApplicationContext();
@@ -57,7 +57,8 @@ public class StaticApplicationContextTests extends AbstractApplicationContextTes
sac.registerSingleton("beanThatListens", BeanThatListens.class, new MutablePropertyValues());
sac.registerSingleton("aca", ACATester.class, new MutablePropertyValues());
sac.registerPrototype("aca-prototype", ACATester.class, new MutablePropertyValues());
PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader(sac.getDefaultListableBeanFactory());
org.springframework.beans.factory.support.PropertiesBeanDefinitionReader reader =
new org.springframework.beans.factory.support.PropertiesBeanDefinitionReader(sac.getDefaultListableBeanFactory());
reader.loadBeanDefinitions(new ClassPathResource("testBeans.properties", getClass()));
sac.refresh();
sac.addApplicationListener(listener);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@@ -25,7 +25,6 @@ import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.context.NoSuchMessageException;
@@ -176,6 +175,7 @@ public class StaticMessageSourceTests extends AbstractApplicationContextTests {
sac.getMessage(resolvable4, Locale.US));
}
@SuppressWarnings("deprecation")
@Override
protected ConfigurableApplicationContext createContext() throws Exception {
StaticApplicationContext parent = new StaticApplicationContext();
@@ -197,7 +197,8 @@ public class StaticMessageSourceTests extends AbstractApplicationContextTests {
sac.registerPrototype("aca-prototype", ACATester.class, new MutablePropertyValues());
PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader(sac.getDefaultListableBeanFactory());
org.springframework.beans.factory.support.PropertiesBeanDefinitionReader reader =
new org.springframework.beans.factory.support.PropertiesBeanDefinitionReader(sac.getDefaultListableBeanFactory());
reader.loadBeanDefinitions(new ClassPathResource("testBeans.properties", getClass()));
sac.refresh();
sac.addApplicationListener(listener);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2021 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.
@@ -251,7 +251,7 @@ public class EnableMBeanExportConfigurationTests {
@Bean
@Lazy
public Object notLoadable() throws Exception {
return Class.forName("does.not.exist").newInstance();
return Class.forName("does.not.exist").getDeclaredConstructor().newInstance();
}
}
@@ -15,10 +15,16 @@
class="org.springframework.context.annotation.DestroyMethodInferenceTests.WithInheritedCloseMethod"
destroy-method=""/>
<bean id="x9"
class="org.springframework.context.annotation.DestroyMethodInferenceTests.WithDisposableBean"
destroy-method=""/>
<bean id="x10"
class="org.springframework.context.annotation.DestroyMethodInferenceTests.WithAutoCloseable"/>
<beans default-destroy-method="(inferred)">
<bean id="x3"
class="org.springframework.context.annotation.DestroyMethodInferenceTests$WithLocalCloseMethod"/>
<bean id="x4"
class="org.springframework.context.annotation.DestroyMethodInferenceTests$WithNoCloseMethod"/>
</beans>
+5 -5
View File
@@ -50,21 +50,21 @@ dependencies {
optional("io.reactivex.rxjava3:rxjava")
optional("io.smallrye.reactive:mutiny")
optional("io.netty:netty-buffer")
testImplementation("io.projectreactor:reactor-test")
testImplementation("com.google.code.findbugs:jsr305")
testImplementation("javax.annotation:javax.annotation-api")
testImplementation("javax.xml.bind:jaxb-api")
testImplementation("com.google.code.findbugs:jsr305")
testImplementation("com.fasterxml.woodstox:woodstox-core")
testImplementation("org.xmlunit:xmlunit-assertj")
testImplementation("org.xmlunit:xmlunit-matchers")
testImplementation("io.projectreactor:reactor-test")
testImplementation("io.projectreactor.tools:blockhound")
testFixturesImplementation("io.projectreactor:reactor-test")
testFixturesImplementation("com.google.code.findbugs:jsr305")
testFixturesImplementation("org.junit.platform:junit-platform-launcher")
testFixturesImplementation("org.junit.jupiter:junit-jupiter-api")
testFixturesImplementation("org.junit.jupiter:junit-jupiter-params")
testFixturesImplementation("org.assertj:assertj-core")
testFixturesImplementation("org.xmlunit:xmlunit-assertj")
testFixturesImplementation("io.projectreactor:reactor-test")
}
jar {
@@ -92,7 +92,7 @@ jar {
}
test {
// Make sure the classes dir is used on the test classpath (required by ResourceTests)
// When test fixtures are involved, the JAR is used by default
// Make sure the classes dir is used on the test classpath (required by ResourceTests).
// When test fixtures are involved, the JAR is used by default.
classpath = sourceSets.main.output.classesDirs + classpath - files(jar.archiveFile)
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.codec;
import java.nio.charset.Charset;
@@ -324,7 +324,9 @@ public class ClassReader {
}
outputStream.flush();
if (readCount == 1) {
return data;
// SPRING PATCH: some misbehaving InputStreams return -1 but still write to buffer (gh-27429)
// return data;
// END OF PATCH
}
return outputStream.toByteArray();
} finally {
@@ -63,17 +63,16 @@ public class ReflectUtils {
private static final Method classLoaderDefineClassMethod;
private static final ProtectionDomain PROTECTION_DOMAIN;
private static final Throwable THROWABLE;
private static final ProtectionDomain PROTECTION_DOMAIN;
private static final List<Method> OBJECT_METHODS = new ArrayList<Method>();
static {
Method privateLookupIn;
Method lookupDefineClass;
Method classLoaderDefineClass;
ProtectionDomain protectionDomain;
Throwable throwable = null;
try {
privateLookupIn = (Method) AccessController.doPrivileged(new PrivilegedExceptionAction() {
@@ -102,39 +101,37 @@ public class ReflectUtils {
String.class, byte[].class, Integer.TYPE, Integer.TYPE, ProtectionDomain.class);
}
});
protectionDomain = getProtectionDomain(ReflectUtils.class);
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws Exception {
Method[] methods = Object.class.getDeclaredMethods();
for (Method method : methods) {
if ("finalize".equals(method.getName())
|| (method.getModifiers() & (Modifier.FINAL | Modifier.STATIC)) > 0) {
continue;
}
OBJECT_METHODS.add(method);
}
return null;
}
});
}
catch (Throwable t) {
privateLookupIn = null;
lookupDefineClass = null;
classLoaderDefineClass = null;
protectionDomain = null;
throwable = t;
}
privateLookupInMethod = privateLookupIn;
lookupDefineClassMethod = lookupDefineClass;
classLoaderDefineClassMethod = classLoaderDefineClass;
PROTECTION_DOMAIN = protectionDomain;
THROWABLE = throwable;
PROTECTION_DOMAIN = getProtectionDomain(ReflectUtils.class);
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
Method[] methods = Object.class.getDeclaredMethods();
for (Method method : methods) {
if ("finalize".equals(method.getName())
|| (method.getModifiers() & (Modifier.FINAL | Modifier.STATIC)) > 0) {
continue;
}
OBJECT_METHODS.add(method);
}
return null;
}
});
}
// SPRING PATCH END
private static final String[] CGLIB_PACKAGES = {
"java.lang",
};
private static final String[] CGLIB_PACKAGES = {"java.lang"};
static {
primitives.put("byte", Byte.TYPE);
@@ -499,6 +496,7 @@ public class ReflectUtils {
ProtectionDomain protectionDomain, Class<?> contextClass) throws Exception {
Class c = null;
Throwable t = THROWABLE;
// Preferred option: JDK 9+ Lookup.defineClass API if ClassLoader matches
if (contextClass != null && contextClass.getClassLoader() == loader &&
@@ -516,6 +514,7 @@ public class ReflectUtils {
// in case of plain LinkageError (class already defined)
// or IllegalArgumentException (class in different package):
// fall through to traditional ClassLoader.defineClass below
t = target;
}
catch (Throwable ex) {
throw new CodeGenerationException(ex);
@@ -539,9 +538,11 @@ public class ReflectUtils {
throw new CodeGenerationException(ex.getTargetException());
}
// in case of UnsupportedOperationException, fall through
t = ex.getTargetException();
}
catch (Throwable ex) {
// publicDefineClass method not available -> fall through
t = ex;
}
// Classic option: protected ClassLoader.defineClass method
@@ -562,6 +563,7 @@ public class ReflectUtils {
if (!ex.getClass().getName().endsWith("InaccessibleObjectException")) {
throw new CodeGenerationException(ex);
}
t = ex;
}
}
}
@@ -584,7 +586,7 @@ public class ReflectUtils {
// No defineClass variant available at all?
if (c == null) {
throw new CodeGenerationException(THROWABLE);
throw new CodeGenerationException(t);
}
// Force static initializers to run.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@@ -65,9 +65,9 @@ public interface AttributeAccessor {
* @param computeFunction a function that computes a new value for the attribute
* name; the function must not return a {@code null} value
* @return the existing value or newly computed value for the named attribute
* @since 5.3.3
* @see #getAttribute(String)
* @see #setAttribute(String, Object)
* @since 5.3.3
*/
@SuppressWarnings("unchecked")
default <T> T computeAttribute(String name, Function<String, T> computeFunction) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2021 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.
@@ -169,14 +169,14 @@ public final class CollectionFactory {
* (note: only relevant for {@link EnumSet} creation)
* @param capacity the initial capacity
* @return a new collection instance
* @throws IllegalArgumentException if the supplied {@code collectionType} is
* {@code null}; or if the desired {@code collectionType} is {@link EnumSet} and
* the supplied {@code elementType} is not a subtype of {@link Enum}
* @since 4.1.3
* @see java.util.LinkedHashSet
* @see java.util.ArrayList
* @see java.util.TreeSet
* @see java.util.EnumSet
* @throws IllegalArgumentException if the supplied {@code collectionType} is
* {@code null}; or if the desired {@code collectionType} is {@link EnumSet} and
* the supplied {@code elementType} is not a subtype of {@link Enum}
*/
@SuppressWarnings({"unchecked", "cast"})
public static <E> Collection<E> createCollection(Class<?> collectionType, @Nullable Class<?> elementType, int capacity) {
@@ -285,14 +285,14 @@ public final class CollectionFactory {
* (note: only relevant for {@link EnumMap} creation)
* @param capacity the initial capacity
* @return a new map instance
* @throws IllegalArgumentException if the supplied {@code mapType} is
* {@code null}; or if the desired {@code mapType} is {@link EnumMap} and
* the supplied {@code keyType} is not a subtype of {@link Enum}
* @since 4.1.3
* @see java.util.LinkedHashMap
* @see java.util.TreeMap
* @see org.springframework.util.LinkedMultiValueMap
* @see java.util.EnumMap
* @throws IllegalArgumentException if the supplied {@code mapType} is
* {@code null}; or if the desired {@code mapType} is {@link EnumMap} and
* the supplied {@code keyType} is not a subtype of {@link Enum}
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public static <K, V> Map<K, V> createMap(Class<?> mapType, @Nullable Class<?> keyType, int capacity) {
@@ -310,10 +310,10 @@ public class Constants {
* Convert the given bean property name to a constant name prefix.
* <p>Uses a common naming idiom: turning all lower case characters to
* upper case, and prepending upper case characters with an underscore.
* <p>Example: "imageSize" -> "IMAGE_SIZE"<br>
* Example: "imagesize" -> "IMAGESIZE".<br>
* Example: "ImageSize" -> "_IMAGE_SIZE".<br>
* Example: "IMAGESIZE" -> "_I_M_A_G_E_S_I_Z_E"
* <p>Example: "imageSize" &rarr; "IMAGE_SIZE"<br>
* Example: "imagesize" &rarr; "IMAGESIZE".<br>
* Example: "ImageSize" &rarr; "_IMAGE_SIZE".<br>
* Example: "IMAGESIZE" &rarr; "_I_M_A_G_E_S_I_Z_E"
* @param propertyName the name of the bean property
* @return the corresponding constant name prefix
* @see #getValuesForProperty
@@ -41,15 +41,14 @@ import org.springframework.util.ReflectionUtils;
/**
* A registry of adapters to adapt Reactive Streams {@link Publisher} to/from
* various async/reactive types such as {@code CompletableFuture}, RxJava
* {@code Observable}, and others.
* {@code Flowable}, and others.
*
* <p>By default, depending on classpath availability, adapters are registered
* for Reactor, RxJava 2/3, or RxJava 1 (+ RxJava Reactive Streams bridge),
* {@link CompletableFuture}, Java 9+ {@code Flow.Publisher}, and Kotlin
* Coroutines' {@code Deferred} and {@code Flow}.
* for Reactor, RxJava 3, {@link CompletableFuture}, {@code Flow.Publisher},
* and Kotlin Coroutines' {@code Deferred} and {@code Flow}.
*
* <p><strong>Note:</strong> As of Spring Framework 5.3, support for RxJava 1.x
* is deprecated in favor of RxJava 2 and 3.
* <p><strong>Note:</strong> As of Spring Framework 5.3.11, support for
* RxJava 1.x and 2.x is deprecated in favor of RxJava 3.
*
* @author Rossen Stoyanchev
* @author Sebastien Deleuze
@@ -77,11 +76,11 @@ public class ReactiveAdapterRegistry {
static {
ClassLoader classLoader = ReactiveAdapterRegistry.class.getClassLoader();
reactorPresent = ClassUtils.isPresent("reactor.core.publisher.Flux", classLoader);
flowPublisherPresent = ClassUtils.isPresent("java.util.concurrent.Flow.Publisher", classLoader);
rxjava1Present = ClassUtils.isPresent("rx.Observable", classLoader) &&
ClassUtils.isPresent("rx.RxReactiveStreams", classLoader);
rxjava2Present = ClassUtils.isPresent("io.reactivex.Flowable", classLoader);
rxjava3Present = ClassUtils.isPresent("io.reactivex.rxjava3.core.Flowable", classLoader);
flowPublisherPresent = ClassUtils.isPresent("java.util.concurrent.Flow.Publisher", classLoader);
kotlinCoroutinesPresent = ClassUtils.isPresent("kotlinx.coroutines.reactor.MonoKt", classLoader);
mutinyPresent = ClassUtils.isPresent("io.smallrye.mutiny.Multi", classLoader);
}
@@ -97,29 +96,23 @@ public class ReactiveAdapterRegistry {
// Reactor
if (reactorPresent) {
new ReactorRegistrar().registerAdapters(this);
if (flowPublisherPresent) {
// Java 9+ Flow.Publisher
new ReactorJdkFlowAdapterRegistrar().registerAdapter(this);
}
}
// RxJava1 (deprecated)
// RxJava
if (rxjava1Present) {
new RxJava1Registrar().registerAdapters(this);
}
// RxJava2
if (rxjava2Present) {
new RxJava2Registrar().registerAdapters(this);
}
// RxJava3
if (rxjava3Present) {
new RxJava3Registrar().registerAdapters(this);
}
// Java 9+ Flow.Publisher
if (flowPublisherPresent) {
new ReactorJdkFlowAdapterRegistrar().registerAdapter(this);
}
// If not present, do nothing for the time being...
// We can fall back on "reactive-streams-flow-bridge" (once released)
// Kotlin Coroutines
if (reactorPresent && kotlinCoroutinesPresent) {
new CoroutinesRegistrar().registerAdapters(this);
@@ -223,159 +216,6 @@ public class ReactiveAdapterRegistry {
}
private static class ReactorRegistrar {
void registerAdapters(ReactiveAdapterRegistry registry) {
// Register Flux and Mono before Publisher...
registry.registerReactiveType(
ReactiveTypeDescriptor.singleOptionalValue(Mono.class, Mono::empty),
source -> (Mono<?>) source,
Mono::from
);
registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(Flux.class, Flux::empty),
source -> (Flux<?>) source,
Flux::from);
registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(Publisher.class, Flux::empty),
source -> (Publisher<?>) source,
source -> source);
registry.registerReactiveType(
ReactiveTypeDescriptor.nonDeferredAsyncValue(CompletionStage.class, EmptyCompletableFuture::new),
source -> Mono.fromCompletionStage((CompletionStage<?>) source),
source -> Mono.from(source).toFuture()
);
}
}
private static class RxJava1Registrar {
void registerAdapters(ReactiveAdapterRegistry registry) {
registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(rx.Observable.class, rx.Observable::empty),
source -> RxReactiveStreams.toPublisher((rx.Observable<?>) source),
RxReactiveStreams::toObservable
);
registry.registerReactiveType(
ReactiveTypeDescriptor.singleRequiredValue(rx.Single.class),
source -> RxReactiveStreams.toPublisher((rx.Single<?>) source),
RxReactiveStreams::toSingle
);
registry.registerReactiveType(
ReactiveTypeDescriptor.noValue(rx.Completable.class, rx.Completable::complete),
source -> RxReactiveStreams.toPublisher((rx.Completable) source),
RxReactiveStreams::toCompletable
);
}
}
private static class RxJava2Registrar {
void registerAdapters(ReactiveAdapterRegistry registry) {
registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(io.reactivex.Flowable.class, io.reactivex.Flowable::empty),
source -> (io.reactivex.Flowable<?>) source,
io.reactivex.Flowable::fromPublisher
);
registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(io.reactivex.Observable.class, io.reactivex.Observable::empty),
source -> ((io.reactivex.Observable<?>) source).toFlowable(io.reactivex.BackpressureStrategy.BUFFER),
io.reactivex.Observable::fromPublisher
);
registry.registerReactiveType(
ReactiveTypeDescriptor.singleRequiredValue(io.reactivex.Single.class),
source -> ((io.reactivex.Single<?>) source).toFlowable(),
io.reactivex.Single::fromPublisher
);
registry.registerReactiveType(
ReactiveTypeDescriptor.singleOptionalValue(io.reactivex.Maybe.class, io.reactivex.Maybe::empty),
source -> ((io.reactivex.Maybe<?>) source).toFlowable(),
source -> io.reactivex.Flowable.fromPublisher(source)
.toObservable().singleElement()
);
registry.registerReactiveType(
ReactiveTypeDescriptor.noValue(io.reactivex.Completable.class, io.reactivex.Completable::complete),
source -> ((io.reactivex.Completable) source).toFlowable(),
io.reactivex.Completable::fromPublisher
);
}
}
private static class RxJava3Registrar {
void registerAdapters(ReactiveAdapterRegistry registry) {
registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(
io.reactivex.rxjava3.core.Flowable.class,
io.reactivex.rxjava3.core.Flowable::empty),
source -> (io.reactivex.rxjava3.core.Flowable<?>) source,
io.reactivex.rxjava3.core.Flowable::fromPublisher
);
registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(
io.reactivex.rxjava3.core.Observable.class,
io.reactivex.rxjava3.core.Observable::empty),
source -> ((io.reactivex.rxjava3.core.Observable<?>) source).toFlowable(
io.reactivex.rxjava3.core.BackpressureStrategy.BUFFER),
io.reactivex.rxjava3.core.Observable::fromPublisher
);
registry.registerReactiveType(
ReactiveTypeDescriptor.singleRequiredValue(io.reactivex.rxjava3.core.Single.class),
source -> ((io.reactivex.rxjava3.core.Single<?>) source).toFlowable(),
io.reactivex.rxjava3.core.Single::fromPublisher
);
registry.registerReactiveType(
ReactiveTypeDescriptor.singleOptionalValue(
io.reactivex.rxjava3.core.Maybe.class,
io.reactivex.rxjava3.core.Maybe::empty),
source -> ((io.reactivex.rxjava3.core.Maybe<?>) source).toFlowable(),
io.reactivex.rxjava3.core.Maybe::fromPublisher
);
registry.registerReactiveType(
ReactiveTypeDescriptor.noValue(
io.reactivex.rxjava3.core.Completable.class,
io.reactivex.rxjava3.core.Completable::complete),
source -> ((io.reactivex.rxjava3.core.Completable) source).toFlowable(),
io.reactivex.rxjava3.core.Completable::fromPublisher
);
}
}
private static class ReactorJdkFlowAdapterRegistrar {
void registerAdapter(ReactiveAdapterRegistry registry) {
// TODO: remove reflection when build requires JDK 9+
try {
String publisherName = "java.util.concurrent.Flow.Publisher";
Class<?> publisherClass = ClassUtils.forName(publisherName, getClass().getClassLoader());
String adapterName = "reactor.adapter.JdkFlowAdapter";
Class<?> flowAdapterClass = ClassUtils.forName(adapterName, getClass().getClassLoader());
Method toFluxMethod = flowAdapterClass.getMethod("flowPublisherToFlux", publisherClass);
Method toFlowMethod = flowAdapterClass.getMethod("publisherToFlowPublisher", Publisher.class);
Object emptyFlow = ReflectionUtils.invokeMethod(toFlowMethod, null, Flux.empty());
registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(publisherClass, () -> emptyFlow),
source -> (Publisher<?>) ReflectionUtils.invokeMethod(toFluxMethod, null, source),
publisher -> ReflectionUtils.invokeMethod(toFlowMethod, null, publisher)
);
}
catch (Throwable ex) {
// Ignore
}
}
}
/**
* ReactiveAdapter variant that wraps adapted Publishers as {@link Flux} or
* {@link Mono} depending on {@link ReactiveTypeDescriptor#isMultiValue()}.
@@ -399,6 +239,34 @@ public class ReactiveAdapterRegistry {
}
private static class ReactorRegistrar {
void registerAdapters(ReactiveAdapterRegistry registry) {
// Register Flux and Mono before Publisher...
registry.registerReactiveType(
ReactiveTypeDescriptor.singleOptionalValue(Mono.class, Mono::empty),
source -> (Mono<?>) source,
Mono::from);
registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(Flux.class, Flux::empty),
source -> (Flux<?>) source,
Flux::from);
registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(Publisher.class, Flux::empty),
source -> (Publisher<?>) source,
source -> source);
registry.registerReactiveType(
ReactiveTypeDescriptor.nonDeferredAsyncValue(CompletionStage.class, EmptyCompletableFuture::new),
source -> Mono.fromCompletionStage((CompletionStage<?>) source),
source -> Mono.from(source).toFuture());
}
}
private static class EmptyCompletableFuture<T> extends CompletableFuture<T> {
EmptyCompletableFuture() {
@@ -407,6 +275,127 @@ public class ReactiveAdapterRegistry {
}
private static class ReactorJdkFlowAdapterRegistrar {
void registerAdapter(ReactiveAdapterRegistry registry) {
// Reflectively access optional JDK 9+ API (for runtime compatibility with JDK 8)
try {
String publisherName = "java.util.concurrent.Flow.Publisher";
Class<?> publisherClass = ClassUtils.forName(publisherName, getClass().getClassLoader());
String adapterName = "reactor.adapter.JdkFlowAdapter";
Class<?> flowAdapterClass = ClassUtils.forName(adapterName, getClass().getClassLoader());
Method toFluxMethod = flowAdapterClass.getMethod("flowPublisherToFlux", publisherClass);
Method toFlowMethod = flowAdapterClass.getMethod("publisherToFlowPublisher", Publisher.class);
Object emptyFlow = ReflectionUtils.invokeMethod(toFlowMethod, null, Flux.empty());
registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(publisherClass, () -> emptyFlow),
source -> (Publisher<?>) ReflectionUtils.invokeMethod(toFluxMethod, null, source),
publisher -> ReflectionUtils.invokeMethod(toFlowMethod, null, publisher));
}
catch (Throwable ex) {
// Ignore
}
}
}
private static class RxJava1Registrar {
void registerAdapters(ReactiveAdapterRegistry registry) {
registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(rx.Observable.class, rx.Observable::empty),
source -> RxReactiveStreams.toPublisher((rx.Observable<?>) source),
RxReactiveStreams::toObservable);
registry.registerReactiveType(
ReactiveTypeDescriptor.singleRequiredValue(rx.Single.class),
source -> RxReactiveStreams.toPublisher((rx.Single<?>) source),
RxReactiveStreams::toSingle);
registry.registerReactiveType(
ReactiveTypeDescriptor.noValue(rx.Completable.class, rx.Completable::complete),
source -> RxReactiveStreams.toPublisher((rx.Completable) source),
RxReactiveStreams::toCompletable);
}
}
private static class RxJava2Registrar {
void registerAdapters(ReactiveAdapterRegistry registry) {
registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(io.reactivex.Flowable.class, io.reactivex.Flowable::empty),
source -> (io.reactivex.Flowable<?>) source,
io.reactivex.Flowable::fromPublisher);
registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(io.reactivex.Observable.class, io.reactivex.Observable::empty),
source -> ((io.reactivex.Observable<?>) source).toFlowable(io.reactivex.BackpressureStrategy.BUFFER),
io.reactivex.Observable::fromPublisher);
registry.registerReactiveType(
ReactiveTypeDescriptor.singleRequiredValue(io.reactivex.Single.class),
source -> ((io.reactivex.Single<?>) source).toFlowable(),
io.reactivex.Single::fromPublisher);
registry.registerReactiveType(
ReactiveTypeDescriptor.singleOptionalValue(io.reactivex.Maybe.class, io.reactivex.Maybe::empty),
source -> ((io.reactivex.Maybe<?>) source).toFlowable(),
source -> io.reactivex.Flowable.fromPublisher(source)
.toObservable().singleElement());
registry.registerReactiveType(
ReactiveTypeDescriptor.noValue(io.reactivex.Completable.class, io.reactivex.Completable::complete),
source -> ((io.reactivex.Completable) source).toFlowable(),
io.reactivex.Completable::fromPublisher);
}
}
private static class RxJava3Registrar {
void registerAdapters(ReactiveAdapterRegistry registry) {
registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(
io.reactivex.rxjava3.core.Flowable.class,
io.reactivex.rxjava3.core.Flowable::empty),
source -> (io.reactivex.rxjava3.core.Flowable<?>) source,
io.reactivex.rxjava3.core.Flowable::fromPublisher);
registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(
io.reactivex.rxjava3.core.Observable.class,
io.reactivex.rxjava3.core.Observable::empty),
source -> ((io.reactivex.rxjava3.core.Observable<?>) source).toFlowable(
io.reactivex.rxjava3.core.BackpressureStrategy.BUFFER),
io.reactivex.rxjava3.core.Observable::fromPublisher);
registry.registerReactiveType(
ReactiveTypeDescriptor.singleRequiredValue(io.reactivex.rxjava3.core.Single.class),
source -> ((io.reactivex.rxjava3.core.Single<?>) source).toFlowable(),
io.reactivex.rxjava3.core.Single::fromPublisher);
registry.registerReactiveType(
ReactiveTypeDescriptor.singleOptionalValue(
io.reactivex.rxjava3.core.Maybe.class,
io.reactivex.rxjava3.core.Maybe::empty),
source -> ((io.reactivex.rxjava3.core.Maybe<?>) source).toFlowable(),
io.reactivex.rxjava3.core.Maybe::fromPublisher);
registry.registerReactiveType(
ReactiveTypeDescriptor.noValue(
io.reactivex.rxjava3.core.Completable.class,
io.reactivex.rxjava3.core.Completable::complete),
source -> ((io.reactivex.rxjava3.core.Completable) source).toFlowable(),
io.reactivex.rxjava3.core.Completable::fromPublisher);
}
}
private static class CoroutinesRegistrar {
@SuppressWarnings("KotlinInternalInJava")
@@ -420,8 +409,7 @@ public class ReactiveAdapterRegistry {
registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(kotlinx.coroutines.flow.Flow.class, kotlinx.coroutines.flow.FlowKt::emptyFlow),
source -> kotlinx.coroutines.reactor.ReactorFlowKt.asFlux((kotlinx.coroutines.flow.Flow<?>) source),
kotlinx.coroutines.reactive.ReactiveFlowKt::asFlow
);
kotlinx.coroutines.reactive.ReactiveFlowKt::asFlow);
}
}
@@ -434,16 +422,14 @@ public class ReactiveAdapterRegistry {
io.smallrye.mutiny.Uni.class,
() -> io.smallrye.mutiny.Uni.createFrom().nothing()),
uni -> ((io.smallrye.mutiny.Uni<?>) uni).convert().toPublisher(),
publisher -> io.smallrye.mutiny.Uni.createFrom().publisher(publisher)
);
publisher -> io.smallrye.mutiny.Uni.createFrom().publisher(publisher));
registry.registerReactiveType(
ReactiveTypeDescriptor.multiValue(
io.smallrye.mutiny.Multi.class,
() -> io.smallrye.mutiny.Multi.createFrom().empty()),
multi -> (io.smallrye.mutiny.Multi<?>) multi,
publisher -> io.smallrye.mutiny.Multi.createFrom().publisher(publisher)
);
publisher -> io.smallrye.mutiny.Multi.createFrom().publisher(publisher));
}
}
@@ -461,7 +447,6 @@ public class ReactiveAdapterRegistry {
@Override
public void applyTo(BlockHound.Builder builder) {
// Avoid hard references potentially anywhere in spring-core (no need for structural dependency)
builder.allowBlockingCallsInside(
@@ -91,7 +91,6 @@ public interface SmartClassLoader {
* not being possible (thrown by the default implementation in this interface)
* @since 5.3.4
* @see ClassLoader#defineClass(String, byte[], int, int, ProtectionDomain)
* @see java.lang.invoke.MethodHandles.Lookup#defineClass(byte[])
*/
default Class<?> publicDefineClass(String name, byte[] b, @Nullable ProtectionDomain protectionDomain) {
throw new UnsupportedOperationException();

Some files were not shown because too many files have changed in this diff Show More