Compare commits

..

1 Commits

Author SHA1 Message Date
Spring Builds 379e1f22ee Release v6.1.1 2023-11-23 08:51:35 +00:00
547 changed files with 6645 additions and 10504 deletions
+36
View File
@@ -0,0 +1,36 @@
Juergen Hoeller <jhoeller@vmware.com>
Juergen Hoeller <jhoeller@vmware.com> <jhoeller@pivotal.io>
Juergen Hoeller <jhoeller@vmware.com> <jhoeller@gopivotal.com>
Rossen Stoyanchev <rstoyanchev@vmware.com>
Rossen Stoyanchev <rstoyanchev@vmware.com> <rstoyanchev@pivotal.io>
Rossen Stoyanchev <rstoyanchev@vmware.com> <rstoyanchev@gopivotal.com>
Phillip Webb <pwebb@vmware.com>
Phillip Webb <pwebb@vmware.com> <pwebb@pivotal.io>
Phillip Webb <pwebb@vmware.com> <pwebb@gopivotal.com>
Chris Beams <cbeams@vmware.com>
Chris Beams <cbeams@vmware.com> <cbeams@pivotal.io>
Chris Beams <cbeams@vmware.com> <cbeams@gopivotal.com>
Arjen Poutsma <poutsmaa@vmware.com>
Arjen Poutsma <poutsmaa@vmware.com> <apoutsma@pivotal.io>
Arjen Poutsma <poutsmaa@vmware.com> <apoutsma@gopivotal.com>
Arjen Poutsma <poutsmaa@vmware.com> <poutsma@mac.com>
Arjen Poutsma <poutsmaa@vmware.com> <apoutsma@vmware.com>
Oliver Drotbohm <odrotbohm@vmware.com>
Oliver Drotbohm <odrotbohm@vmware.com> <ogierke@vmware.com>
Oliver Drotbohm <odrotbohm@vmware.com> <ogierke@pivotal.io>
Oliver Drotbohm <odrotbohm@vmware.com> <ogierke@gopivotal.com>
Dave Syer <dsyer@vmware.com>
Dave Syer <dsyer@vmware.com> <dsyer@pivotal.io>
Dave Syer <dsyer@vmware.com> <dsyer@gopivotal.com>
Dave Syer <dsyer@vmware.com> <david_syer@hotmail.com>
Andy Clement <aclement@vmware.com>
Andy Clement <aclement@vmware.com> <aclement@pivotal.io>
Andy Clement <aclement@vmware.com> <aclement@gopivotal.com>
Andy Clement <aclement@vmware.com> <andrew.clement@gmail.com>
Sam Brannen <sbrannen@vmware.com>
Sam Brannen <sbrannen@vmware.com> <sbrannen@pivotal.io>
Sam Brannen <sbrannen@vmware.com> <sam@sambrannen.com>
Simon Basle <sbasle@vmware.com>
Simon Baslé <sbasle@vmware.com>
<dmitry.katsubo@gmail.com> <dmitry.katsubo@gmai.com>
Nick Williams <nicholas@nicholaswilliams.net>
+1 -1
View File
@@ -1,4 +1,4 @@
# <img src="framework-docs/src/docs/spring-framework.png" width="80" height="80"> Spring Framework [![Build Status](https://ci.spring.io/api/v1/teams/spring-framework/pipelines/spring-framework-6.1.x/jobs/build/badge)](https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-6.1.x?groups=Build") [![Revved up by Gradle Enterprise](https://img.shields.io/badge/Revved%20up%20by-Gradle%20Enterprise-06A0CE?logo=Gradle&labelColor=02303A)](https://ge.spring.io/scans?search.rootProjectNames=spring)
# <img src="framework-docs/src/docs/spring-framework.png" width="80" height="80"> Spring Framework [![Build Status](https://ci.spring.io/api/v1/teams/spring-framework/pipelines/spring-framework-6.0.x/jobs/build/badge)](https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-6.0.x?groups=Build") [![Revved up by Gradle Enterprise](https://img.shields.io/badge/Revved%20up%20by-Gradle%20Enterprise-06A0CE?logo=Gradle&labelColor=02303A)](https://ge.spring.io/scans?search.rootProjectNames=spring)
This is the home of the Spring Framework: the foundation for all [Spring projects](https://spring.io/projects). Collectively the Spring Framework and the family of Spring projects are often referred to simply as "Spring".
+5 -2
View File
@@ -16,8 +16,6 @@ ext {
javaProjects = subprojects.findAll { !it.name.startsWith("framework-") }
}
description = "Spring Framework"
configure(allprojects) { project ->
apply plugin: "org.springframework.build.localdev"
group = "org.springframework"
@@ -118,3 +116,8 @@ configure([rootProject] + javaProjects) { project ->
configure(moduleProjects) { project ->
apply from: "${rootDir}/gradle/spring-module.gradle"
}
configure(rootProject) {
description = "Spring Framework"
apply plugin: 'org.springframework.build.api-diff'
}
+15
View File
@@ -22,6 +22,21 @@ but doesn't affect the classpath of dependent projects.
This plugin does not provide a `provided` configuration, as the native `compileOnly` and `testCompileOnly`
configurations are preferred.
### API Diff
This plugin uses the [Gradle JApiCmp](https://github.com/melix/japicmp-gradle-plugin) plugin
to generate API Diff reports for each Spring Framework module. This plugin is applied once on the root
project and creates tasks in each framework module. Unlike previous versions of this part of the build,
there is no need for checking out a specific tag. The plugin will fetch the JARs we want to compare the
current working version with. You can generate the reports for all modules or a single module:
```
./gradlew apiDiff -PbaselineVersion=5.1.0.RELEASE
./gradlew :spring-core:apiDiff -PbaselineVersion=5.1.0.RELEASE
```
The reports are located under `build/reports/api-diff/$OLDVERSION_to_$NEWVERSION/`.
### RuntimeHints Java Agent
+6 -1
View File
@@ -21,13 +21,18 @@ dependencies {
checkstyle "io.spring.javaformat:spring-javaformat-checkstyle:${javaFormatVersion}"
implementation "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}"
implementation "org.jetbrains.kotlin:kotlin-compiler-embeddable:${kotlinVersion}"
implementation "org.gradle:test-retry-gradle-plugin:1.5.6"
implementation "me.champeau.gradle:japicmp-gradle-plugin:0.3.0"
implementation "org.gradle:test-retry-gradle-plugin:1.4.1"
implementation "io.spring.javaformat:spring-javaformat-gradle-plugin:${javaFormatVersion}"
implementation "io.spring.nohttp:nohttp-gradle:0.0.11"
}
gradlePlugin {
plugins {
apiDiffPlugin {
id = "org.springframework.build.api-diff"
implementationClass = "org.springframework.build.api.ApiDiffPlugin"
}
conventionsPlugin {
id = "org.springframework.build.conventions"
implementationClass = "org.springframework.build.ConventionsPlugin"
@@ -0,0 +1,142 @@
/*
* Copyright 2002-2023 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.build.api;
import java.io.File;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import me.champeau.gradle.japicmp.JapicmpPlugin;
import me.champeau.gradle.japicmp.JapicmpTask;
import org.gradle.api.GradleException;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.jvm.tasks.Jar;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* {@link Plugin} that applies the {@code "japicmp-gradle-plugin"}
* and create tasks for all subprojects named {@code "spring-*"}, diffing the public API one by one
* and creating the reports in {@code "build/reports/api-diff/$OLDVERSION_to_$NEWVERSION/"}.
* <p>{@code "./gradlew apiDiff -PbaselineVersion=5.1.0.RELEASE"} will output the
* reports for the API diff between the baseline version and the current one for all modules.
* You can limit the report to a single module with
* {@code "./gradlew :spring-core:apiDiff -PbaselineVersion=5.1.0.RELEASE"}.
*
* @author Brian Clozel
*/
public class ApiDiffPlugin implements Plugin<Project> {
private static final Logger logger = LoggerFactory.getLogger(ApiDiffPlugin.class);
public static final String TASK_NAME = "apiDiff";
private static final String BASELINE_VERSION_PROPERTY = "baselineVersion";
private static final List<String> PACKAGE_INCLUDES = Collections.singletonList("org.springframework.*");
private static final URI SPRING_MILESTONE_REPOSITORY = URI.create("https://repo.spring.io/milestone");
@Override
public void apply(Project project) {
if (project.hasProperty(BASELINE_VERSION_PROPERTY) && project.equals(project.getRootProject())) {
project.getPluginManager().apply(JapicmpPlugin.class);
project.getPlugins().withType(JapicmpPlugin.class,
plugin -> applyApiDiffConventions(project));
}
}
private void applyApiDiffConventions(Project project) {
String baselineVersion = project.property(BASELINE_VERSION_PROPERTY).toString();
project.subprojects(subProject -> {
if (subProject.getName().startsWith("spring-")) {
createApiDiffTask(baselineVersion, subProject);
}
});
}
private void createApiDiffTask(String baselineVersion, Project project) {
if (isProjectEligible(project)) {
// Add Spring Milestone repository for generating diffs against previous milestones
project.getRootProject()
.getRepositories()
.maven(mavenArtifactRepository -> mavenArtifactRepository.setUrl(SPRING_MILESTONE_REPOSITORY));
JapicmpTask apiDiff = project.getTasks().create(TASK_NAME, JapicmpTask.class);
apiDiff.setDescription("Generates an API diff report with japicmp");
apiDiff.setGroup(JavaBasePlugin.DOCUMENTATION_GROUP);
apiDiff.setOldClasspath(createBaselineConfiguration(baselineVersion, project));
TaskProvider<Jar> jar = project.getTasks().withType(Jar.class).named("jar");
apiDiff.setNewArchives(project.getLayout().files(jar.get().getArchiveFile().get().getAsFile()));
apiDiff.setNewClasspath(getRuntimeClassPath(project));
apiDiff.setPackageIncludes(PACKAGE_INCLUDES);
apiDiff.setOnlyModified(true);
apiDiff.setIgnoreMissingClasses(true);
// Ignore Kotlin metadata annotations since they contain
// illegal HTML characters and fail the report generation
apiDiff.setAnnotationExcludes(Collections.singletonList("@kotlin.Metadata"));
apiDiff.setHtmlOutputFile(getOutputFile(baselineVersion, project));
apiDiff.dependsOn(project.getTasks().getByName("jar"));
}
}
private boolean isProjectEligible(Project project) {
return project.getPlugins().hasPlugin(JavaPlugin.class)
&& project.getPlugins().hasPlugin(MavenPublishPlugin.class);
}
private Configuration createBaselineConfiguration(String baselineVersion, Project project) {
String baseline = String.join(":",
project.getGroup().toString(), project.getName(), baselineVersion);
Dependency baselineDependency = project.getDependencies().create(baseline + "@jar");
Configuration baselineConfiguration = project.getRootProject().getConfigurations().detachedConfiguration(baselineDependency);
try {
// eagerly resolve the baseline configuration to check whether this is a new Spring module
baselineConfiguration.resolve();
return baselineConfiguration;
}
catch (GradleException exception) {
logger.warn("Could not resolve {} - assuming this is a new Spring module.", baseline);
}
return project.getRootProject().getConfigurations().detachedConfiguration();
}
private Configuration getRuntimeClassPath(Project project) {
return project.getConfigurations().getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME);
}
private File getOutputFile(String baseLineVersion, Project project) {
String buildDirectoryPath = project.getRootProject()
.getLayout().getBuildDirectory().getAsFile().get().getAbsolutePath();
Path outDir = Paths.get(buildDirectoryPath, "reports", "api-diff",
baseLineVersion + "_to_" + project.getRootProject().getVersion());
return project.file(outDir.resolve(project.getName() + ".html").toString());
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
FROM ubuntu:jammy-20231128
FROM ubuntu:jammy-20231004
ADD setup.sh /setup.sh
ADD get-jdk-url.sh /get-jdk-url.sh
+1 -1
View File
@@ -9,7 +9,7 @@ case "$1" in
echo "https://download.bell-sw.com/java/21.0.1+12/bellsoft-jdk21.0.1+12-linux-amd64.tar.gz"
;;
java22)
echo "https://download.java.net/java/early_access/jdk22/27/GPL/openjdk-22-ea+27_linux-x64_bin.tar.gz"
echo "https://download.java.net/java/early_access/jdk22/19/GPL/openjdk-22-ea+19_linux-x64_bin.tar.gz"
;;
*)
echo $"Unknown java version"
+1 -1
View File
@@ -27,7 +27,7 @@ javadoc {
author = true
header = rootProject.description
use = true
overview = project.relativePath("$rootProject.rootDir/framework-docs/src/docs/api/overview.html")
overview = "$rootProject.rootDir/framework-docs/src/docs/api/overview.html"
destinationDir = file("${project.buildDir}/docs/javadoc-api")
splitIndex = true
links(rootProject.ext.javadocLinks)
@@ -156,7 +156,6 @@ Java::
/**
* Bean definitions for {@link DataSourceConfiguration}
*/
@Generated
public class DataSourceConfiguration__BeanDefinitions {
/**
* Get the bean definition for 'dataSourceConfiguration'
@@ -191,9 +190,6 @@ Java::
NOTE: The exact code generated may differ depending on the exact nature of your bean definitions.
TIP: Each generated class is annotated with `org.springframework.aot.generate.Generated` to
identify them if they need to be excluded, for instance by static analysis tools.
The generated code above creates bean definitions equivalent to the `@Configuration` class, but in a direct way and without the use of reflection if at all possible.
There is a bean definition for `dataSourceConfiguration` and one for `dataSourceBean`.
When a `datasource` instance is required, a `BeanInstanceSupplier` is called.
@@ -516,8 +516,8 @@ as the following example shows:
[[beans-definition-profiles-default]]
=== Default Profile
The default profile represents the profile that is enabled if no profile is active. Consider
the following example:
The default profile represents the profile that is enabled by default. Consider the
following example:
[tabs]
======
@@ -558,9 +558,9 @@ Kotlin::
----
======
If xref:#beans-definition-profiles-enable[no profile is active], the `dataSource` is
created. You can see this as a way to provide a default definition for one or more
beans. If any profile is enabled, the default profile does not apply.
If no profile is active, the `dataSource` is created. You can see this
as a way to provide a default definition for one or more beans. If any
profile is enabled, the default profile does not apply.
The name of the default profile is `default`. You can change the name of
the default profile by using `setDefaultProfiles()` on the `Environment` or,
@@ -1,15 +1,15 @@
[[beans-introduction]]
= Introduction to the Spring IoC Container and Beans
This chapter covers the Spring Framework implementation of the Inversion of Control (IoC)
principle. Dependency injection (DI) is a specialized form of IoC, whereby objects define
their dependencies (that is, the other objects they work with) only through constructor
arguments, arguments to a factory method, or properties that are set on the object
instance after it is constructed or returned from a factory method. The IoC container
This chapter covers the Spring Framework implementation of the Inversion of Control
(IoC) principle. IoC is also known as dependency injection (DI). It is a process whereby
objects define their dependencies (that is, the other objects they work with) only through
constructor arguments, arguments to a factory method, or properties that are set on the
object instance after it is constructed or returned from a factory method. The container
then injects those dependencies when it creates the bean. This process is fundamentally
the inverse (hence the name, Inversion of Control) of the bean itself controlling the
instantiation or location of its dependencies by using direct construction of classes or
a mechanism such as the Service Locator pattern.
the inverse (hence the name, Inversion of Control) of the bean itself
controlling the instantiation or location of its dependencies by using direct
construction of classes or a mechanism such as the Service Locator pattern.
The `org.springframework.beans` and `org.springframework.context` packages are the basis
for Spring Framework's IoC container. The
@@ -3,5 +3,17 @@
:page-section-summary-toc: 1
This section covers how to use annotations in your Java code to configure the Spring
container.
container. It includes the following topics:
* xref:core/beans/java/basic-concepts.adoc[Basic Concepts: `@Bean` and `@Configuration`]
* xref:core/beans/java/instantiating-container.adoc[Instantiating the Spring Container by Using `AnnotationConfigApplicationContext`]
* xref:core/beans/java/bean-annotation.adoc[Using the `@Bean` Annotation]
* xref:core/beans/java/configuration-annotation.adoc[Using the `@Configuration` annotation]
* xref:core/beans/java/composing-configuration-classes.adoc[Composing Java-based Configurations]
* xref:core/beans/environment.adoc#beans-definition-profiles[Bean Definition Profiles]
* xref:core/beans/environment.adoc#beans-property-source-abstraction[`PropertySource` Abstraction]
* xref:core/beans/environment.adoc#beans-using-propertysource[Using `@PropertySource`]
* xref:core/beans/environment.adoc#beans-placeholder-resolution-in-statements[Placeholder Resolution in Statements]
@@ -2,4 +2,24 @@
= Language Reference
:page-section-summary-toc: 1
This section describes how the Spring Expression Language works.
This section describes how the Spring Expression Language works. It covers the following
topics:
* xref:core/expressions/language-ref/literal.adoc[Literal Expressions]
* xref:core/expressions/language-ref/properties-arrays.adoc[Properties, Arrays, Lists, Maps, and Indexers]
* xref:core/expressions/language-ref/inline-lists.adoc[Inline Lists]
* xref:core/expressions/language-ref/inline-maps.adoc[Inline Maps]
* xref:core/expressions/language-ref/array-construction.adoc[Array Construction]
* xref:core/expressions/language-ref/methods.adoc[Methods]
* xref:core/expressions/language-ref/operators.adoc[Operators]
* xref:core/expressions/language-ref/types.adoc[Types]
* xref:core/expressions/language-ref/constructors.adoc[Constructors]
* xref:core/expressions/language-ref/variables.adoc[Variables]
* xref:core/expressions/language-ref/functions.adoc[User-Defined Functions]
* xref:core/expressions/language-ref/bean-references.adoc[Bean References]
* xref:core/expressions/language-ref/operator-ternary.adoc[Ternary Operator (If-Then-Else)]
* xref:core/expressions/language-ref/operator-elvis.adoc[The Elvis Operator]
* xref:core/expressions/language-ref/operator-safe-navigation.adoc[Safe Navigation Operator]
@@ -1,8 +1,8 @@
[[expressions-ref-variables]]
= Variables
You can reference variables in an expression by using the `#variableName` syntax. Variables
are set by using the `setVariable()` method in `EvaluationContext` implementations.
You can reference variables in the expression by using the `#variableName` syntax. Variables
are set by using the `setVariable` method on `EvaluationContext` implementations.
[NOTE]
====
@@ -29,7 +29,7 @@ Java::
context.setVariable("newName", "Mike Tesla");
parser.parseExpression("name = #newName").getValue(context, tesla);
System.out.println(tesla.getName()); // "Mike Tesla"
System.out.println(tesla.getName()) // "Mike Tesla"
----
Kotlin::
@@ -53,10 +53,8 @@ Kotlin::
The `#this` variable is always defined and refers to the current evaluation object
(against which unqualified references are resolved). The `#root` variable is always
defined and refers to the root context object. Although `#this` may vary as components of
an expression are evaluated, `#root` always refers to the root.
The following example shows how to use the `#this` variable in conjunction with
xref:core/expressions/language-ref/collection-selection.adoc[collection selection].
an expression are evaluated, `#root` always refers to the root. The following examples
show how to use the `#this` and `#root` variables:
[tabs]
======
@@ -64,95 +62,40 @@ Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
// Create a list of prime integers.
List<Integer> primes = List.of(2, 3, 5, 7, 11, 13, 17);
// create an array of integers
List<Integer> primes = new ArrayList<>();
primes.addAll(Arrays.asList(2,3,5,7,11,13,17));
// Create parser and set variable 'primes' as the list of integers.
// create parser and set variable 'primes' as the array of integers
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataAccess();
context.setVariable("primes", primes);
// Select all prime numbers > 10 from the list (using selection ?{...}).
String expression = "#primes.?[#this > 10]";
// Evaluates to a list containing [11, 13, 17].
List<Integer> primesGreaterThanTen =
parser.parseExpression(expression).getValue(context, List.class);
// all prime numbers > 10 from the list (using selection ?{...})
// evaluates to [11, 13, 17]
List<Integer> primesGreaterThanTen = (List<Integer>) parser.parseExpression(
"#primes.?[#this>10]").getValue(context);
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
// Create a list of prime integers.
val primes = listOf(2, 3, 5, 7, 11, 13, 17)
// create an array of integers
val primes = ArrayList<Int>()
primes.addAll(listOf(2, 3, 5, 7, 11, 13, 17))
// Create parser and set variable 'primes' as the list of integers.
// create parser and set variable 'primes' as the array of integers
val parser = SpelExpressionParser()
val context = SimpleEvaluationContext.forReadWriteDataBinding().build()
val context = SimpleEvaluationContext.forReadOnlyDataAccess()
context.setVariable("primes", primes)
// Select all prime numbers > 10 from the list (using selection ?{...}).
val expression = "#primes.?[#this > 10]"
// Evaluates to a list containing [11, 13, 17].
val primesGreaterThanTen = parser.parseExpression(expression)
.getValue(context) as List<Int>
// all prime numbers > 10 from the list (using selection ?{...})
// evaluates to [11, 13, 17]
val primesGreaterThanTen = parser.parseExpression(
"#primes.?[#this>10]").getValue(context) as List<Int>
----
======
The following example shows how to use the `#this` and `#root` variables together in
conjunction with
xref:core/expressions/language-ref/collection-projection.adoc[collection projection].
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
// Create parser and evaluation context.
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
// Create an inventor to use as the root context object.
Inventor tesla = new Inventor("Nikola Tesla");
tesla.setInventions("Telephone repeater", "Tesla coil transformer");
// Iterate over all inventions of the Inventor referenced as the #root
// object, and generate a list of strings whose contents take the form
// "<inventor's name> invented the <invention>." (using projection !{...}).
String expression = "#root.inventions.![#root.name + ' invented the ' + #this + '.']";
// Evaluates to a list containing:
// "Nikola Tesla invented the Telephone repeater."
// "Nikola Tesla invented the Tesla coil transformer."
List<String> results = parser.parseExpression(expression)
.getValue(context, tesla, List.class);
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
// Create parser and evaluation context.
val parser = SpelExpressionParser()
val context = SimpleEvaluationContext.forReadWriteDataBinding().build()
// Create an inventor to use as the root context object.
val tesla = Inventor("Nikola Tesla")
tesla.setInventions("Telephone repeater", "Tesla coil transformer")
// Iterate over all inventions of the Inventor referenced as the #root
// object, and generate a list of strings whose contents take the form
// "<inventor's name> invented the <invention>." (using projection !{...}).
val expression = "#root.inventions.![#root.name + ' invented the ' + #this + '.']"
// Evaluates to a list containing:
// "Nikola Tesla invented the Telephone repeater."
// "Nikola Tesla invented the Tesla coil transformer."
val results = parser.parseExpression(expression)
.getValue(context, tesla, List::class.java)
----
======
@@ -230,19 +230,6 @@ provided you stick to the required connection lookup pattern. Note that JTA does
savepoints or custom isolation levels and has a different timeout mechanism but otherwise
exposes similar behavior in terms of JDBC resources and JDBC commit/rollback management.
For JTA-style lazy retrieval of actual resource connections, Spring provides a
corresponding `DataSource` proxy class for the target connection pool: see
{spring-framework-api}/jdbc/datasource/LazyConnectionDataSourceProxy.html[`LazyConnectionDataSourceProxy`].
This is particularly useful for potentially empty transactions without actual statement
execution (never fetching an actual resource in such a scenario), and also in front of
a routing `DataSource` which means to take the transaction-synchronized read-only flag
and/or isolation level into account (e.g. `IsolationLevelDataSourceRouter`).
`LazyConnectionDataSourceProxy` also provides special support for a read-only connection
pool to use during a read-only transaction, avoiding the overhead of switching the JDBC
Connection's read-only flag at the beginning and end of every transaction when fetching
it from the primary connection pool (which may be costly depending on the JDBC driver).
NOTE: As of 5.3, Spring provides an extended `JdbcTransactionManager` variant which adds
exception translation capabilities on commit/rollback (aligned with `JdbcTemplate`).
Where `DataSourceTransactionManager` will only ever throw `TransactionSystemException`
@@ -407,12 +407,6 @@ exposes the Hibernate transaction as a JDBC transaction if you have set up the p
`DataSource` for which the transactions are supposed to be exposed through the
`dataSource` property of the `HibernateTransactionManager` class.
For JTA-style lazy retrieval of actual resource connections, Spring provides a
corresponding `DataSource` proxy class for the target connection pool: see
{spring-framework-api}/jdbc/datasource/LazyConnectionDataSourceProxy.html[`LazyConnectionDataSourceProxy`].
This is particularly useful for Hibernate read-only transactions which can often
be processed from a local cache rather than hitting the database.
[[orm-hibernate-resources]]
== Comparing Container-managed and Locally Defined Resources
@@ -506,20 +506,13 @@ if you have not already done so, to get more detailed coverage of Spring's decla
The recommended strategy for JPA is local transactions through JPA's native transaction
support. Spring's `JpaTransactionManager` provides many capabilities known from local
JDBC transactions (such as transaction-specific isolation levels and resource-level
read-only optimizations) against any regular JDBC connection pool, without requiring
a JTA transaction coordinator and XA-capable resources.
read-only optimizations) against any regular JDBC connection pool (no XA requirement).
Spring JPA also lets a configured `JpaTransactionManager` expose a JPA transaction
to JDBC access code that accesses the same `DataSource`, provided that the registered
`JpaDialect` supports retrieval of the underlying JDBC `Connection`. Spring provides
dialects for the EclipseLink and Hibernate JPA implementations. See the
xref:data-access/orm/jpa.adoc#orm-jpa-dialect[next section] for details on `JpaDialect`.
For JTA-style lazy retrieval of actual resource connections, Spring provides a
corresponding `DataSource` proxy class for the target connection pool: see
{spring-framework-api}/jdbc/datasource/LazyConnectionDataSourceProxy.html[`LazyConnectionDataSourceProxy`].
This is particularly useful for JPA read-only transactions which can often
be processed from a local cache rather than hitting the database.
`JpaDialect` supports retrieval of the underlying JDBC `Connection`.
Spring provides dialects for the EclipseLink and Hibernate JPA implementations.
See the xref:data-access/orm/jpa.adoc#orm-jpa-dialect[next section] for details on the `JpaDialect` mechanism.
[[orm-jpa-dialect]]
@@ -15,7 +15,8 @@ Conceptually, checkpoint and restore align with the xref:core/beans/factory-natu
== On-demand checkpoint/restore of a running application
A checkpoint can be created on demand, for example using a command like `jcmd application.jar JDK.checkpoint`. Before the creation of the checkpoint, Spring stops all the running beans, giving them a chance to close resources if needed by implementing `Lifecycle.stop`. After restore, the same beans are restarted, with `Lifecycle.start` allowing beans to reopen resources when relevant. For libraries that do not depend on Spring, custom checkpoint/restore integration can be provided by implementing `org.crac.Resource` and registering the related instance.
A checkpoint can be created on demand, for example using a command like `jcmd application.jar JDK.checkpoint`. Before the creation of the checkpoint, Spring Framework
stops all the running beans, giving them a chance to close resources if needed by implementing `Lifecycle.stop`. After restore, the same beans are restarted, with `Lifecycle.start` allowing beans to reopen resources when relevant. For libraries that do not depend on Spring, custom checkpoint/restore integration can be provided by implementing `org.crac.Resource` and registering the related instance.
WARNING: Leveraging checkpoint/restore of a running application typically requires additional lifecycle management to gracefully stop and start using resources like files or sockets and stop active threads.
@@ -28,11 +29,6 @@ startup during the `LifecycleProcessor.onRefresh` phase. After this phase has co
`InitializingBean#afterPropertiesSet` callbacks have been invoked; but the lifecycle has not started, and the
`ContextRefreshedEvent` has not yet been published.
For testing purposes, it is also possible to leverage the `-Dspring.context.exit=onRefresh` JVM system property which
triggers similar behavior, but instead of creating a checkpoint, it exits your Spring application at the same lifecycle
phase without requiring the Project CraC dependency/JVM or Linux. This can be useful to check if connections to remote
services are required when the beans are not started, and potentially refine the configuration to avoid that.
WARNING: As mentioned above, and especially in use cases where the CRaC files are shipped as part of a deployable artifact (a container image for example), operate with the assumption that any sensitive data "seen" by the JVM ends up in the CRaC files, and assess carefully the related security implications.
NOTE: Automatic checkpoint/restore is a way to "fast-forward" the startup of the application to a phase where the application context is about to start, but it does not allow to have a fully warmed-up JVM.
@@ -19,7 +19,7 @@ been published.
To create the archive, two additional JVM flags must be specified:
* `-XX:ArchiveClassesAtExit=application.jsa`: creates the CDS archive on exit
* `-XX:ArchiveClassesAtExit=app-cds.jsa`: creates the CDS archive on exit
* `-Dspring.context.exit=onRefresh`: starts and then immediately exits your Spring
application as described above
@@ -40,8 +40,8 @@ The base CDS archive can be created by issuing the following command:
== Using the Archive
Once the archive is available, add `-XX:SharedArchiveFile=application.jsa` to your startup
script to use it, assuming an `application.jsa` file in the working directory.
Once the archive is available, add `-XX:SharedArchiveFile=app-cds.jsa` to your startup
script to use it, assuming a `app-cds.jsa` file in the working directory.
To figure out how effective the cache is, you can enable class loading logs by adding
an extra attribute: `-Xlog:class+load:file=cds.log`. This creates a `cds.log` with every
@@ -45,7 +45,7 @@ xref:appendix.adoc#appendix-spring-properties[`SpringProperties`] mechanism.
[NOTE]
====
The `@ContextHierarchy` annotation is not supported in AOT mode.
The `@ContextHierarchy` annotation is currently not supported in AOT mode.
====
To provide test-specific runtime hints for use within a GraalVM native image, you have
@@ -42,15 +42,13 @@ become cumbersome if a custom factory needs to be used across an entire test sui
issue is addressed through support for automatic discovery of default
`ContextCustomizerFactory` implementations through the `SpringFactoriesLoader` mechanism.
For example, the modules that make up the testing support in Spring Framework and Spring
Specifically, the modules that make up the testing support in Spring Framework and Spring
Boot declare all core default `ContextCustomizerFactory` implementations under the
`org.springframework.test.context.ContextCustomizerFactory` key in their
`META-INF/spring.factories` properties files. The `spring.factories` file for the
`spring-test` module can be viewed
{spring-framework-code}/spring-test/src/main/resources/META-INF/spring.factories[here].
Third-party frameworks and developers can contribute their own `ContextCustomizerFactory`
implementations to the list of default factories in the same manner through their own
`spring.factories` files.
`META-INF/spring.factories` properties files. Third-party frameworks and developers can
contribute their own `ContextCustomizerFactory` implementations to the list of default
factories in the same manner through their own `META-INF/spring.factories` properties
files.
[[testcontext-context-customizers-merging]]
@@ -80,12 +80,12 @@ become cumbersome if a custom listener needs to be used across an entire test su
issue is addressed through support for automatic discovery of default
`TestExecutionListener` implementations through the `SpringFactoriesLoader` mechanism.
For example, the `spring-test` module declares all core default `TestExecutionListener`
Specifically, the `spring-test` module declares all core default `TestExecutionListener`
implementations under the `org.springframework.test.context.TestExecutionListener` key in
its {spring-framework-code}/spring-test/src/main/resources/META-INF/spring.factories[`META-INF/spring.factories`
properties file]. Third-party frameworks and developers can contribute their own
`TestExecutionListener` implementations to the list of default listeners in the same
manner through their own `spring.factories` files.
its `META-INF/spring.factories` properties file. Third-party frameworks and developers
can contribute their own `TestExecutionListener` implementations to the list of default
listeners in the same manner through their own `META-INF/spring.factories` properties
file.
[[testcontext-tel-config-ordering]]
== Ordering `TestExecutionListener` Implementations
@@ -207,3 +207,4 @@ Kotlin::
}
----
======
@@ -198,9 +198,6 @@ controller method xref:web/webmvc/mvc-controller/ann-validation.adoc[Validation]
TIP: Using `@ModelAttribute` is optional. By default, any argument that is not a simple
value type as determined by
{spring-framework-api}/beans/BeanUtils.html#isSimpleProperty-java.lang.Class-[BeanUtils#isSimpleProperty]
_AND_ that is not resolved by any other argument resolver is treated as an implicit `@ModelAttribute`.
_AND_ that is not resolved by any other argument resolver is treated as an `@ModelAttribute`.
WARNING: When compiling to a native image with GraalVM, the implicit `@ModelAttribute`
support described above does not allow proper ahead-of-time inference of related data
binding reflection hints. As a consequence, it is recommended to explicitly annotate
method parameters with `@ModelAttribute` for use in a GraalVM native image.
@@ -509,7 +509,7 @@ Kotlin::
[[webflux-ann-httpexchange-annotation]]
== `@HttpExchange`
[.small]#xref:web/webmvc/mvc-controller/ann-requestmapping.adoc#mvc-ann-httpexchange-annotation[See equivalent in the Servlet stack]#
[.small]#xref:web/webmvc/mvc-controller/ann-requestmapping.adoc#mvc-ann-httpexchange-annotation[See equivalent in the Reactive stack]#
As an alternative to `@RequestMapping`, you can also handle requests with `@HttpExchange`
methods. Such methods are declared on an
@@ -243,9 +243,4 @@ xref:web/webmvc/mvc-controller/ann-validation.adoc[Validation].
TIP: Using `@ModelAttribute` is optional. By default, any parameter that is not a simple
value type as determined by
{spring-framework-api}/beans/BeanUtils.html#isSimpleProperty-java.lang.Class-[BeanUtils#isSimpleProperty]
_AND_ that is not resolved by any other argument resolver is treated as an implicit `@ModelAttribute`.
WARNING: When compiling to a native image with GraalVM, the implicit `@ModelAttribute`
support described above does not allow proper ahead-of-time inference of related data
binding reflection hints. As a consequence, it is recommended to explicitly annotate
method parameters with `@ModelAttribute` for use in a GraalVM native image.
_AND_ that is not resolved by any other argument resolver is treated as an `@ModelAttribute`.
@@ -103,9 +103,9 @@ You can also use the WebSocket transport configuration shown earlier to configur
maximum allowed size for incoming STOMP messages. In theory, a WebSocket
message can be almost unlimited in size. In practice, WebSocket servers impose
limits -- for example, 8K on Tomcat and 64K on Jetty. For this reason, STOMP clients
such as https://github.com/stomp-js/stompjs[`stomp-js/stompjs`] and others split larger
STOMP messages at 16K boundaries and send them as multiple WebSocket messages,
which requires the server to buffer and re-assemble.
(such as the JavaScript https://github.com/JSteunou/webstomp-client[webstomp-client]
and others) split larger STOMP messages at 16K boundaries and send them as multiple
WebSocket messages, which requires the server to buffer and re-assemble.
Spring's STOMP-over-WebSocket support does this ,so applications can configure the
maximum size for STOMP messages irrespective of WebSocket server-specific message
+9 -9
View File
@@ -8,19 +8,19 @@ javaPlatform {
dependencies {
api(platform("com.fasterxml.jackson:jackson-bom:2.15.2"))
api(platform("io.micrometer:micrometer-bom:1.12.1"))
api(platform("io.micrometer:micrometer-bom:1.12.0"))
api(platform("io.netty:netty-bom:4.1.101.Final"))
api(platform("io.netty:netty5-bom:5.0.0.Alpha5"))
api(platform("io.projectreactor:reactor-bom:2023.0.1"))
api(platform("io.projectreactor:reactor-bom:2023.0.0"))
api(platform("io.rsocket:rsocket-bom:1.1.3"))
api(platform("org.apache.groovy:groovy-bom:4.0.16"))
api(platform("org.apache.groovy:groovy-bom:4.0.15"))
api(platform("org.apache.logging.log4j:log4j-bom:2.21.1"))
api(platform("org.eclipse.jetty:jetty-bom:12.0.4"))
api(platform("org.eclipse.jetty:jetty-bom:12.0.3"))
api(platform("org.eclipse.jetty.ee10:jetty-ee10-bom:12.0.3"))
api(platform("org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.7.3"))
api(platform("org.jetbrains.kotlinx:kotlinx-serialization-bom:1.6.0"))
api(platform("org.junit:junit-bom:5.10.1"))
api(platform("org.mockito:mockito-bom:5.8.0"))
api(platform("org.mockito:mockito-bom:5.7.0"))
constraints {
api("com.fasterxml:aalto-xml:1.3.2")
@@ -102,10 +102,10 @@ dependencies {
api("org.apache.httpcomponents.client5:httpclient5:5.2.1")
api("org.apache.httpcomponents.core5:httpcore5-reactive:5.2.3")
api("org.apache.poi:poi-ooxml:5.2.4")
api("org.apache.tomcat.embed:tomcat-embed-core:10.1.16")
api("org.apache.tomcat.embed:tomcat-embed-websocket:10.1.16")
api("org.apache.tomcat:tomcat-util:10.1.16")
api("org.apache.tomcat:tomcat-websocket:10.1.16")
api("org.apache.tomcat.embed:tomcat-embed-core:10.1.15")
api("org.apache.tomcat.embed:tomcat-embed-websocket:10.1.15")
api("org.apache.tomcat:tomcat-util:10.1.15")
api("org.apache.tomcat:tomcat-websocket:10.1.15")
api("org.aspectj:aspectjrt:1.9.20.1")
api("org.aspectj:aspectjtools:1.9.20.1")
api("org.aspectj:aspectjweaver:1.9.20.1")
+2 -2
View File
@@ -1,10 +1,10 @@
version=6.1.2
version=6.1.1
org.gradle.caching=true
org.gradle.jvmargs=-Xmx2048m
org.gradle.parallel=true
kotlinVersion=1.9.21
kotlinVersion=1.9.20
kotlin.jvm.target.validation.mode=ignore
kotlin.stdlib.default.dependency=false
Binary file not shown.
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2018 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.
@@ -49,13 +49,10 @@ public interface TargetSource extends TargetClassAware {
* Will all calls to {@link #getTarget()} return the same object?
* <p>In that case, there will be no need to invoke {@link #releaseTarget(Object)},
* and the AOP framework can cache the return value of {@link #getTarget()}.
* <p>The default implementation returns {@code false}.
* @return {@code true} if the target is immutable
* @see #getTarget
*/
default boolean isStatic() {
return false;
}
boolean isStatic();
/**
* Return a target instance. Invoked immediately before the
@@ -70,11 +67,9 @@ public interface TargetSource extends TargetClassAware {
/**
* Release the given target object obtained from the
* {@link #getTarget()} method, if any.
* <p>The default implementation is empty.
* @param target object obtained from a call to {@link #getTarget()}
* @throws Exception if the object can't be released
*/
default void releaseTarget(Object target) throws Exception {
}
void releaseTarget(Object target) throws Exception;
}
@@ -78,7 +78,6 @@ import org.springframework.util.StringUtils;
* @author Juergen Hoeller
* @author Ramnivas Laddad
* @author Dave Syer
* @author Yanming Zhou
* @since 2.0
*/
@SuppressWarnings("serial")
@@ -472,11 +471,10 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
}
}
if (targetMethod != originalMethod && (shadowMatch == null ||
(Proxy.isProxyClass(targetMethod.getDeclaringClass()) &&
(shadowMatch.neverMatches() || containsAnnotationPointcut())))) {
(shadowMatch.neverMatches() && Proxy.isProxyClass(targetMethod.getDeclaringClass())))) {
// Fall back to the plain original method in case of no resolvable match or a
// negative match on a proxy class (which doesn't carry any annotations on its
// redeclared methods), as well as for annotation pointcuts.
// redeclared methods).
methodToMatch = originalMethod;
try {
shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);
@@ -515,10 +513,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
return shadowMatch;
}
private boolean containsAnnotationPointcut() {
return resolveExpression().contains("@annotation");
}
@Override
public boolean equals(@Nullable Object other) {
@@ -38,8 +38,8 @@ abstract class CoroutinesUtils {
@Nullable
@SuppressWarnings({"unchecked", "rawtypes"})
static Object awaitSingleOrNull(@Nullable Object value, Object continuation) {
return MonoKt.awaitSingleOrNull(value instanceof Mono mono ? mono : Mono.justOrEmpty(value),
static Object awaitSingleOrNull(Object value, Object continuation) {
return MonoKt.awaitSingleOrNull(value instanceof Mono mono ? mono : Mono.just(value),
(Continuation<Object>) continuation);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2022 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,6 +73,8 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
protected final Log logger = LogFactory.getLog(getClass());
private final Map<Method, AsyncTaskExecutor> executors = new ConcurrentHashMap<>(16);
private SingletonSupplier<Executor> defaultExecutor;
private SingletonSupplier<AsyncUncaughtExceptionHandler> exceptionHandler;
@@ -83,9 +85,6 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
@Nullable
private StringValueResolver embeddedValueResolver;
private final Map<Method, AsyncTaskExecutor> executors = new ConcurrentHashMap<>(16);
/**
* Create a new instance with a default {@link AsyncUncaughtExceptionHandler}.
* @param defaultExecutor the {@code Executor} (typically a Spring {@code AsyncTaskExecutor}
@@ -158,7 +157,6 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
if (beanFactory instanceof ConfigurableBeanFactory configurableBeanFactory) {
this.embeddedValueResolver = new EmbeddedValueResolver(configurableBeanFactory);
}
this.executors.clear();
}
@@ -153,6 +153,16 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour
}
}
@Override
public boolean isStatic() {
return false;
}
@Override
public void releaseTarget(Object target) throws Exception {
// Nothing to do here.
}
/**
* Copy configuration from the other AbstractBeanFactoryBasedTargetSource object.
@@ -72,6 +72,11 @@ public abstract class AbstractLazyCreationTargetSource implements TargetSource {
return (this.lazyTarget != null ? this.lazyTarget.getClass() : null);
}
@Override
public boolean isStatic() {
return false;
}
/**
* Returns the lazy-initialized target object,
* creating it on-the-fly if it doesn't exist already.
@@ -86,6 +91,11 @@ public abstract class AbstractLazyCreationTargetSource implements TargetSource {
return this.lazyTarget;
}
@Override
public void releaseTarget(Object target) throws Exception {
// nothing to do
}
/**
* Subclasses should implement this method to return the lazy initialized object.
@@ -116,6 +116,13 @@ public final class EmptyTargetSource implements TargetSource, Serializable {
return null;
}
/**
* Nothing to release.
*/
@Override
public void releaseTarget(Object target) {
}
/**
* Returns the canonical instance on deserialization in case
@@ -66,11 +66,21 @@ public class HotSwappableTargetSource implements TargetSource, Serializable {
return this.target.getClass();
}
@Override
public final boolean isStatic() {
return false;
}
@Override
public synchronized Object getTarget() {
return this.target;
}
@Override
public void releaseTarget(Object target) {
// nothing to do
}
/**
* Swap the target, returning the old target object.
@@ -67,6 +67,11 @@ public class SingletonTargetSource implements TargetSource, Serializable {
return this.target;
}
@Override
public void releaseTarget(Object target) {
// nothing to do
}
@Override
public boolean isStatic() {
return true;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2018 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,6 +73,14 @@ public abstract class AbstractRefreshableTargetSource implements TargetSource, R
return this.targetObject.getClass();
}
/**
* Not static.
*/
@Override
public boolean isStatic() {
return false;
}
@Override
@Nullable
public final synchronized Object getTarget() {
@@ -82,6 +90,13 @@ public abstract class AbstractRefreshableTargetSource implements TargetSource, R
return this.targetObject;
}
/**
* No need to release target.
*/
@Override
public void releaseTarget(Object object) {
}
@Override
public final synchronized void refresh() {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2022 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.
@@ -50,7 +50,6 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
* @author Rob Harrop
* @author Rod Johnson
* @author Chris Beams
* @author Yanming Zhou
*/
public class AspectJExpressionPointcutTests {
@@ -425,19 +424,6 @@ public class AspectJExpressionPointcutTests {
assertThat(ajexp.matches(BeanA.class.getMethod("getAge"), proxy.getClass())).isTrue();
}
@Test
public void testNotAnnotationOnCglibProxyMethod() throws Exception {
String expression = "!@annotation(test.annotation.transaction.Tx)";
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
ajexp.setExpression(expression);
ProxyFactory factory = new ProxyFactory(new BeanA());
factory.setProxyTargetClass(true);
BeanA proxy = (BeanA) factory.getProxy();
assertThat(ajexp.matches(BeanA.class.getMethod("getAge"), proxy.getClass())).isFalse();
}
@Test
public void testAnnotationOnDynamicProxyMethod() throws Exception {
String expression = "@annotation(test.annotation.transaction.Tx)";
@@ -450,18 +436,6 @@ public class AspectJExpressionPointcutTests {
assertThat(ajexp.matches(IBeanA.class.getMethod("getAge"), proxy.getClass())).isTrue();
}
@Test
public void testNotAnnotationOnDynamicProxyMethod() throws Exception {
String expression = "!@annotation(test.annotation.transaction.Tx)";
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
ajexp.setExpression(expression);
ProxyFactory factory = new ProxyFactory(new BeanA());
factory.setProxyTargetClass(false);
IBeanA proxy = (IBeanA) factory.getProxy();
assertThat(ajexp.matches(IBeanA.class.getMethod("getAge"), proxy.getClass())).isFalse();
}
@Test
public void testAnnotationOnMethodWithWildcard() throws Exception {
String expression = "execution(@(test.annotation..*) * *(..))";
@@ -354,8 +354,8 @@ public class ProxyFactoryTests {
list.add(proxy1);
list.add(proxy2);
AnnotationAwareOrderComparator.sort(list);
assertThat(list).element(0).isSameAs(proxy2);
assertThat(list).element(1).isSameAs(proxy1);
assertThat(list.get(0)).isSameAs(proxy2);
assertThat(list.get(1)).isSameAs(proxy1);
}
@Test
@@ -370,8 +370,8 @@ public class ProxyFactoryTests {
list.add(proxy1);
list.add(proxy2);
AnnotationAwareOrderComparator.sort(list);
assertThat(list).element(0).isSameAs(proxy2);
assertThat(list).element(1).isSameAs(proxy1);
assertThat(list.get(0)).isSameAs(proxy2);
assertThat(list.get(1)).isSameAs(proxy1);
}
@Test
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2019 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.
@@ -39,8 +39,8 @@ public class ScopedProxyAutowireTests {
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
qualifiedResource(ScopedProxyAutowireTests.class, "scopedAutowireFalse.xml"));
assertThat(Arrays.asList(bf.getBeanNamesForType(TestBean.class, false, false))).contains("scoped");
assertThat(Arrays.asList(bf.getBeanNamesForType(TestBean.class, true, false))).contains("scoped");
assertThat(Arrays.asList(bf.getBeanNamesForType(TestBean.class, false, false)).contains("scoped")).isTrue();
assertThat(Arrays.asList(bf.getBeanNamesForType(TestBean.class, true, false)).contains("scoped")).isTrue();
assertThat(bf.containsSingleton("scoped")).isFalse();
TestBean autowired = (TestBean) bf.getBean("autowired");
TestBean unscoped = (TestBean) bf.getBean("unscoped");
@@ -53,8 +53,8 @@ public class ScopedProxyAutowireTests {
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
qualifiedResource(ScopedProxyAutowireTests.class, "scopedAutowireTrue.xml"));
assertThat(Arrays.asList(bf.getBeanNamesForType(TestBean.class, true, false))).contains("scoped");
assertThat(Arrays.asList(bf.getBeanNamesForType(TestBean.class, false, false))).contains("scoped");
assertThat(Arrays.asList(bf.getBeanNamesForType(TestBean.class, true, false)).contains("scoped")).isTrue();
assertThat(Arrays.asList(bf.getBeanNamesForType(TestBean.class, false, false)).contains("scoped")).isTrue();
assertThat(bf.containsSingleton("scoped")).isFalse();
TestBean autowired = (TestBean) bf.getBean("autowired");
TestBean scoped = (TestBean) bf.getBean("scoped");
@@ -141,7 +141,7 @@ public class ComposablePointcutTests {
pc1.intersection(GETTER_METHOD_MATCHER);
assertThat(pc1).isNotEqualTo(pc2);
assertThat(pc1.equals(pc2)).isFalse();
assertThat(pc1.hashCode()).isNotEqualTo(pc2.hashCode());
pc2.intersection(GETTER_METHOD_MATCHER);
@@ -110,8 +110,8 @@ public class MethodMatchersTests {
public void testUnionEquals() {
MethodMatcher first = MethodMatchers.union(MethodMatcher.TRUE, MethodMatcher.TRUE);
MethodMatcher second = new ComposablePointcut(MethodMatcher.TRUE).union(new ComposablePointcut(MethodMatcher.TRUE)).getMethodMatcher();
assertThat(first).isEqualTo(second);
assertThat(second).isEqualTo(first);
assertThat(first.equals(second)).isTrue();
assertThat(second.equals(first)).isTrue();
}
@Test
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2019 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.
@@ -34,7 +34,7 @@ import static org.springframework.core.testfixture.io.ResourceTestUtils.qualifie
* @author Chris Beams
* @since 07.01.2005
*/
class LazyInitTargetSourceTests {
public class LazyInitTargetSourceTests {
private static final Class<?> CLASS = LazyInitTargetSourceTests.class;
@@ -42,11 +42,9 @@ class LazyInitTargetSourceTests {
private static final Resource CUSTOM_TARGET_CONTEXT = qualifiedResource(CLASS, "customTarget.xml");
private static final Resource FACTORY_BEAN_CONTEXT = qualifiedResource(CLASS, "factoryBean.xml");
private final DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
@Test
void lazyInitSingletonTargetSource() {
public void testLazyInitSingletonTargetSource() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(SINGLETON_CONTEXT);
bf.preInstantiateSingletons();
@@ -57,7 +55,8 @@ class LazyInitTargetSourceTests {
}
@Test
void customLazyInitSingletonTargetSource() {
public void testCustomLazyInitSingletonTargetSource() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(CUSTOM_TARGET_CONTEXT);
bf.preInstantiateSingletons();
@@ -68,25 +67,25 @@ class LazyInitTargetSourceTests {
}
@Test
@SuppressWarnings("unchecked")
void lazyInitFactoryBeanTargetSource() {
public void testLazyInitFactoryBeanTargetSource() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(FACTORY_BEAN_CONTEXT);
bf.preInstantiateSingletons();
Set<Object> set1 = (Set<Object>) bf.getBean("proxy1");
Set<?> set1 = (Set<?>) bf.getBean("proxy1");
assertThat(bf.containsSingleton("target1")).isFalse();
assertThat(set1).contains("10");
assertThat(set1.contains("10")).isTrue();
assertThat(bf.containsSingleton("target1")).isTrue();
Set<Object> set2 = (Set<Object>) bf.getBean("proxy2");
Set<?> set2 = (Set<?>) bf.getBean("proxy2");
assertThat(bf.containsSingleton("target2")).isFalse();
assertThat(set2).contains("20");
assertThat(set2.contains("20")).isTrue();
assertThat(bf.containsSingleton("target2")).isTrue();
}
@SuppressWarnings("serial")
static class CustomLazyInitTargetSource extends LazyInitTargetSource {
public static class CustomLazyInitTargetSource extends LazyInitTargetSource {
@Override
protected void postProcessTargetObject(Object targetObject) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2022 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.
@@ -75,9 +75,14 @@ public class PrototypeBasedTargetSourceTests {
private TestBean thisFieldIsNotSerializable = new TestBean();
@Override
public Object getTarget() {
public Object getTarget() throws Exception {
return newPrototypeInstance();
}
@Override
public void releaseTarget(Object target) throws Exception {
// Do nothing
}
}
}
@@ -1,75 +0,0 @@
/*
* Copyright 2002-2023 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.aop.framework
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.runBlocking
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import kotlin.coroutines.Continuation
/**
* Tests for [CoroutinesUtils].
*
* @author Sebastien Deleuze
*/
class CoroutinesUtilsTests {
@Test
fun awaitSingleNonNullValue() {
val value = "foo"
val continuation = Continuation<Any>(CoroutineName("test")) { }
runBlocking {
assertThat(CoroutinesUtils.awaitSingleOrNull(value, continuation)).isEqualTo(value)
}
}
@Test
fun awaitSingleNullValue() {
val value = null
val continuation = Continuation<Any>(CoroutineName("test")) { }
runBlocking {
assertThat(CoroutinesUtils.awaitSingleOrNull(value, continuation)).isNull()
}
}
@Test
fun awaitSingleMonoValue() {
val value = "foo"
val continuation = Continuation<Any>(CoroutineName("test")) { }
runBlocking {
assertThat(CoroutinesUtils.awaitSingleOrNull(Mono.just(value), continuation)).isEqualTo(value)
}
}
@Test
@Suppress("UNCHECKED_CAST")
fun flow() {
val value1 = "foo"
val value2 = "bar"
val values = Flux.just(value1, value2)
val flow = CoroutinesUtils.asFlow(values) as Flow<String>
runBlocking {
assertThat(flow.toList()).containsExactly(value1, value2)
}
}
}
@@ -543,7 +543,7 @@ public abstract class AbstractCacheAnnotationTests {
Object r1 = service.multiConditionalCacheAndEvict(key);
Object r3 = service.multiConditionalCacheAndEvict(key);
assertThat(r1).isNotEqualTo(r3);
assertThat(r1.equals(r3)).isFalse();
assertThat(primary.get(key)).isNull();
Object key2 = 3;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2020 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.
@@ -55,30 +55,30 @@ public class DefaultListableBeanFactoryBenchmark {
RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class);
switch (this.mode) {
case "simple" -> {
}
case "dependencyCheck" -> {
case "simple":
break;
case "dependencyCheck":
rbd = new RootBeanDefinition(LifecycleBean.class);
rbd.setDependencyCheck(RootBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
this.beanFactory.addBeanPostProcessor(new LifecycleBean.PostProcessor());
}
case "constructor" -> {
break;
case "constructor":
rbd.getConstructorArgumentValues().addGenericArgumentValue("juergen");
rbd.getConstructorArgumentValues().addGenericArgumentValue("99");
}
case "constructorArgument" -> {
break;
case "constructorArgument":
rbd.getConstructorArgumentValues().addGenericArgumentValue(new RuntimeBeanReference("spouse"));
this.beanFactory.registerBeanDefinition("test", rbd);
this.beanFactory.registerBeanDefinition("spouse", new RootBeanDefinition(TestBean.class));
}
case "properties" -> {
break;
case "properties":
rbd.getPropertyValues().add("name", "juergen");
rbd.getPropertyValues().add("age", "99");
}
case "resolvedProperties" -> {
break;
case "resolvedProperties":
rbd.getPropertyValues().add("spouse", new RuntimeBeanReference("spouse"));
this.beanFactory.registerBeanDefinition("spouse", new RootBeanDefinition(TestBean.class));
}
break;
}
rbd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
this.beanFactory.registerBeanDefinition("test", rbd);
@@ -976,11 +976,11 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
int length = propertyName.length();
for (int i = startIndex; i < length; i++) {
switch (propertyName.charAt(i)) {
case PropertyAccessor.PROPERTY_KEY_PREFIX_CHAR -> {
case PropertyAccessor.PROPERTY_KEY_PREFIX_CHAR:
// The property name contains opening prefix(es)...
unclosedPrefixes++;
}
case PropertyAccessor.PROPERTY_KEY_SUFFIX_CHAR -> {
break;
case PropertyAccessor.PROPERTY_KEY_SUFFIX_CHAR:
if (unclosedPrefixes == 0) {
// No unclosed prefix(es) in the property name (left) ->
// this is the suffix we are looking for.
@@ -991,12 +991,13 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
// just one that occurred within the property name.
unclosedPrefixes--;
}
}
break;
}
}
return -1;
}
@Override
public String toString() {
String className = getClass().getName();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -91,14 +91,14 @@ public abstract class PropertyAccessorUtils {
int i = (last ? length - 1 : 0);
while (last ? i >= 0 : i < length) {
switch (propertyPath.charAt(i)) {
case PropertyAccessor.PROPERTY_KEY_PREFIX_CHAR, PropertyAccessor.PROPERTY_KEY_SUFFIX_CHAR -> {
case PropertyAccessor.PROPERTY_KEY_PREFIX_CHAR:
case PropertyAccessor.PROPERTY_KEY_SUFFIX_CHAR:
inKey = !inKey;
}
case PropertyAccessor.NESTED_PROPERTY_SEPARATOR_CHAR -> {
break;
case PropertyAccessor.NESTED_PROPERTY_SEPARATOR_CHAR:
if (!inKey) {
return i;
}
}
}
if (last) {
i--;
@@ -49,7 +49,6 @@ import org.springframework.util.StringUtils;
* @author Juergen Hoeller
* @author Rob Harrop
* @author Dave Syer
* @author Yanming Zhou
* @since 2.0
* @see BeanWrapperImpl
* @see SimpleTypeConverter
@@ -179,13 +178,13 @@ class TypeConverterDelegate {
return (T) convertToTypedArray(convertedValue, propertyName, requiredType.componentType());
}
else if (convertedValue.getClass().isArray()) {
if (Collection.class.isAssignableFrom(requiredType)) {
convertedValue = convertToTypedCollection(CollectionUtils.arrayToList(convertedValue),
propertyName, requiredType, typeDescriptor);
if (Array.getLength(convertedValue) == 1) {
convertedValue = Array.get(convertedValue, 0);
standardConversion = true;
}
else if (Array.getLength(convertedValue) == 1) {
convertedValue = Array.get(convertedValue, 0);
else if (Collection.class.isAssignableFrom(requiredType)) {
convertedValue = convertToTypedCollection(CollectionUtils.arrayToList(convertedValue),
propertyName, requiredType, typeDescriptor);
standardConversion = true;
}
}
@@ -159,9 +159,6 @@ import org.springframework.util.StringUtils;
public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor,
MergedBeanDefinitionPostProcessor, BeanRegistrationAotProcessor, PriorityOrdered, BeanFactoryAware {
private static final Constructor<?>[] EMPTY_CONSTRUCTOR_ARRAY = new Constructor<?>[0];
protected final Log logger = LogFactory.getLog(getClass());
private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
@@ -289,25 +286,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// Register externally managed config members on bean definition.
findInjectionMetadata(beanName, beanType, beanDefinition);
// Use opportunity to clear caches which are not needed after singleton instantiation.
// The injectionMetadataCache itself is left intact since it cannot be reliably
// reconstructed in terms of externally managed config members otherwise.
if (beanDefinition.isSingleton()) {
this.candidateConstructorsCache.remove(beanType);
// With actual lookup overrides, keep it intact along with bean definition.
if (!beanDefinition.hasMethodOverrides()) {
this.lookupMethodsChecked.remove(beanName);
}
}
}
@Override
public void resetBeanDefinition(String beanName) {
this.lookupMethodsChecked.remove(beanName);
this.injectionMetadataCache.remove(beanName);
}
@Override
@@ -345,6 +324,12 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
return metadata;
}
@Override
public void resetBeanDefinition(String beanName) {
this.lookupMethodsChecked.remove(beanName);
this.injectionMetadataCache.remove(beanName);
}
@Override
public Class<?> determineBeanType(Class<?> beanClass, String beanName) throws BeanCreationException {
checkLookupMethods(beanClass, beanName);
@@ -444,7 +429,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
"default constructor to fall back to: " + candidates.get(0));
}
}
candidateConstructors = candidates.toArray(EMPTY_CONSTRUCTOR_ARRAY);
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
@@ -457,7 +442,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
candidateConstructors = new Constructor<?>[] {primaryConstructor};
}
else {
candidateConstructors = EMPTY_CONSTRUCTOR_ARRAY;
candidateConstructors = new Constructor<?>[0];
}
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
@@ -191,14 +191,16 @@ public final class AutowiredFieldValueResolver extends AutowiredElementResolver
return value;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
throw new UnsatisfiedDependencyException(null, beanName,
new InjectionPoint(field), ex);
}
}
private Field getField(RegisteredBean registeredBean) {
Field field = ReflectionUtils.findField(registeredBean.getBeanClass(), this.fieldName);
Assert.notNull(field, () -> "No field '" + this.fieldName + "' found on " +
registeredBean.getBeanClass().getName());
Field field = ReflectionUtils.findField(registeredBean.getBeanClass(),
this.fieldName);
Assert.notNull(field, () -> "No field '" + this.fieldName + "' found on "
+ registeredBean.getBeanClass().getName());
return field;
}
@@ -34,9 +34,6 @@ import java.util.function.Function;
import java.util.function.Predicate;
import org.springframework.aot.generate.GeneratedMethods;
import org.springframework.aot.generate.ValueCodeGenerator;
import org.springframework.aot.generate.ValueCodeGenerator.Delegate;
import org.springframework.aot.generate.ValueCodeGeneratorDelegates;
import org.springframework.aot.hint.ExecutableMode;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
@@ -92,22 +89,17 @@ class BeanDefinitionPropertiesCodeGenerator {
private final Predicate<String> attributeFilter;
private final ValueCodeGenerator valueCodeGenerator;
private final BeanDefinitionPropertyValueCodeGenerator valueCodeGenerator;
BeanDefinitionPropertiesCodeGenerator(RuntimeHints hints,
Predicate<String> attributeFilter, GeneratedMethods generatedMethods,
List<Delegate> additionalDelegates,
BiFunction<String, Object, CodeBlock> customValueCodeGenerator) {
this.hints = hints;
this.attributeFilter = attributeFilter;
List<Delegate> allDelegates = new ArrayList<>();
allDelegates.add((valueCodeGenerator, value) -> customValueCodeGenerator.apply(PropertyNamesStack.peek(), value));
allDelegates.addAll(additionalDelegates);
allDelegates.addAll(BeanDefinitionPropertyValueCodeGeneratorDelegates.INSTANCES);
allDelegates.addAll(ValueCodeGeneratorDelegates.INSTANCES);
this.valueCodeGenerator = ValueCodeGenerator.with(allDelegates).scoped(generatedMethods);
this.valueCodeGenerator = new BeanDefinitionPropertyValueCodeGenerator(generatedMethods,
(object, type) -> customValueCodeGenerator.apply(PropertyNamesStack.peek(), object));
}
@@ -174,10 +166,6 @@ class BeanDefinitionPropertiesCodeGenerator {
Method method = ReflectionUtils.findMethod(methodDeclaringClass, methodName);
if (method != null) {
this.hints.reflection().registerMethod(method, ExecutableMode.INVOKE);
Method interfaceMethod = ClassUtils.getInterfaceMethodIfPossible(method, beanUserClass);
if (!interfaceMethod.equals(method)) {
this.hints.reflection().registerMethod(interfaceMethod, ExecutableMode.INVOKE);
}
}
}
@@ -221,32 +209,32 @@ class BeanDefinitionPropertiesCodeGenerator {
private void addPropertyValues(CodeBlock.Builder code, RootBeanDefinition beanDefinition) {
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
if (!propertyValues.isEmpty()) {
Class<?> infrastructureType = getInfrastructureType(beanDefinition);
Map<String, Method> writeMethods = (infrastructureType != Object.class) ? getWriteMethods(infrastructureType) : Collections.emptyMap();
for (PropertyValue propertyValue : propertyValues) {
String name = propertyValue.getName();
CodeBlock valueCode = generateValue(name, propertyValue.getValue());
code.addStatement("$L.getPropertyValues().addPropertyValue($S, $L)",
BEAN_DEFINITION_VARIABLE, name, valueCode);
Method writeMethod = writeMethods.get(name);
if (writeMethod != null) {
registerReflectionHints(beanDefinition, writeMethod);
BEAN_DEFINITION_VARIABLE, propertyValue.getName(), valueCode);
}
Class<?> infrastructureType = getInfrastructureType(beanDefinition);
if (infrastructureType != Object.class) {
Map<String, Method> writeMethods = getWriteMethods(infrastructureType);
for (PropertyValue propertyValue : propertyValues) {
Method writeMethod = writeMethods.get(propertyValue.getName());
if (writeMethod != null) {
this.hints.reflection().registerMethod(writeMethod, ExecutableMode.INVOKE);
// ReflectionUtils#findField searches recursively in the type hierarchy
Class<?> searchType = beanDefinition.getTargetType();
while (searchType != null && searchType != writeMethod.getDeclaringClass()) {
this.hints.reflection().registerType(searchType, MemberCategory.DECLARED_FIELDS);
searchType = searchType.getSuperclass();
}
this.hints.reflection().registerType(writeMethod.getDeclaringClass(), MemberCategory.DECLARED_FIELDS);
}
}
}
}
}
private void registerReflectionHints(RootBeanDefinition beanDefinition, Method writeMethod) {
this.hints.reflection().registerMethod(writeMethod, ExecutableMode.INVOKE);
// ReflectionUtils#findField searches recursively in the type hierarchy
Class<?> searchType = beanDefinition.getTargetType();
while (searchType != null && searchType != writeMethod.getDeclaringClass()) {
this.hints.reflection().registerType(searchType, MemberCategory.DECLARED_FIELDS);
searchType = searchType.getSuperclass();
}
this.hints.reflection().registerType(writeMethod.getDeclaringClass(), MemberCategory.DECLARED_FIELDS);
}
private void addQualifiers(CodeBlock.Builder code, RootBeanDefinition beanDefinition) {
Set<AutowireCandidateQualifier> qualifiers = beanDefinition.getQualifiers();
if (!qualifiers.isEmpty()) {
@@ -374,7 +362,6 @@ class BeanDefinitionPropertiesCodeGenerator {
return (castNecessary ? CodeBlock.of("($T) $L", castType, valueCode) : valueCode);
}
static class PropertyNamesStack {
private static final ThreadLocal<ArrayDeque<String>> threadLocal = ThreadLocal.withInitial(ArrayDeque::new);
@@ -393,6 +380,7 @@ class BeanDefinitionPropertiesCodeGenerator {
String value = threadLocal.get().peek();
return ("".equals(value) ? null : value);
}
}
}
@@ -0,0 +1,600 @@
/*
* Copyright 2002-2023 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.aot;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.function.BiFunction;
import java.util.stream.Stream;
import org.springframework.aot.generate.GeneratedMethod;
import org.springframework.aot.generate.GeneratedMethods;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanReference;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.support.ManagedSet;
import org.springframework.core.ResolvableType;
import org.springframework.javapoet.AnnotationSpec;
import org.springframework.javapoet.CodeBlock;
import org.springframework.javapoet.CodeBlock.Builder;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
/**
* Internal code generator used to generate code for a single value contained in
* a {@link BeanDefinition} property.
*
* @author Stephane Nicoll
* @author Phillip Webb
* @author Sebastien Deleuze
* @since 6.0
*/
class BeanDefinitionPropertyValueCodeGenerator {
static final CodeBlock NULL_VALUE_CODE_BLOCK = CodeBlock.of("null");
private final GeneratedMethods generatedMethods;
private final List<Delegate> delegates;
BeanDefinitionPropertyValueCodeGenerator(GeneratedMethods generatedMethods,
@Nullable BiFunction<Object, ResolvableType, CodeBlock> customValueGenerator) {
this.generatedMethods = generatedMethods;
this.delegates = new ArrayList<>();
if (customValueGenerator != null) {
this.delegates.add(customValueGenerator::apply);
}
this.delegates.addAll(List.of(
new PrimitiveDelegate(),
new StringDelegate(),
new CharsetDelegate(),
new EnumDelegate(),
new ClassDelegate(),
new ResolvableTypeDelegate(),
new ArrayDelegate(),
new ManagedListDelegate(),
new ManagedSetDelegate(),
new ManagedMapDelegate(),
new ListDelegate(),
new SetDelegate(),
new MapDelegate(),
new BeanReferenceDelegate(),
new TypedStringValueDelegate()
));
}
CodeBlock generateCode(@Nullable Object value) {
ResolvableType type = ResolvableType.forInstance(value);
try {
return generateCode(value, type);
}
catch (Exception ex) {
throw new IllegalArgumentException(buildErrorMessage(value, type), ex);
}
}
private CodeBlock generateCodeForElement(@Nullable Object value, ResolvableType type) {
try {
return generateCode(value, type);
}
catch (Exception ex) {
throw new IllegalArgumentException(buildErrorMessage(value, type), ex);
}
}
private static String buildErrorMessage(@Nullable Object value, ResolvableType type) {
StringBuilder message = new StringBuilder("Failed to generate code for '");
message.append(value).append("'");
if (type != ResolvableType.NONE) {
message.append(" with type ").append(type);
}
return message.toString();
}
private CodeBlock generateCode(@Nullable Object value, ResolvableType type) {
if (value == null) {
return NULL_VALUE_CODE_BLOCK;
}
for (Delegate delegate : this.delegates) {
CodeBlock code = delegate.generateCode(value, type);
if (code != null) {
return code;
}
}
throw new IllegalArgumentException("Code generation does not support " + type);
}
/**
* Internal delegate used to support generation for a specific type.
*/
@FunctionalInterface
private interface Delegate {
@Nullable
CodeBlock generateCode(Object value, ResolvableType type);
}
/**
* {@link Delegate} for {@code primitive} types.
*/
private static class PrimitiveDelegate implements Delegate {
private static final Map<Character, String> CHAR_ESCAPES = Map.of(
'\b', "\\b",
'\t', "\\t",
'\n', "\\n",
'\f', "\\f",
'\r', "\\r",
'\"', "\"",
'\'', "\\'",
'\\', "\\\\"
);
@Override
@Nullable
public CodeBlock generateCode(Object value, ResolvableType type) {
if (value instanceof Boolean || value instanceof Integer) {
return CodeBlock.of("$L", value);
}
if (value instanceof Byte) {
return CodeBlock.of("(byte) $L", value);
}
if (value instanceof Short) {
return CodeBlock.of("(short) $L", value);
}
if (value instanceof Long) {
return CodeBlock.of("$LL", value);
}
if (value instanceof Float) {
return CodeBlock.of("$LF", value);
}
if (value instanceof Double) {
return CodeBlock.of("(double) $L", value);
}
if (value instanceof Character character) {
return CodeBlock.of("'$L'", escape(character));
}
return null;
}
private String escape(char ch) {
String escaped = CHAR_ESCAPES.get(ch);
if (escaped != null) {
return escaped;
}
return (!Character.isISOControl(ch)) ? Character.toString(ch)
: String.format("\\u%04x", (int) ch);
}
}
/**
* {@link Delegate} for {@link String} types.
*/
private static class StringDelegate implements Delegate {
@Override
@Nullable
public CodeBlock generateCode(Object value, ResolvableType type) {
if (value instanceof String) {
return CodeBlock.of("$S", value);
}
return null;
}
}
/**
* {@link Delegate} for {@link Charset} types.
*/
private static class CharsetDelegate implements Delegate {
@Override
@Nullable
public CodeBlock generateCode(Object value, ResolvableType type) {
if (value instanceof Charset charset) {
return CodeBlock.of("$T.forName($S)", Charset.class, charset.name());
}
return null;
}
}
/**
* {@link Delegate} for {@link Enum} types.
*/
private static class EnumDelegate implements Delegate {
@Override
@Nullable
public CodeBlock generateCode(Object value, ResolvableType type) {
if (value instanceof Enum<?> enumValue) {
return CodeBlock.of("$T.$L", enumValue.getDeclaringClass(),
enumValue.name());
}
return null;
}
}
/**
* {@link Delegate} for {@link Class} types.
*/
private static class ClassDelegate implements Delegate {
@Override
@Nullable
public CodeBlock generateCode(Object value, ResolvableType type) {
if (value instanceof Class<?> clazz) {
return CodeBlock.of("$T.class", ClassUtils.getUserClass(clazz));
}
return null;
}
}
/**
* {@link Delegate} for {@link ResolvableType} types.
*/
private static class ResolvableTypeDelegate implements Delegate {
@Override
@Nullable
public CodeBlock generateCode(Object value, ResolvableType type) {
if (value instanceof ResolvableType resolvableType) {
return ResolvableTypeCodeGenerator.generateCode(resolvableType);
}
return null;
}
}
/**
* {@link Delegate} for {@code array} types.
*/
private class ArrayDelegate implements Delegate {
@Override
@Nullable
public CodeBlock generateCode(@Nullable Object value, ResolvableType type) {
if (type.isArray()) {
ResolvableType componentType = type.getComponentType();
Stream<CodeBlock> elements = Arrays.stream(ObjectUtils.toObjectArray(value)).map(component ->
BeanDefinitionPropertyValueCodeGenerator.this.generateCode(component, componentType));
CodeBlock.Builder code = CodeBlock.builder();
code.add("new $T {", type.toClass());
code.add(elements.collect(CodeBlock.joining(", ")));
code.add("}");
return code.build();
}
return null;
}
}
/**
* Abstract {@link Delegate} for {@code Collection} types.
*/
private abstract class CollectionDelegate<T extends Collection<?>> implements Delegate {
private final Class<?> collectionType;
private final CodeBlock emptyResult;
public CollectionDelegate(Class<?> collectionType, CodeBlock emptyResult) {
this.collectionType = collectionType;
this.emptyResult = emptyResult;
}
@SuppressWarnings("unchecked")
@Override
@Nullable
public CodeBlock generateCode(Object value, ResolvableType type) {
if (this.collectionType.isInstance(value)) {
T collection = (T) value;
if (collection.isEmpty()) {
return this.emptyResult;
}
ResolvableType elementType = type.as(this.collectionType).getGeneric();
return generateCollectionCode(elementType, collection);
}
return null;
}
protected CodeBlock generateCollectionCode(ResolvableType elementType, T collection) {
return generateCollectionOf(collection, this.collectionType, elementType);
}
protected final CodeBlock generateCollectionOf(Collection<?> collection,
Class<?> collectionType, ResolvableType elementType) {
Builder code = CodeBlock.builder();
code.add("$T.of(", collectionType);
Iterator<?> iterator = collection.iterator();
while (iterator.hasNext()) {
Object element = iterator.next();
code.add("$L", BeanDefinitionPropertyValueCodeGenerator.this
.generateCodeForElement(element, elementType));
if (iterator.hasNext()) {
code.add(", ");
}
}
code.add(")");
return code.build();
}
}
/**
* {@link Delegate} for {@link ManagedList} types.
*/
private class ManagedListDelegate extends CollectionDelegate<ManagedList<?>> {
public ManagedListDelegate() {
super(ManagedList.class, CodeBlock.of("new $T()", ManagedList.class));
}
}
/**
* {@link Delegate} for {@link ManagedSet} types.
*/
private class ManagedSetDelegate extends CollectionDelegate<ManagedSet<?>> {
public ManagedSetDelegate() {
super(ManagedSet.class, CodeBlock.of("new $T()", ManagedSet.class));
}
}
/**
* {@link Delegate} for {@link ManagedMap} types.
*/
private class ManagedMapDelegate implements Delegate {
private static final CodeBlock EMPTY_RESULT = CodeBlock.of("$T.ofEntries()", ManagedMap.class);
@Override
@Nullable
public CodeBlock generateCode(Object value, ResolvableType type) {
if (value instanceof ManagedMap<?, ?> managedMap) {
return generateManagedMapCode(type, managedMap);
}
return null;
}
private <K, V> CodeBlock generateManagedMapCode(ResolvableType type, ManagedMap<K, V> managedMap) {
if (managedMap.isEmpty()) {
return EMPTY_RESULT;
}
ResolvableType keyType = type.as(Map.class).getGeneric(0);
ResolvableType valueType = type.as(Map.class).getGeneric(1);
CodeBlock.Builder code = CodeBlock.builder();
code.add("$T.ofEntries(", ManagedMap.class);
Iterator<Map.Entry<K, V>> iterator = managedMap.entrySet().iterator();
while (iterator.hasNext()) {
Entry<?, ?> entry = iterator.next();
code.add("$T.entry($L,$L)", Map.class,
BeanDefinitionPropertyValueCodeGenerator.this
.generateCodeForElement(entry.getKey(), keyType),
BeanDefinitionPropertyValueCodeGenerator.this
.generateCodeForElement(entry.getValue(), valueType));
if (iterator.hasNext()) {
code.add(", ");
}
}
code.add(")");
return code.build();
}
}
/**
* {@link Delegate} for {@link List} types.
*/
private class ListDelegate extends CollectionDelegate<List<?>> {
ListDelegate() {
super(List.class, CodeBlock.of("$T.emptyList()", Collections.class));
}
}
/**
* {@link Delegate} for {@link Set} types.
*/
private class SetDelegate extends CollectionDelegate<Set<?>> {
SetDelegate() {
super(Set.class, CodeBlock.of("$T.emptySet()", Collections.class));
}
@Override
protected CodeBlock generateCollectionCode(ResolvableType elementType, Set<?> set) {
if (set instanceof LinkedHashSet) {
return CodeBlock.of("new $T($L)", LinkedHashSet.class,
generateCollectionOf(set, List.class, elementType));
}
return super.generateCollectionCode(elementType, orderForCodeConsistency(set));
}
private Set<?> orderForCodeConsistency(Set<?> set) {
try {
return new TreeSet<Object>(set);
}
catch (ClassCastException ex) {
// If elements are not comparable, just keep the original set
return set;
}
}
}
/**
* {@link Delegate} for {@link Map} types.
*/
private class MapDelegate implements Delegate {
private static final CodeBlock EMPTY_RESULT = CodeBlock.of("$T.emptyMap()", Collections.class);
@Override
@Nullable
public CodeBlock generateCode(Object value, ResolvableType type) {
if (value instanceof Map<?, ?> map) {
return generateMapCode(type, map);
}
return null;
}
private <K, V> CodeBlock generateMapCode(ResolvableType type, Map<K, V> map) {
if (map.isEmpty()) {
return EMPTY_RESULT;
}
ResolvableType keyType = type.as(Map.class).getGeneric(0);
ResolvableType valueType = type.as(Map.class).getGeneric(1);
if (map instanceof LinkedHashMap<?, ?>) {
return generateLinkedHashMapCode(map, keyType, valueType);
}
map = orderForCodeConsistency(map);
boolean useOfEntries = map.size() > 10;
CodeBlock.Builder code = CodeBlock.builder();
code.add("$T" + ((!useOfEntries) ? ".of(" : ".ofEntries("), Map.class);
Iterator<Map.Entry<K, V>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Entry<K, V> entry = iterator.next();
CodeBlock keyCode = BeanDefinitionPropertyValueCodeGenerator.this
.generateCodeForElement(entry.getKey(), keyType);
CodeBlock valueCode = BeanDefinitionPropertyValueCodeGenerator.this
.generateCodeForElement(entry.getValue(), valueType);
if (!useOfEntries) {
code.add("$L, $L", keyCode, valueCode);
}
else {
code.add("$T.entry($L,$L)", Map.class, keyCode, valueCode);
}
if (iterator.hasNext()) {
code.add(", ");
}
}
code.add(")");
return code.build();
}
private <K, V> Map<K, V> orderForCodeConsistency(Map<K, V> map) {
try {
return new TreeMap<>(map);
}
catch (ClassCastException ex) {
// If elements are not comparable, just keep the original map
return map;
}
}
private <K, V> CodeBlock generateLinkedHashMapCode(Map<K, V> map,
ResolvableType keyType, ResolvableType valueType) {
GeneratedMethods generatedMethods = BeanDefinitionPropertyValueCodeGenerator.this.generatedMethods;
GeneratedMethod generatedMethod = generatedMethods.add("getMap", method -> {
method.addAnnotation(AnnotationSpec
.builder(SuppressWarnings.class)
.addMember("value", "{\"rawtypes\", \"unchecked\"}")
.build());
method.returns(Map.class);
method.addStatement("$T map = new $T($L)", Map.class,
LinkedHashMap.class, map.size());
map.forEach((key, value) -> method.addStatement("map.put($L, $L)",
BeanDefinitionPropertyValueCodeGenerator.this
.generateCodeForElement(key, keyType),
BeanDefinitionPropertyValueCodeGenerator.this
.generateCodeForElement(value, valueType)));
method.addStatement("return map");
});
return CodeBlock.of("$L()", generatedMethod.getName());
}
}
/**
* {@link Delegate} for {@link BeanReference} types.
*/
private static class BeanReferenceDelegate implements Delegate {
@Override
@Nullable
public CodeBlock generateCode(Object value, ResolvableType type) {
if (value instanceof RuntimeBeanReference runtimeBeanReference &&
runtimeBeanReference.getBeanType() != null) {
return CodeBlock.of("new $T($T.class)", RuntimeBeanReference.class,
runtimeBeanReference.getBeanType());
}
else if (value instanceof BeanReference beanReference) {
return CodeBlock.of("new $T($S)", RuntimeBeanReference.class,
beanReference.getBeanName());
}
return null;
}
}
/**
* {@link Delegate} for {@link TypedStringValue} types.
*/
private class TypedStringValueDelegate implements Delegate {
@Override
public CodeBlock generateCode(Object value, ResolvableType type) {
if (value instanceof TypedStringValue typedStringValue) {
return generateTypeStringValueCode(typedStringValue);
}
return null;
}
private CodeBlock generateTypeStringValueCode(TypedStringValue typedStringValue) {
String value = typedStringValue.getValue();
if (typedStringValue.hasTargetType()) {
return CodeBlock.of("new $T($S, $L)", TypedStringValue.class, value,
generateCode(typedStringValue.getTargetType()));
}
return generateCode(value);
}
private CodeBlock generateCode(@Nullable Object value) {
return BeanDefinitionPropertyValueCodeGenerator.this.generateCode(value);
}
}
}
@@ -1,212 +0,0 @@
/*
* Copyright 2002-2023 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.aot;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.springframework.aot.generate.GeneratedMethod;
import org.springframework.aot.generate.GeneratedMethods;
import org.springframework.aot.generate.ValueCodeGenerator;
import org.springframework.aot.generate.ValueCodeGenerator.Delegate;
import org.springframework.aot.generate.ValueCodeGeneratorDelegates;
import org.springframework.aot.generate.ValueCodeGeneratorDelegates.CollectionDelegate;
import org.springframework.aot.generate.ValueCodeGeneratorDelegates.MapDelegate;
import org.springframework.beans.factory.config.BeanReference;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.support.ManagedSet;
import org.springframework.javapoet.AnnotationSpec;
import org.springframework.javapoet.CodeBlock;
/**
* Code generator {@link Delegate} for common bean definition property values.
*
* @author Stephane Nicoll
* @since 6.1.2
*/
abstract class BeanDefinitionPropertyValueCodeGeneratorDelegates {
/**
* Return the {@link Delegate} implementations for common bean definition
* property value types. These are:
* <ul>
* <li>{@link ManagedList},</li>
* <li>{@link ManagedSet},</li>
* <li>{@link ManagedMap},</li>
* <li>{@link LinkedHashMap},</li>
* <li>{@link BeanReference},</li>
* <li>{@link TypedStringValue}.</li>
* </ul>
* When combined with {@linkplain ValueCodeGeneratorDelegates#INSTANCES the
* delegates for common value types}, this should be added first as they have
* special handling for list, set, and map.
*/
public static final List<Delegate> INSTANCES = List.of(
new ManagedListDelegate(),
new ManagedSetDelegate(),
new ManagedMapDelegate(),
new LinkedHashMapDelegate(),
new BeanReferenceDelegate(),
new TypedStringValueDelegate()
);
/**
* {@link Delegate} for {@link ManagedList} types.
*/
private static class ManagedListDelegate extends CollectionDelegate<ManagedList<?>> {
public ManagedListDelegate() {
super(ManagedList.class, CodeBlock.of("new $T()", ManagedList.class));
}
}
/**
* {@link Delegate} for {@link ManagedSet} types.
*/
private static class ManagedSetDelegate extends CollectionDelegate<ManagedSet<?>> {
public ManagedSetDelegate() {
super(ManagedSet.class, CodeBlock.of("new $T()", ManagedSet.class));
}
}
/**
* {@link Delegate} for {@link ManagedMap} types.
*/
private static class ManagedMapDelegate implements Delegate {
private static final CodeBlock EMPTY_RESULT = CodeBlock.of("$T.ofEntries()", ManagedMap.class);
@Override
public CodeBlock generateCode(ValueCodeGenerator valueCodeGenerator, Object value) {
if (value instanceof ManagedMap<?, ?> managedMap) {
return generateManagedMapCode(valueCodeGenerator, managedMap);
}
return null;
}
private <K, V> CodeBlock generateManagedMapCode(ValueCodeGenerator valueCodeGenerator,
ManagedMap<K, V> managedMap) {
if (managedMap.isEmpty()) {
return EMPTY_RESULT;
}
CodeBlock.Builder code = CodeBlock.builder();
code.add("$T.ofEntries(", ManagedMap.class);
Iterator<Entry<K, V>> iterator = managedMap.entrySet().iterator();
while (iterator.hasNext()) {
Entry<?, ?> entry = iterator.next();
code.add("$T.entry($L,$L)", Map.class,
valueCodeGenerator.generateCode(entry.getKey()),
valueCodeGenerator.generateCode(entry.getValue()));
if (iterator.hasNext()) {
code.add(", ");
}
}
code.add(")");
return code.build();
}
}
/**
* {@link Delegate} for {@link Map} types.
*/
private static class LinkedHashMapDelegate extends MapDelegate {
@Override
protected CodeBlock generateMapCode(ValueCodeGenerator valueCodeGenerator, Map<?, ?> map) {
GeneratedMethods generatedMethods = valueCodeGenerator.getGeneratedMethods();
if (map instanceof LinkedHashMap<?, ?> && generatedMethods != null) {
return generateLinkedHashMapCode(valueCodeGenerator, generatedMethods, map);
}
return super.generateMapCode(valueCodeGenerator, map);
}
private CodeBlock generateLinkedHashMapCode(ValueCodeGenerator valueCodeGenerator,
GeneratedMethods generatedMethods, Map<?, ?> map) {
GeneratedMethod generatedMethod = generatedMethods.add("getMap", method -> {
method.addAnnotation(AnnotationSpec
.builder(SuppressWarnings.class)
.addMember("value", "{\"rawtypes\", \"unchecked\"}")
.build());
method.returns(Map.class);
method.addStatement("$T map = new $T($L)", Map.class,
LinkedHashMap.class, map.size());
map.forEach((key, value) -> method.addStatement("map.put($L, $L)",
valueCodeGenerator.generateCode(key),
valueCodeGenerator.generateCode(value)));
method.addStatement("return map");
});
return CodeBlock.of("$L()", generatedMethod.getName());
}
}
/**
* {@link Delegate} for {@link BeanReference} types.
*/
private static class BeanReferenceDelegate implements Delegate {
@Override
public CodeBlock generateCode(ValueCodeGenerator valueCodeGenerator, Object value) {
if (value instanceof RuntimeBeanReference runtimeBeanReference &&
runtimeBeanReference.getBeanType() != null) {
return CodeBlock.of("new $T($T.class)", RuntimeBeanReference.class,
runtimeBeanReference.getBeanType());
}
else if (value instanceof BeanReference beanReference) {
return CodeBlock.of("new $T($S)", RuntimeBeanReference.class,
beanReference.getBeanName());
}
return null;
}
}
/**
* {@link Delegate} for {@link TypedStringValue} types.
*/
private static class TypedStringValueDelegate implements Delegate {
@Override
public CodeBlock generateCode(ValueCodeGenerator valueCodeGenerator, Object value) {
if (value instanceof TypedStringValue typedStringValue) {
return generateTypeStringValueCode(valueCodeGenerator, typedStringValue);
}
return null;
}
private CodeBlock generateTypeStringValueCode(ValueCodeGenerator valueCodeGenerator, TypedStringValue typedStringValue) {
String value = typedStringValue.getValue();
if (typedStringValue.hasTargetType()) {
return CodeBlock.of("new $T($S, $L)", TypedStringValue.class, value,
valueCodeGenerator.generateCode(typedStringValue.getTargetType()));
}
return valueCodeGenerator.generateCode(value);
}
}
}
@@ -27,10 +27,7 @@ import org.springframework.aot.generate.AccessControl;
import org.springframework.aot.generate.GenerationContext;
import org.springframework.aot.generate.MethodReference;
import org.springframework.aot.generate.MethodReference.ArgumentCodeGenerator;
import org.springframework.aot.generate.ValueCodeGenerator;
import org.springframework.aot.generate.ValueCodeGenerator.Delegate;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.aot.AotServices.Loader;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.InstanceSupplier;
@@ -54,8 +51,6 @@ import org.springframework.util.function.SingletonSupplier;
*/
class DefaultBeanRegistrationCodeFragments implements BeanRegistrationCodeFragments {
private static final ValueCodeGenerator valueCodeGenerator = ValueCodeGenerator.withDefaults();
private final BeanRegistrationsCode beanRegistrationsCode;
private final RegisteredBean registeredBean;
@@ -152,9 +147,9 @@ class DefaultBeanRegistrationCodeFragments implements BeanRegistrationCodeFragme
private CodeBlock generateBeanTypeCode(ResolvableType beanType) {
if (!beanType.hasGenerics()) {
return valueCodeGenerator.generateCode(ClassUtils.getUserClass(beanType.toClass()));
return CodeBlock.of("$T.class", ClassUtils.getUserClass(beanType.toClass()));
}
return valueCodeGenerator.generateCode(beanType);
return ResolvableTypeCodeGenerator.generateCode(beanType);
}
private boolean targetTypeNecessary(ResolvableType beanType, @Nullable Class<?> beanClass) {
@@ -173,12 +168,12 @@ class DefaultBeanRegistrationCodeFragments implements BeanRegistrationCodeFragme
GenerationContext generationContext,
BeanRegistrationCode beanRegistrationCode, RootBeanDefinition beanDefinition,
Predicate<String> attributeFilter) {
Loader loader = AotServices.factories(this.registeredBean.getBeanFactory().getBeanClassLoader());
List<Delegate> additionalDelegates = loader.load(Delegate.class).asList();
return new BeanDefinitionPropertiesCodeGenerator(generationContext.getRuntimeHints(),
attributeFilter, beanRegistrationCode.getMethods(),
additionalDelegates, (name, value) -> generateValueCode(generationContext, name, value)
).generateCode(beanDefinition);
return new BeanDefinitionPropertiesCodeGenerator(
generationContext.getRuntimeHints(), attributeFilter,
beanRegistrationCode.getMethods(),
(name, value) -> generateValueCode(generationContext, name, value))
.generateCode(beanDefinition);
}
@Nullable
@@ -0,0 +1,69 @@
/*
* Copyright 2002-2022 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.aot;
import java.util.Arrays;
import org.springframework.core.ResolvableType;
import org.springframework.javapoet.CodeBlock;
import org.springframework.util.ClassUtils;
/**
* Internal code generator used to support {@link ResolvableType}.
*
* @author Stephane Nicoll
* @author Phillip Webb
* @since 6.0
*/
final class ResolvableTypeCodeGenerator {
private ResolvableTypeCodeGenerator() {
}
public static CodeBlock generateCode(ResolvableType resolvableType) {
return generateCode(resolvableType, false);
}
private static CodeBlock generateCode(ResolvableType resolvableType, boolean allowClassResult) {
if (ResolvableType.NONE.equals(resolvableType)) {
return CodeBlock.of("$T.NONE", ResolvableType.class);
}
Class<?> type = ClassUtils.getUserClass(resolvableType.toClass());
if (resolvableType.hasGenerics() && !resolvableType.hasUnresolvableGenerics()) {
return generateCodeWithGenerics(resolvableType, type);
}
if (allowClassResult) {
return CodeBlock.of("$T.class", type);
}
return CodeBlock.of("$T.forClass($T.class)", ResolvableType.class, type);
}
private static CodeBlock generateCodeWithGenerics(ResolvableType target, Class<?> type) {
ResolvableType[] generics = target.getGenerics();
boolean hasNoNestedGenerics = Arrays.stream(generics).noneMatch(ResolvableType::hasGenerics);
CodeBlock.Builder code = CodeBlock.builder();
code.add("$T.forClassWithGenerics($T.class", ResolvableType.class, type);
for (ResolvableType generic : generics) {
code.add(", $L", generateCode(generic, hasNoNestedGenerics));
}
code.add(")");
return code.build();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 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.
@@ -375,16 +375,6 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
}
}
/**
* Determine whether this dependency supports lazy resolution,
* e.g. through extra proxying. The default is {@code true}.
* @since 6.1.2
* @see org.springframework.beans.factory.support.AutowireCandidateResolver#getLazyResolutionProxyIfNecessary
*/
public boolean supportsLazyResolution() {
return true;
}
@Override
public boolean equals(@Nullable Object other) {
@@ -496,13 +496,15 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
@@ -51,7 +51,6 @@ import org.springframework.util.StringUtils;
* @author Juergen Hoeller
* @author Rob Harrop
* @author Mark Fisher
* @author Sebastien Deleuze
* @see GenericBeanDefinition
* @see RootBeanDefinition
* @see ChildBeanDefinition
@@ -140,18 +139,6 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
*/
public static final String PREFERRED_CONSTRUCTORS_ATTRIBUTE = "preferredConstructors";
/**
* The name of an attribute that can be
* {@link org.springframework.core.AttributeAccessor#setAttribute set} on a
* {@link org.springframework.beans.factory.config.BeanDefinition} so that
* bean definitions can indicate the sort order for the targeted bean.
* This is analogous to the {@code @Order} annotation.
* @since 6.1.2
* @see org.springframework.core.annotation.Order
* @see org.springframework.core.Ordered
*/
public static final String ORDER_ATTRIBUTE = "order";
/**
* Constant that indicates the container should attempt to infer the
* {@link #setDestroyMethodName destroy method name} for a bean as opposed to
@@ -1503,11 +1503,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
if (mbd.hasBeanClass()) {
return mbd.getBeanClass();
}
Class<?> beanClass = doResolveBeanClass(mbd, typesToMatch);
if (mbd.hasBeanClass()) {
mbd.prepareMethodOverrides();
}
return beanClass;
return doResolveBeanClass(mbd, typesToMatch);
}
catch (ClassNotFoundException ex) {
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
@@ -1515,10 +1511,6 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
catch (LinkageError err) {
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
}
@Nullable
@@ -70,7 +70,6 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.config.NamedBeanHolder;
import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations;
@@ -111,7 +110,6 @@ import org.springframework.util.StringUtils;
* @author Chris Beams
* @author Phillip Webb
* @author Stephane Nicoll
* @author Sebastien Deleuze
* @since 16 April 2001
* @see #registerBeanDefinition
* @see #addBeanPostProcessor
@@ -1343,14 +1341,14 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else if (descriptor.supportsLazyResolution()) {
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result != null) {
return result;
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
return doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
@Nullable
@@ -2232,9 +2230,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
* that is aware of the bean metadata of the instances to sort.
* <p>Lookup for the method factory of an instance to sort, if any, and let the
* comparator retrieve the {@link org.springframework.core.annotation.Order}
* value defined on it.
* <p>As of 6.1.2, this class takes the {@link AbstractBeanDefinition#ORDER_ATTRIBUTE}
* attribute into account.
* value defined on it. This essentially allows for the following construct:
*/
private class FactoryAwareOrderSourceProvider implements OrderComparator.OrderSourceProvider {
@@ -2253,17 +2249,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
try {
RootBeanDefinition beanDefinition = (RootBeanDefinition) getMergedBeanDefinition(beanName);
List<Object> sources = new ArrayList<>(3);
Object orderAttribute = beanDefinition.getAttribute(AbstractBeanDefinition.ORDER_ATTRIBUTE);
if (orderAttribute != null) {
if (orderAttribute instanceof Integer order) {
sources.add((Ordered) () -> order);
}
else {
throw new IllegalStateException("Invalid value type for attribute '" +
AbstractBeanDefinition.ORDER_ATTRIBUTE + "': " + orderAttribute.getClass().getName());
}
}
List<Object> sources = new ArrayList<>(2);
Method factoryMethod = beanDefinition.getResolvedFactoryMethod();
if (factoryMethod != null) {
sources.add(factoryMethod);
@@ -72,7 +72,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
Class<?> clazz = bd.getBeanClass();
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
@@ -105,7 +105,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
Constructor<?> ctor, Object... args) {
final Constructor<?> ctor, Object... args) {
if (!bd.hasMethodOverrides()) {
return BeanUtils.instantiateClass(ctor, args);
@@ -129,7 +129,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, Method factoryMethod, Object... args) {
@Nullable Object factoryBean, final Method factoryMethod, Object... args) {
try {
ReflectionUtils.makeAccessible(factoryMethod);
@@ -153,7 +153,8 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
}
}
catch (IllegalArgumentException ex) {
if (factoryBean != null && !factoryMethod.getDeclaringClass().isAssignableFrom(factoryBean.getClass())) {
if (factoryBean != null
&& !factoryMethod.getDeclaringClass().isAssignableFrom(factoryBean.getClass())) {
throw new BeanInstantiationException(factoryMethod,
"Illegal factory instance for factory method '" + factoryMethod.getName() + "'; " +
"instance: " + factoryBean.getClass().getName(), ex);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2022 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.
@@ -78,10 +78,8 @@ public class PathEditor extends PropertyEditorSupport {
if (nioPathCandidate && !text.startsWith("/")) {
try {
URI uri = ResourceUtils.toURI(text);
String scheme = uri.getScheme();
if (scheme != null) {
// No NIO candidate except for "C:" style drive letters
nioPathCandidate = (scheme.length() == 1);
if (uri.getScheme() != null) {
nioPathCandidate = false;
// Let's try NIO file system providers via Paths.get(URI)
setValue(Paths.get(uri).normalize());
return;
@@ -111,8 +109,7 @@ public class PathEditor extends PropertyEditorSupport {
setValue(resource.getFile().toPath());
}
catch (IOException ex) {
throw new IllegalArgumentException(
"Could not retrieve file for " + resource + ": " + ex.getMessage());
throw new IllegalArgumentException("Failed to retrieve file for " + resource, ex);
}
}
}
@@ -406,7 +406,6 @@ abstract class AbstractPropertyAccessorTests {
}
@Test
@SuppressWarnings("unchecked")
void setPropertyIntermediateListIsNullWithAutoGrow() {
Foo target = new Foo();
AbstractPropertyAccessor accessor = createAccessor(target);
@@ -415,7 +414,7 @@ abstract class AbstractPropertyAccessorTests {
Map<String, String> map = new HashMap<>();
map.put("favoriteNumber", "9");
accessor.setPropertyValue("list[0]", map);
assertThat(target.list).element(0).isEqualTo(map);
assertThat(target.list.get(0)).isEqualTo(map);
}
@Test
@@ -1144,12 +1143,12 @@ abstract class AbstractPropertyAccessorTests {
assertThat(target.getSet()).hasSize(1);
assertThat(target.getSet().contains("set1")).isTrue();
assertThat(target.getSortedSet()).hasSize(1);
assertThat(target.getSortedSet()).contains("sortedSet1");
assertThat(target.getSortedSet().contains("sortedSet1")).isTrue();
assertThat(target.getList()).hasSize(1);
assertThat(target.getList()).contains("list1");
assertThat(target.getList().contains("list1")).isTrue();
accessor.setPropertyValue("list", Collections.singletonList("list1 "));
assertThat(target.getList()).contains("list1");
assertThat(target.getList().contains("list1")).isTrue();
}
@Test
@@ -0,0 +1,55 @@
/*
* Copyright 2002-2023 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans;
import java.util.HashMap;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Rod Johnson
* @author Chris Beams
*/
public abstract class AbstractPropertyValuesTests {
/**
* Must contain: forname=Tony surname=Blair age=50
*/
protected void doTestTony(PropertyValues pvs) {
assertThat(pvs.getPropertyValues()).as("Contains 3").hasSize(3);
assertThat(pvs.contains("forname")).as("Contains forname").isTrue();
assertThat(pvs.contains("surname")).as("Contains surname").isTrue();
assertThat(pvs.contains("age")).as("Contains age").isTrue();
assertThat(!pvs.contains("tory")).as("Doesn't contain tory").isTrue();
PropertyValue[] ps = pvs.getPropertyValues();
Map<String, String> m = new HashMap<>();
m.put("forname", "Tony");
m.put("surname", "Blair");
m.put("age", "50");
for (PropertyValue element : ps) {
Object val = m.get(element.getName());
assertThat(val).as("Can't have unexpected value").isNotNull();
assertThat(val instanceof String).as("Val i string").isTrue();
assertThat(val.equals(element.getValue())).as("val matches expected").isTrue();
m.remove(element.getName());
}
assertThat(m).as("Map size is 0").isEmpty();
}
}
@@ -126,7 +126,7 @@ public class BeanWrapperAutoGrowingTests {
public void getPropertyValueAutoGrowList() {
assertNotNull(wrapper.getPropertyValue("list[0]"));
assertThat(bean.getList()).hasSize(1);
assertThat(bean.getList()).element(0).isInstanceOf(Bean.class);
assertThat(bean.getList().get(0)).isInstanceOf(Bean.class);
}
@Test
@@ -139,11 +139,11 @@ public class BeanWrapperAutoGrowingTests {
public void getPropertyValueAutoGrowListBySeveralElements() {
assertNotNull(wrapper.getPropertyValue("list[4]"));
assertThat(bean.getList()).hasSize(5);
assertThat(bean.getList()).element(0).isInstanceOf(Bean.class);
assertThat(bean.getList()).element(1).isInstanceOf(Bean.class);
assertThat(bean.getList()).element(2).isInstanceOf(Bean.class);
assertThat(bean.getList()).element(3).isInstanceOf(Bean.class);
assertThat(bean.getList()).element(4).isInstanceOf(Bean.class);
assertThat(bean.getList().get(0)).isInstanceOf(Bean.class);
assertThat(bean.getList().get(1)).isInstanceOf(Bean.class);
assertThat(bean.getList().get(2)).isInstanceOf(Bean.class);
assertThat(bean.getList().get(3)).isInstanceOf(Bean.class);
assertThat(bean.getList().get(4)).isInstanceOf(Bean.class);
assertNotNull(wrapper.getPropertyValue("list[0]"));
assertNotNull(wrapper.getPropertyValue("list[1]"));
assertNotNull(wrapper.getPropertyValue("list[2]"));
@@ -161,8 +161,8 @@ public class BeanWrapperAutoGrowingTests {
@Test
public void getPropertyValueAutoGrowMultiDimensionalList() {
assertNotNull(wrapper.getPropertyValue("multiList[0][0]"));
assertThat(bean.getMultiList()).element(0).asList().hasSize(1);
assertThat(bean.getMultiList().get(0)).element(0).isInstanceOf(Bean.class);
assertThat(bean.getMultiList().get(0)).hasSize(1);
assertThat(bean.getMultiList().get(0).get(0)).isInstanceOf(Bean.class);
}
@Test
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2022 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.
@@ -92,7 +92,7 @@ public class BeanWrapperEnumTests {
BeanWrapper bw = new BeanWrapperImpl(gb);
bw.setPropertyValue("customEnumSet", "VALUE_1");
assertThat(gb.getCustomEnumSet()).hasSize(1);
assertThat(gb.getCustomEnumSet()).contains(CustomEnum.VALUE_1);
assertThat(gb.getCustomEnumSet().contains(CustomEnum.VALUE_1)).isTrue();
}
@Test
@@ -101,8 +101,8 @@ public class BeanWrapperEnumTests {
BeanWrapper bw = new BeanWrapperImpl(gb);
bw.setPropertyValue("customEnumSet", new String[] {"VALUE_1", "VALUE_2"});
assertThat(gb.getCustomEnumSet()).hasSize(2);
assertThat(gb.getCustomEnumSet()).contains(CustomEnum.VALUE_1);
assertThat(gb.getCustomEnumSet()).contains(CustomEnum.VALUE_2);
assertThat(gb.getCustomEnumSet().contains(CustomEnum.VALUE_1)).isTrue();
assertThat(gb.getCustomEnumSet().contains(CustomEnum.VALUE_2)).isTrue();
}
@Test
@@ -111,8 +111,8 @@ public class BeanWrapperEnumTests {
BeanWrapper bw = new BeanWrapperImpl(gb);
bw.setPropertyValue("customEnumSet", "VALUE_1,VALUE_2");
assertThat(gb.getCustomEnumSet()).hasSize(2);
assertThat(gb.getCustomEnumSet()).contains(CustomEnum.VALUE_1);
assertThat(gb.getCustomEnumSet()).contains(CustomEnum.VALUE_2);
assertThat(gb.getCustomEnumSet().contains(CustomEnum.VALUE_1)).isTrue();
assertThat(gb.getCustomEnumSet().contains(CustomEnum.VALUE_2)).isTrue();
}
@Test
@@ -121,8 +121,8 @@ public class BeanWrapperEnumTests {
BeanWrapper bw = new BeanWrapperImpl(gb);
bw.setPropertyValue("customEnumSetMismatch", new String[] {"VALUE_1", "VALUE_2"});
assertThat(gb.getCustomEnumSet()).hasSize(2);
assertThat(gb.getCustomEnumSet()).contains(CustomEnum.VALUE_1);
assertThat(gb.getCustomEnumSet()).contains(CustomEnum.VALUE_2);
assertThat(gb.getCustomEnumSet().contains(CustomEnum.VALUE_1)).isTrue();
assertThat(gb.getCustomEnumSet().contains(CustomEnum.VALUE_2)).isTrue();
}
@Test
@@ -133,8 +133,8 @@ public class BeanWrapperEnumTests {
assertThat(gb.getStandardEnumSet()).isNull();
bw.setPropertyValue("standardEnumSet", new String[] {"VALUE_1", "VALUE_2"});
assertThat(gb.getStandardEnumSet()).hasSize(2);
assertThat(gb.getStandardEnumSet()).contains(CustomEnum.VALUE_1);
assertThat(gb.getStandardEnumSet()).contains(CustomEnum.VALUE_2);
assertThat(gb.getStandardEnumSet().contains(CustomEnum.VALUE_1)).isTrue();
assertThat(gb.getStandardEnumSet().contains(CustomEnum.VALUE_2)).isTrue();
}
@Test
@@ -39,7 +39,6 @@ import org.springframework.core.io.UrlResource;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import static java.util.Map.entry;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -58,8 +57,8 @@ class BeanWrapperGenericsTests {
input.add("4");
input.add("5");
bw.setPropertyValue("integerSet", input);
assertThat(gb.getIntegerSet()).contains(4);
assertThat(gb.getIntegerSet()).contains(5);
assertThat(gb.getIntegerSet().contains(4)).isTrue();
assertThat(gb.getIntegerSet().contains(5)).isTrue();
}
@Test
@@ -94,8 +93,8 @@ class BeanWrapperGenericsTests {
input.add("http://localhost:8080");
input.add("http://localhost:9090");
bw.setPropertyValue("resourceList", input);
assertThat(gb.getResourceList()).element(0).isEqualTo(new UrlResource("http://localhost:8080"));
assertThat(gb.getResourceList()).element(1).isEqualTo(new UrlResource("http://localhost:9090"));
assertThat(gb.getResourceList().get(0)).isEqualTo(new UrlResource("http://localhost:8080"));
assertThat(gb.getResourceList().get(1)).isEqualTo(new UrlResource("http://localhost:9090"));
}
@Test
@@ -104,7 +103,7 @@ class BeanWrapperGenericsTests {
gb.setResourceList(new ArrayList<>());
BeanWrapper bw = new BeanWrapperImpl(gb);
bw.setPropertyValue("resourceList[0]", "http://localhost:8080");
assertThat(gb.getResourceList()).element(0).isEqualTo(new UrlResource("http://localhost:8080"));
assertThat(gb.getResourceList().get(0)).isEqualTo(new UrlResource("http://localhost:8080"));
}
@Test
@@ -201,7 +200,7 @@ class BeanWrapperGenericsTests {
BeanWrapper bw = new BeanWrapperImpl(gb);
bw.setPropertyValue("listOfLists[0][0]", 5);
assertThat(bw.getPropertyValue("listOfLists[0][0]")).isEqualTo(5);
assertThat(gb.getListOfLists().get(0)).element(0).isEqualTo(5);
assertThat(gb.getListOfLists().get(0).get(0)).isEqualTo(5);
}
@Test
@@ -213,7 +212,7 @@ class BeanWrapperGenericsTests {
BeanWrapper bw = new BeanWrapperImpl(gb);
bw.setPropertyValue("listOfLists[0][0]", "5");
assertThat(bw.getPropertyValue("listOfLists[0][0]")).isEqualTo(5);
assertThat(gb.getListOfLists().get(0)).element(0).isEqualTo(5);
assertThat(gb.getListOfLists().get(0).get(0)).isEqualTo(5);
}
@Test
@@ -298,7 +297,7 @@ class BeanWrapperGenericsTests {
BeanWrapper bw = new BeanWrapperImpl(gb);
bw.setPropertyValue("mapOfLists[1][0]", 5);
assertThat(bw.getPropertyValue("mapOfLists[1][0]")).isEqualTo(5);
assertThat(gb.getMapOfLists().get(1)).element(0).isEqualTo(5);
assertThat(gb.getMapOfLists().get(1).get(0)).isEqualTo(5);
}
@Test
@@ -310,7 +309,7 @@ class BeanWrapperGenericsTests {
BeanWrapper bw = new BeanWrapperImpl(gb);
bw.setPropertyValue("mapOfLists[1][0]", "5");
assertThat(bw.getPropertyValue("mapOfLists[1][0]")).isEqualTo(5);
assertThat(gb.getMapOfLists().get(1)).element(0).isEqualTo(5);
assertThat(gb.getMapOfLists().get(1).get(0)).isEqualTo(5);
}
@Test
@@ -385,7 +384,8 @@ class BeanWrapperGenericsTests {
BeanWrapper bw = new BeanWrapperImpl(holder);
bw.setPropertyValue("genericMap", inputMap);
assertThat(holder.getGenericMap()).containsOnly(entry(List.of(1), List.of(10L)));
assertThat(holder.getGenericMap().keySet().iterator().next().get(0)).isEqualTo(1);
assertThat(holder.getGenericMap().values().iterator().next().get(0)).isEqualTo(Long.valueOf(10));
}
@Test
@@ -401,7 +401,8 @@ class BeanWrapperGenericsTests {
BeanWrapper bw = new BeanWrapperImpl(holder);
bw.setPropertyValue("genericMap", inputMap);
assertThat(holder.getGenericMap()).containsOnly(entry(List.of(1), List.of(10L)));
assertThat(holder.getGenericMap().keySet().iterator().next().get(0)).isEqualTo(1);
assertThat(holder.getGenericMap().values().iterator().next().get(0)).isEqualTo(Long.valueOf(10));
}
@Test
@@ -413,7 +414,8 @@ class BeanWrapperGenericsTests {
BeanWrapper bw = new BeanWrapperImpl(holder);
bw.setPropertyValue("genericIndexedMap[1]", inputValue);
assertThat(holder.getGenericIndexedMap()).containsOnly(entry(1, List.of(10L)));
assertThat(holder.getGenericIndexedMap().keySet().iterator().next()).isEqualTo(1);
assertThat(holder.getGenericIndexedMap().values().iterator().next().get(0)).isEqualTo(Long.valueOf(10));
}
@Test
@@ -425,7 +427,8 @@ class BeanWrapperGenericsTests {
BeanWrapper bw = new BeanWrapperImpl(holder);
bw.setPropertyValue("genericIndexedMap[1]", inputValue);
assertThat(holder.getGenericIndexedMap()).containsOnly(entry(1, List.of(10L)));
assertThat(holder.getGenericIndexedMap().keySet().iterator().next()).isEqualTo(1);
assertThat(holder.getGenericIndexedMap().values().iterator().next().get(0)).isEqualTo(Long.valueOf(10));
}
@Test
@@ -436,7 +439,8 @@ class BeanWrapperGenericsTests {
BeanWrapper bw = new BeanWrapperImpl(holder);
bw.setPropertyValue("genericIndexedMap[1]", inputValue);
assertThat(holder.getGenericIndexedMap()).containsOnly(entry(1, List.of(10L)));
assertThat(holder.getGenericIndexedMap().keySet().iterator().next()).isEqualTo(1);
assertThat(holder.getGenericIndexedMap().values().iterator().next().get(0)).isEqualTo(Long.valueOf(10));
}
@Test
@@ -448,7 +452,8 @@ class BeanWrapperGenericsTests {
BeanWrapper bw = new BeanWrapperImpl(holder);
bw.setPropertyValue("derivedIndexedMap[1]", inputValue);
assertThat(holder.getDerivedIndexedMap()).containsOnly(entry(1, List.of(10L)));
assertThat(holder.getDerivedIndexedMap().keySet().iterator().next()).isEqualTo(1);
assertThat(holder.getDerivedIndexedMap().values().iterator().next().get(0)).isEqualTo(Long.valueOf(10));
}
@Test
@@ -460,7 +465,8 @@ class BeanWrapperGenericsTests {
BeanWrapper bw = new BeanWrapperImpl(holder);
bw.setPropertyValue("derivedIndexedMap[1]", inputValue);
assertThat(holder.getDerivedIndexedMap()).containsOnly(entry(1, List.of(10L)));
assertThat(holder.getDerivedIndexedMap().keySet().iterator().next()).isEqualTo(1);
assertThat(holder.getDerivedIndexedMap().values().iterator().next().get(0)).isEqualTo(Long.valueOf(10));
}
@Test
@@ -471,7 +477,8 @@ class BeanWrapperGenericsTests {
BeanWrapper bw = new BeanWrapperImpl(holder);
bw.setPropertyValue("derivedIndexedMap[1]", inputValue);
assertThat(holder.getDerivedIndexedMap()).containsOnly(entry(1, List.of(10L)));
assertThat(holder.getDerivedIndexedMap().keySet().iterator().next()).isEqualTo(1);
assertThat(holder.getDerivedIndexedMap().values().iterator().next().get(0)).isEqualTo(Long.valueOf(10));
}
@Test
@@ -483,7 +490,8 @@ class BeanWrapperGenericsTests {
BeanWrapper bw = new BeanWrapperImpl(holder);
bw.setPropertyValue("multiValueMap[1]", inputValue);
assertThat(holder.getMultiValueMap()).containsOnly(entry(1, List.of(10L)));
assertThat(holder.getMultiValueMap().keySet().iterator().next()).isEqualTo(1);
assertThat(holder.getMultiValueMap().values().iterator().next().get(0)).isEqualTo(Long.valueOf(10));
}
@Test
@@ -495,7 +503,8 @@ class BeanWrapperGenericsTests {
BeanWrapper bw = new BeanWrapperImpl(holder);
bw.setPropertyValue("multiValueMap[1]", inputValue);
assertThat(holder.getMultiValueMap()).containsOnly(entry(1, List.of(10L)));
assertThat(holder.getMultiValueMap().keySet().iterator().next()).isEqualTo(1);
assertThat(holder.getMultiValueMap().values().iterator().next().get(0)).isEqualTo(Long.valueOf(10));
}
@Test
@@ -506,7 +515,8 @@ class BeanWrapperGenericsTests {
BeanWrapper bw = new BeanWrapperImpl(holder);
bw.setPropertyValue("multiValueMap[1]", inputValue);
assertThat(holder.getMultiValueMap()).containsOnly(entry(1, List.of(10L)));
assertThat(holder.getMultiValueMap().keySet().iterator().next()).isEqualTo(1);
assertThat(holder.getMultiValueMap().values().iterator().next().get(0)).isEqualTo(Long.valueOf(10));
}
@Test
@@ -516,8 +526,8 @@ class BeanWrapperGenericsTests {
bw.setPropertyValue("genericProperty", "10");
bw.setPropertyValue("genericListProperty", new String[] {"20", "30"});
assertThat(gb.getGenericProperty()).isEqualTo(10);
assertThat(gb.getGenericListProperty()).element(0).isEqualTo(20);
assertThat(gb.getGenericListProperty()).element(1).isEqualTo(30);
assertThat(gb.getGenericListProperty().get(0)).isEqualTo(20);
assertThat(gb.getGenericListProperty().get(1)).isEqualTo(30);
}
@Test
@@ -526,9 +536,9 @@ class BeanWrapperGenericsTests {
BeanWrapper bw = new BeanWrapperImpl(gb);
bw.setPropertyValue("genericProperty", "10");
bw.setPropertyValue("genericListProperty", new String[] {"20", "30"});
assertThat(gb.getGenericProperty()).element(0).isEqualTo(10);
assertThat(gb.getGenericListProperty().get(0)).element(0).isEqualTo(20);
assertThat(gb.getGenericListProperty().get(1)).element(0).isEqualTo(30);
assertThat(gb.getGenericProperty().iterator().next()).isEqualTo(10);
assertThat(gb.getGenericListProperty().get(0).iterator().next()).isEqualTo(20);
assertThat(gb.getGenericListProperty().get(1).iterator().next()).isEqualTo(30);
}
@Test
@@ -16,9 +16,7 @@
package org.springframework.beans;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.junit.jupiter.api.Test;
@@ -32,10 +30,10 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
* @author Chris Beams
* @author Juergen Hoeller
*/
class MutablePropertyValuesTests {
public class MutablePropertyValuesTests extends AbstractPropertyValuesTests {
@Test
void valid() {
public void testValid() {
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.addPropertyValue(new PropertyValue("forname", "Tony"));
pvs.addPropertyValue(new PropertyValue("surname", "Blair"));
@@ -50,7 +48,7 @@ class MutablePropertyValuesTests {
}
@Test
void addOrOverride() {
public void testAddOrOverride() {
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.addPropertyValue(new PropertyValue("forname", "Tony"));
pvs.addPropertyValue(new PropertyValue("surname", "Blair"));
@@ -58,25 +56,25 @@ class MutablePropertyValuesTests {
doTestTony(pvs);
PropertyValue addedPv = new PropertyValue("rod", "Rod");
pvs.addPropertyValue(addedPv);
assertThat(pvs.getPropertyValue("rod")).isEqualTo(addedPv);
assertThat(pvs.getPropertyValue("rod").equals(addedPv)).isTrue();
PropertyValue changedPv = new PropertyValue("forname", "Greg");
pvs.addPropertyValue(changedPv);
assertThat(pvs.getPropertyValue("forname")).isEqualTo(changedPv);
assertThat(pvs.getPropertyValue("forname").equals(changedPv)).isTrue();
}
@Test
void changesOnEquals() {
public void testChangesOnEquals() {
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.addPropertyValue(new PropertyValue("forname", "Tony"));
pvs.addPropertyValue(new PropertyValue("surname", "Blair"));
pvs.addPropertyValue(new PropertyValue("age", "50"));
MutablePropertyValues pvs2 = pvs;
PropertyValues changes = pvs2.changesSince(pvs);
assertThat(changes.getPropertyValues()).as("changes are empty").isEmpty();
assertThat(changes.getPropertyValues().length).as("changes are empty").isEqualTo(0);
}
@Test
void changeOfOneField() {
public void testChangeOfOneField() {
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.addPropertyValue(new PropertyValue("forname", "Tony"));
pvs.addPropertyValue(new PropertyValue("surname", "Blair"));
@@ -84,31 +82,33 @@ class MutablePropertyValuesTests {
MutablePropertyValues pvs2 = new MutablePropertyValues(pvs);
PropertyValues changes = pvs2.changesSince(pvs);
assertThat(changes.getPropertyValues()).as("changes").isEmpty();
assertThat(changes.getPropertyValues().length).as("changes are empty, not of length " + changes.getPropertyValues().length)
.isEqualTo(0);
pvs2.addPropertyValue(new PropertyValue("forname", "Gordon"));
changes = pvs2.changesSince(pvs);
assertThat(changes.getPropertyValues()).as("1 change").hasSize(1);
assertThat(changes.getPropertyValues().length).as("1 change").isEqualTo(1);
PropertyValue fn = changes.getPropertyValue("forname");
assertThat(fn).as("change is forname").isNotNull();
assertThat(fn.getValue()).isEqualTo("Gordon");
assertThat(fn.getValue().equals("Gordon")).as("new value is gordon").isTrue();
MutablePropertyValues pvs3 = new MutablePropertyValues(pvs);
changes = pvs3.changesSince(pvs);
assertThat(changes.getPropertyValues()).as("changes").isEmpty();
assertThat(changes.getPropertyValues().length).as("changes are empty, not of length " + changes.getPropertyValues().length)
.isEqualTo(0);
// add new
pvs3.addPropertyValue(new PropertyValue("foo", "bar"));
pvs3.addPropertyValue(new PropertyValue("fi", "fum"));
changes = pvs3.changesSince(pvs);
assertThat(changes.getPropertyValues()).as("2 changes").hasSize(2);
assertThat(changes.getPropertyValues().length).as("2 change").isEqualTo(2);
fn = changes.getPropertyValue("foo");
assertThat(fn).as("change in foo").isNotNull();
assertThat(fn.getValue()).isEqualTo("bar");
assertThat(fn.getValue().equals("bar")).as("new value is bar").isTrue();
}
@Test
void iteratorContainsPropertyValue() {
public void iteratorContainsPropertyValue() {
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.add("foo", "bar");
@@ -122,55 +122,28 @@ class MutablePropertyValuesTests {
}
@Test
void iteratorIsEmptyForEmptyValues() {
public void iteratorIsEmptyForEmptyValues() {
MutablePropertyValues pvs = new MutablePropertyValues();
Iterator<PropertyValue> it = pvs.iterator();
assertThat(it.hasNext()).isFalse();
}
@Test
void streamContainsPropertyValue() {
public void streamContainsPropertyValue() {
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.add("foo", "bar");
assertThat(pvs.stream()).isNotNull();
assertThat(pvs.stream()).hasSize(1);
assertThat(pvs.stream()).anyMatch(pv -> "foo".equals(pv.getName()) && "bar".equals(pv.getValue()));
assertThat(pvs.stream()).noneMatch(pv -> "bar".equals(pv.getName()) && "foo".equals(pv.getValue()));
assertThat(pvs.stream().count()).isEqualTo(1L);
assertThat(pvs.stream().anyMatch(pv -> "foo".equals(pv.getName()) && "bar".equals(pv.getValue()))).isTrue();
assertThat(pvs.stream().anyMatch(pv -> "bar".equals(pv.getName()) && "foo".equals(pv.getValue()))).isFalse();
}
@Test
void streamIsEmptyForEmptyValues() {
public void streamIsEmptyForEmptyValues() {
MutablePropertyValues pvs = new MutablePropertyValues();
assertThat(pvs.stream()).isNotNull();
assertThat(pvs.stream()).isEmpty();
}
/**
* Must contain: forname=Tony surname=Blair age=50
*/
protected void doTestTony(PropertyValues pvs) {
PropertyValue[] propertyValues = pvs.getPropertyValues();
assertThat(propertyValues).hasSize(3);
assertThat(pvs.contains("forname")).as("Contains forname").isTrue();
assertThat(pvs.contains("surname")).as("Contains surname").isTrue();
assertThat(pvs.contains("age")).as("Contains age").isTrue();
assertThat(pvs.contains("tory")).as("Doesn't contain tory").isFalse();
Map<String, String> map = new HashMap<>();
map.put("forname", "Tony");
map.put("surname", "Blair");
map.put("age", "50");
for (PropertyValue element : propertyValues) {
Object val = map.get(element.getName());
assertThat(val).as("Can't have unexpected value").isNotNull();
assertThat(val).isInstanceOf(String.class);
assertThat(val).isEqualTo(element.getValue());
map.remove(element.getName());
}
assertThat(map).isEmpty();
assertThat(pvs.stream().count()).isEqualTo(0L);
}
}
@@ -112,7 +112,7 @@ public class BeanFactoryUtilsTests {
List<String> names = Arrays.asList(
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory, IndexedTestBean.class));
assertThat(names).hasSize(1);
assertThat(names).contains("indexedBean");
assertThat(names.contains("indexedBean")).isTrue();
// Distinguish from default ListableBeanFactory behavior
assertThat(listableBeanFactory.getBeanNamesForType(IndexedTestBean.class)).isEmpty();
}
@@ -123,10 +123,10 @@ public class BeanFactoryUtilsTests {
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class));
// includes 2 TestBeans from FactoryBeans (DummyFactory definitions)
assertThat(names).hasSize(4);
assertThat(names).contains("test");
assertThat(names).contains("test3");
assertThat(names).contains("testFactory1");
assertThat(names).contains("testFactory2");
assertThat(names.contains("test")).isTrue();
assertThat(names.contains("test3")).isTrue();
assertThat(names.contains("testFactory1")).isTrue();
assertThat(names.contains("testFactory2")).isTrue();
}
@Test
@@ -134,7 +134,7 @@ public class BeanFactoryUtilsTests {
StaticListableBeanFactory lbf = new StaticListableBeanFactory();
lbf.addBean("foo", new Object());
Map<String, ?> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, ITestBean.class, true, false);
assertThat(beans).isEmpty();
assertThat(beans.isEmpty()).isTrue();
}
@Test
@@ -155,7 +155,7 @@ public class BeanFactoryUtilsTests {
assertThat(beans.get("t1")).isEqualTo(t1);
assertThat(beans.get("t2")).isEqualTo(t2);
assertThat(beans.get("t3")).isEqualTo(t3.getObject());
assertThat(beans.get("t4")).isInstanceOf(TestBean.class);
assertThat(beans.get("t4") instanceof TestBean).isTrue();
beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, DummyFactory.class, true, true);
assertThat(beans).hasSize(2);
@@ -191,7 +191,7 @@ public class BeanFactoryUtilsTests {
assertThat(beans.get("t1")).isEqualTo(t1);
assertThat(beans.get("t2")).isEqualTo(t2);
assertThat(beans.get("t3")).isEqualTo(t3.getObject());
assertThat(beans.get("t4")).isInstanceOf(TestBean.class);
assertThat(beans.get("t4") instanceof TestBean).isTrue();
// t3 and t4 are found here as of Spring 2.0, since they are pre-registered
// singleton instances, while testFactory1 and testFactory are *not* found
// because they are FactoryBean definitions that haven't been initialized yet.
@@ -210,11 +210,11 @@ public class BeanFactoryUtilsTests {
assertThat(beans.get("test3")).isEqualTo(test3);
assertThat(beans.get("test")).isEqualTo(test);
assertThat(beans.get("testFactory1")).isEqualTo(testFactory1);
assertThat(beans.get("testFactory2")).isInstanceOf(TestBean.class);
assertThat(beans.get("testFactory2") instanceof TestBean).isTrue();
assertThat(beans.get("t1")).isEqualTo(t1);
assertThat(beans.get("t2")).isEqualTo(t2);
assertThat(beans.get("t3")).isEqualTo(t3.getObject());
assertThat(beans.get("t4")).isInstanceOf(TestBean.class);
assertThat(beans.get("t4") instanceof TestBean).isTrue();
beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, DummyFactory.class, true, true);
assertThat(beans).hasSize(4);
@@ -257,7 +257,7 @@ public class BeanFactoryUtilsTests {
assertThat(beans.get("test3")).isEqualTo(test3);
assertThat(beans.get("test")).isEqualTo(test);
assertThat(beans.get("testFactory1")).isEqualTo(testFactory1);
assertThat(beans.get("testFactory2")).isInstanceOf(TestBean.class);
assertThat(beans.get("testFactory2") instanceof TestBean).isTrue();
beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, DummyFactory.class, true, true);
assertThat(beans).hasSize(2);
@@ -282,7 +282,7 @@ public class BeanFactoryUtilsTests {
List<String> names = Arrays.asList(
BeanFactoryUtils.beanNamesForAnnotationIncludingAncestors(this.listableBeanFactory, TestAnnotation.class));
assertThat(names).hasSize(1);
assertThat(names).contains("annotatedBean");
assertThat(names.contains("annotatedBean")).isTrue();
// Distinguish from default ListableBeanFactory behavior
assertThat(listableBeanFactory.getBeanNamesForAnnotation(TestAnnotation.class)).isEmpty();
}
@@ -294,8 +294,8 @@ public class BeanFactoryUtilsTests {
List<String> names = Arrays.asList(
BeanFactoryUtils.beanNamesForAnnotationIncludingAncestors(this.listableBeanFactory, TestAnnotation.class));
assertThat(names).hasSize(2);
assertThat(names).contains("annotatedBean");
assertThat(names).contains("anotherAnnotatedBean");
assertThat(names.contains("annotatedBean")).isTrue();
assertThat(names.contains("anotherAnnotatedBean")).isTrue();
}
@Test
@@ -79,11 +79,9 @@ import org.springframework.beans.testfixture.beans.TestBean;
import org.springframework.beans.testfixture.beans.factory.DummyFactory;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.MethodParameter;
import org.springframework.core.Ordered;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.annotation.Order;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.core.io.Resource;
@@ -1486,55 +1484,6 @@ class DefaultListableBeanFactoryTests {
assertThat(bean.getSpouse2()).isNull();
}
@Test
void orderFromAttribute() {
GenericBeanDefinition bd1 = new GenericBeanDefinition();
bd1.setBeanClass(TestBean.class);
bd1.setPropertyValues(new MutablePropertyValues(List.of(new PropertyValue("name", "lowest"))));
bd1.setAttribute(AbstractBeanDefinition.ORDER_ATTRIBUTE, Ordered.LOWEST_PRECEDENCE);
lbf.registerBeanDefinition("bean1", bd1);
GenericBeanDefinition bd2 = new GenericBeanDefinition();
bd2.setBeanClass(TestBean.class);
bd2.setPropertyValues(new MutablePropertyValues(List.of(new PropertyValue("name", "highest"))));
bd2.setAttribute(AbstractBeanDefinition.ORDER_ATTRIBUTE, Ordered.HIGHEST_PRECEDENCE);
lbf.registerBeanDefinition("bean2", bd2);
assertThat(lbf.getBeanProvider(TestBean.class).orderedStream().map(TestBean::getName))
.containsExactly("highest", "lowest");
}
@Test
void orderFromAttributeOverrideAnnotation() {
lbf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
RootBeanDefinition rbd1 = new RootBeanDefinition(LowestPrecedenceTestBeanFactoryBean.class);
rbd1.setAttribute(AbstractBeanDefinition.ORDER_ATTRIBUTE, Ordered.HIGHEST_PRECEDENCE);
lbf.registerBeanDefinition("lowestPrecedenceFactory", rbd1);
RootBeanDefinition rbd2 = new RootBeanDefinition(HighestPrecedenceTestBeanFactoryBean.class);
rbd2.setAttribute(AbstractBeanDefinition.ORDER_ATTRIBUTE, Ordered.LOWEST_PRECEDENCE);
lbf.registerBeanDefinition("highestPrecedenceFactory", rbd2);
GenericBeanDefinition bd1 = new GenericBeanDefinition();
bd1.setFactoryBeanName("highestPrecedenceFactory");
lbf.registerBeanDefinition("bean1", bd1);
GenericBeanDefinition bd2 = new GenericBeanDefinition();
bd2.setFactoryBeanName("lowestPrecedenceFactory");
lbf.registerBeanDefinition("bean2", bd2);
assertThat(lbf.getBeanProvider(TestBean.class).orderedStream().map(TestBean::getName))
.containsExactly("fromLowestPrecedenceTestBeanFactoryBean", "fromHighestPrecedenceTestBeanFactoryBean");
}
@Test
void invalidOrderAttribute() {
GenericBeanDefinition bd1 = new GenericBeanDefinition();
bd1.setBeanClass(TestBean.class);
bd1.setAttribute(AbstractBeanDefinition.ORDER_ATTRIBUTE, Boolean.TRUE);
lbf.registerBeanDefinition("bean1", bd1);
GenericBeanDefinition bd2 = new GenericBeanDefinition();
bd2.setBeanClass(TestBean.class);
lbf.registerBeanDefinition("bean", bd2);
assertThatIllegalStateException()
.isThrownBy(() -> lbf.getBeanProvider(TestBean.class).orderedStream().collect(Collectors.toList()))
.withMessageContaining("Invalid value type for attribute");
}
@Test
void dependsOnCycle() {
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
@@ -1845,19 +1794,19 @@ class DefaultListableBeanFactoryTests {
resolved.add(instance);
}
assertThat(resolved).hasSize(2);
assertThat(resolved).contains(lbf.getBean("bd1"));
assertThat(resolved).contains(lbf.getBean("bd2"));
assertThat(resolved.contains(lbf.getBean("bd1"))).isTrue();
assertThat(resolved.contains(lbf.getBean("bd2"))).isTrue();
resolved = new HashSet<>();
provider.forEach(resolved::add);
assertThat(resolved).hasSize(2);
assertThat(resolved).contains(lbf.getBean("bd1"));
assertThat(resolved).contains(lbf.getBean("bd2"));
assertThat(resolved.contains(lbf.getBean("bd1"))).isTrue();
assertThat(resolved.contains(lbf.getBean("bd2"))).isTrue();
resolved = provider.stream().collect(Collectors.toSet());
assertThat(resolved).hasSize(2);
assertThat(resolved).contains(lbf.getBean("bd1"));
assertThat(resolved).contains(lbf.getBean("bd2"));
assertThat(resolved.contains(lbf.getBean("bd1"))).isTrue();
assertThat(resolved.contains(lbf.getBean("bd2"))).isTrue();
}
@Test
@@ -1894,19 +1843,19 @@ class DefaultListableBeanFactoryTests {
resolved.add(instance);
}
assertThat(resolved).hasSize(2);
assertThat(resolved).contains(lbf.getBean("bd1"));
assertThat(resolved).contains(lbf.getBean("bd2"));
assertThat(resolved.contains(lbf.getBean("bd1"))).isTrue();
assertThat(resolved.contains(lbf.getBean("bd2"))).isTrue();
resolved = new HashSet<>();
provider.forEach(resolved::add);
assertThat(resolved).hasSize(2);
assertThat(resolved).contains(lbf.getBean("bd1"));
assertThat(resolved).contains(lbf.getBean("bd2"));
assertThat(resolved.contains(lbf.getBean("bd1"))).isTrue();
assertThat(resolved.contains(lbf.getBean("bd2"))).isTrue();
resolved = provider.stream().collect(Collectors.toSet());
assertThat(resolved).hasSize(2);
assertThat(resolved).contains(lbf.getBean("bd1"));
assertThat(resolved).contains(lbf.getBean("bd2"));
assertThat(resolved.contains(lbf.getBean("bd1"))).isTrue();
assertThat(resolved.contains(lbf.getBean("bd2"))).isTrue();
}
@Test
@@ -2238,9 +2187,9 @@ class DefaultListableBeanFactoryTests {
ObjectProvider<TestBean> testBeanProvider = lbf.getBeanProvider(ResolvableType.forClass(TestBean.class));
List<TestBean> resolved = testBeanProvider.orderedStream().toList();
assertThat(resolved.size()).isEqualTo(3);
assertThat(resolved).element(0).isSameAs(lbf.getBean("highPriorityTestBean"));
assertThat(resolved).element(1).isSameAs(lbf.getBean("lowPriorityTestBean"));
assertThat(resolved).element(2).isSameAs(lbf.getBean("plainTestBean"));
assertThat(resolved.get(0)).isSameAs(lbf.getBean("highPriorityTestBean"));
assertThat(resolved.get(1)).isSameAs(lbf.getBean("lowPriorityTestBean"));
assertThat(resolved.get(2)).isSameAs(lbf.getBean("plainTestBean"));
}
@Test
@@ -3416,7 +3365,7 @@ class DefaultListableBeanFactoryTests {
}
static class PriorityTestBeanFactory {
private static class PriorityTestBeanFactory {
public static LowPriorityTestBean lowPriorityTestBean() {
return new LowPriorityTestBean();
@@ -3477,34 +3426,4 @@ class DefaultListableBeanFactoryTests {
}
}
@Order
private static class LowestPrecedenceTestBeanFactoryBean implements FactoryBean<TestBean> {
@Override
public TestBean getObject() {
return new TestBean("fromLowestPrecedenceTestBeanFactoryBean");
}
@Override
public Class<?> getObjectType() {
return TestBean.class;
}
}
@Order(Ordered.HIGHEST_PRECEDENCE)
private static class HighestPrecedenceTestBeanFactoryBean implements FactoryBean<TestBean> {
@Override
public TestBean getObject() {
return new TestBean("fromHighestPrecedenceTestBeanFactoryBean");
}
@Override
public Class<?> getObjectType() {
return TestBean.class;
}
}
}
@@ -569,14 +569,14 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.getTestBean4()).isSameAs(tb);
assertThat(bean.getIndexedTestBean()).isSameAs(itb);
assertThat(bean.getNestedTestBeans()).hasSize(2);
assertThat(bean.getNestedTestBeans()).element(0).isSameAs(ntb1);
assertThat(bean.getNestedTestBeans()).element(1).isSameAs(ntb2);
assertThat(bean.getNestedTestBeans().get(0)).isSameAs(ntb1);
assertThat(bean.getNestedTestBeans().get(1)).isSameAs(ntb2);
assertThat(bean.nestedTestBeansSetter).hasSize(2);
assertThat(bean.nestedTestBeansSetter).element(0).isSameAs(ntb1);
assertThat(bean.nestedTestBeansSetter).element(1).isSameAs(ntb2);
assertThat(bean.nestedTestBeansSetter.get(0)).isSameAs(ntb1);
assertThat(bean.nestedTestBeansSetter.get(1)).isSameAs(ntb2);
assertThat(bean.nestedTestBeansField).hasSize(2);
assertThat(bean.nestedTestBeansField).element(0).isSameAs(ntb1);
assertThat(bean.nestedTestBeansField).element(1).isSameAs(ntb2);
assertThat(bean.nestedTestBeansField.get(0)).isSameAs(ntb1);
assertThat(bean.nestedTestBeansField.get(1)).isSameAs(ntb2);
}
@Test
@@ -600,11 +600,11 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.getTestBean4()).isSameAs(tb);
assertThat(bean.getIndexedTestBean()).isSameAs(itb);
assertThat(bean.getNestedTestBeans()).hasSize(1);
assertThat(bean.getNestedTestBeans()).element(0).isSameAs(ntb1);
assertThat(bean.getNestedTestBeans().get(0)).isSameAs(ntb1);
assertThat(bean.nestedTestBeansSetter).hasSize(1);
assertThat(bean.nestedTestBeansSetter).element(0).isSameAs(ntb1);
assertThat(bean.nestedTestBeansSetter.get(0)).isSameAs(ntb1);
assertThat(bean.nestedTestBeansField).hasSize(1);
assertThat(bean.nestedTestBeansField).element(0).isSameAs(ntb1);
assertThat(bean.nestedTestBeansField.get(0)).isSameAs(ntb1);
}
@Test
@@ -712,14 +712,14 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.getTestBean4()).isSameAs(tb);
assertThat(bean.getIndexedTestBean()).isSameAs(itb);
assertThat(bean.getNestedTestBeans()).hasSize(2);
assertThat(bean.getNestedTestBeans()).element(0).isSameAs(ntb2);
assertThat(bean.getNestedTestBeans()).element(1).isSameAs(ntb1);
assertThat(bean.getNestedTestBeans().get(0)).isSameAs(ntb2);
assertThat(bean.getNestedTestBeans().get(1)).isSameAs(ntb1);
assertThat(bean.nestedTestBeansSetter).hasSize(2);
assertThat(bean.nestedTestBeansSetter).element(0).isSameAs(ntb2);
assertThat(bean.nestedTestBeansSetter).element(1).isSameAs(ntb1);
assertThat(bean.nestedTestBeansSetter.get(0)).isSameAs(ntb2);
assertThat(bean.nestedTestBeansSetter.get(1)).isSameAs(ntb1);
assertThat(bean.nestedTestBeansField).hasSize(2);
assertThat(bean.nestedTestBeansField).element(0).isSameAs(ntb2);
assertThat(bean.nestedTestBeansField).element(1).isSameAs(ntb1);
assertThat(bean.nestedTestBeansField.get(0)).isSameAs(ntb2);
assertThat(bean.nestedTestBeansField.get(1)).isSameAs(ntb1);
}
@Test
@@ -745,14 +745,14 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.getTestBean4()).isSameAs(tb);
assertThat(bean.getIndexedTestBean()).isSameAs(itb);
assertThat(bean.getNestedTestBeans()).hasSize(2);
assertThat(bean.getNestedTestBeans()).element(0).isSameAs(ntb2);
assertThat(bean.getNestedTestBeans()).element(1).isSameAs(ntb1);
assertThat(bean.getNestedTestBeans().get(0)).isSameAs(ntb2);
assertThat(bean.getNestedTestBeans().get(1)).isSameAs(ntb1);
assertThat(bean.nestedTestBeansSetter).hasSize(2);
assertThat(bean.nestedTestBeansSetter).element(0).isSameAs(ntb2);
assertThat(bean.nestedTestBeansSetter).element(1).isSameAs(ntb1);
assertThat(bean.nestedTestBeansSetter.get(0)).isSameAs(ntb2);
assertThat(bean.nestedTestBeansSetter.get(1)).isSameAs(ntb1);
assertThat(bean.nestedTestBeansField).hasSize(2);
assertThat(bean.nestedTestBeansField).element(0).isSameAs(ntb2);
assertThat(bean.nestedTestBeansField).element(1).isSameAs(ntb1);
assertThat(bean.nestedTestBeansField.get(0)).isSameAs(ntb2);
assertThat(bean.nestedTestBeansField.get(1)).isSameAs(ntb1);
}
@Test
@@ -1055,7 +1055,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.getTestBean3()).isNull();
assertThat(bean.getTestBean4()).isSameAs(tb);
assertThat(bean.getNestedTestBeans()).hasSize(1);
assertThat(bean.getNestedTestBeans()).element(0).isSameAs(ntb2);
assertThat(bean.getNestedTestBeans().get(0)).isSameAs(ntb2);
Map<String, NestedTestBean> map = bf.getBeansOfType(NestedTestBean.class);
assertThat(map.get("nestedTestBean1")).isNull();
@@ -1077,8 +1077,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.getTestBean3()).isNull();
assertThat(bean.getTestBean4()).isSameAs(tb);
assertThat(bean.getNestedTestBeans()).hasSize(2);
assertThat(bean.getNestedTestBeans()).element(0).isSameAs(ntb1);
assertThat(bean.getNestedTestBeans()).element(1).isSameAs(ntb2);
assertThat(bean.getNestedTestBeans().get(0)).isSameAs(ntb1);
assertThat(bean.getNestedTestBeans().get(1)).isSameAs(ntb2);
}
@Test
@@ -1113,8 +1113,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.getTestBean3()).isNull();
assertThat(bean.getTestBean4()).isSameAs(tb);
assertThat(bean.getNestedTestBeans()).hasSize(2);
assertThat(bean.getNestedTestBeans()).element(0).isSameAs(ntb2);
assertThat(bean.getNestedTestBeans()).element(1).isSameAs(ntb1);
assertThat(bean.getNestedTestBeans().get(0)).isSameAs(ntb2);
assertThat(bean.getNestedTestBeans().get(1)).isSameAs(ntb1);
}
@Test
@@ -1130,8 +1130,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
SingleConstructorVarargBean bean = bf.getBean("annotatedBean", SingleConstructorVarargBean.class);
assertThat(bean.getTestBean()).isSameAs(tb);
assertThat(bean.getNestedTestBeans()).hasSize(2);
assertThat(bean.getNestedTestBeans()).element(0).isSameAs(ntb2);
assertThat(bean.getNestedTestBeans()).element(1).isSameAs(ntb1);
assertThat(bean.getNestedTestBeans().get(0)).isSameAs(ntb2);
assertThat(bean.getNestedTestBeans().get(1)).isSameAs(ntb1);
}
@Test
@@ -1143,7 +1143,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
SingleConstructorVarargBean bean = bf.getBean("annotatedBean", SingleConstructorVarargBean.class);
assertThat(bean.getTestBean()).isSameAs(tb);
assertThat(bean.getNestedTestBeans()).isNotNull();
assertThat(bean.getNestedTestBeans()).isEmpty();
assertThat(bean.getNestedTestBeans().isEmpty()).isTrue();
}
@Test
@@ -1159,8 +1159,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
SingleConstructorRequiredCollectionBean bean = bf.getBean("annotatedBean", SingleConstructorRequiredCollectionBean.class);
assertThat(bean.getTestBean()).isSameAs(tb);
assertThat(bean.getNestedTestBeans()).hasSize(2);
assertThat(bean.getNestedTestBeans()).element(0).isSameAs(ntb2);
assertThat(bean.getNestedTestBeans()).element(1).isSameAs(ntb1);
assertThat(bean.getNestedTestBeans().get(0)).isSameAs(ntb2);
assertThat(bean.getNestedTestBeans().get(1)).isSameAs(ntb1);
}
@Test
@@ -1172,7 +1172,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
SingleConstructorRequiredCollectionBean bean = bf.getBean("annotatedBean", SingleConstructorRequiredCollectionBean.class);
assertThat(bean.getTestBean()).isSameAs(tb);
assertThat(bean.getNestedTestBeans()).isNotNull();
assertThat(bean.getNestedTestBeans()).isEmpty();
assertThat(bean.getNestedTestBeans().isEmpty()).isTrue();
}
@Test
@@ -1188,8 +1188,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
SingleConstructorOptionalCollectionBean bean = bf.getBean("annotatedBean", SingleConstructorOptionalCollectionBean.class);
assertThat(bean.getTestBean()).isSameAs(tb);
assertThat(bean.getNestedTestBeans()).hasSize(2);
assertThat(bean.getNestedTestBeans()).element(0).isSameAs(ntb2);
assertThat(bean.getNestedTestBeans()).element(1).isSameAs(ntb1);
assertThat(bean.getNestedTestBeans().get(0)).isSameAs(ntb2);
assertThat(bean.getNestedTestBeans().get(1)).isSameAs(ntb1);
}
@Test
@@ -1274,17 +1274,17 @@ public class AutowiredAnnotationBeanPostProcessorTests {
MapFieldInjectionBean bean = bf.getBean("annotatedBean", MapFieldInjectionBean.class);
assertThat(bean.getTestBeanMap()).hasSize(2);
assertThat(bean.getTestBeanMap()).containsKey("testBean1");
assertThat(bean.getTestBeanMap()).containsKey("testBean2");
assertThat(bean.getTestBeanMap()).containsValue(tb1);
assertThat(bean.getTestBeanMap()).containsValue(tb2);
assertThat(bean.getTestBeanMap().keySet().contains("testBean1")).isTrue();
assertThat(bean.getTestBeanMap().keySet().contains("testBean2")).isTrue();
assertThat(bean.getTestBeanMap().values().contains(tb1)).isTrue();
assertThat(bean.getTestBeanMap().values().contains(tb2)).isTrue();
bean = bf.getBean("annotatedBean", MapFieldInjectionBean.class);
assertThat(bean.getTestBeanMap()).hasSize(2);
assertThat(bean.getTestBeanMap()).containsKey("testBean1");
assertThat(bean.getTestBeanMap()).containsKey("testBean2");
assertThat(bean.getTestBeanMap()).containsValue(tb1);
assertThat(bean.getTestBeanMap()).containsValue(tb2);
assertThat(bean.getTestBeanMap().keySet().contains("testBean1")).isTrue();
assertThat(bean.getTestBeanMap().keySet().contains("testBean2")).isTrue();
assertThat(bean.getTestBeanMap().values().contains(tb1)).isTrue();
assertThat(bean.getTestBeanMap().values().contains(tb2)).isTrue();
}
@Test
@@ -1297,14 +1297,14 @@ public class AutowiredAnnotationBeanPostProcessorTests {
MapMethodInjectionBean bean = bf.getBean("annotatedBean", MapMethodInjectionBean.class);
assertThat(bean.getTestBeanMap()).hasSize(1);
assertThat(bean.getTestBeanMap()).containsKey("testBean");
assertThat(bean.getTestBeanMap()).containsValue(tb);
assertThat(bean.getTestBeanMap().keySet().contains("testBean")).isTrue();
assertThat(bean.getTestBeanMap().values().contains(tb)).isTrue();
assertThat(bean.getTestBean()).isSameAs(tb);
bean = bf.getBean("annotatedBean", MapMethodInjectionBean.class);
assertThat(bean.getTestBeanMap()).hasSize(1);
assertThat(bean.getTestBeanMap()).containsKey("testBean");
assertThat(bean.getTestBeanMap()).containsValue(tb);
assertThat(bean.getTestBeanMap().keySet().contains("testBean")).isTrue();
assertThat(bean.getTestBeanMap().values().contains(tb)).isTrue();
assertThat(bean.getTestBean()).isSameAs(tb);
}
@@ -1329,8 +1329,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
MapMethodInjectionBean bean = bf.getBean("annotatedBean", MapMethodInjectionBean.class);
TestBean tb = bf.getBean("testBean1", TestBean.class);
assertThat(bean.getTestBeanMap()).hasSize(1);
assertThat(bean.getTestBeanMap()).containsKey("testBean1");
assertThat(bean.getTestBeanMap()).containsValue(tb);
assertThat(bean.getTestBeanMap().keySet().contains("testBean1")).isTrue();
assertThat(bean.getTestBeanMap().values().contains(tb)).isTrue();
assertThat(bean.getTestBean()).isSameAs(tb);
}
@@ -1501,7 +1501,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
SelfInjectionBean bean2 = bf.getBean("annotatedBean2", SelfInjectionBean.class);
assertThat(bean.reference).isSameAs(bean2);
assertThat(bean.referenceCollection).hasSize(1);
assertThat(bean.referenceCollection).element(0).isSameAs(bean2);
assertThat(bean.referenceCollection.get(0)).isSameAs(bean2);
}
@Test
@@ -1522,7 +1522,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
SelfInjectionCollectionBean bean2 = bf.getBean("annotatedBean2", SelfInjectionCollectionBean.class);
assertThat(bean.reference).isSameAs(bean2);
assertThat(bean2.referenceCollection).hasSize(1);
assertThat(bean.referenceCollection).element(0).isSameAs(bean2);
assertThat(bean.referenceCollection.get(0)).isSameAs(bean2);
}
@Test
@@ -1610,18 +1610,18 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.getUniqueTestBeanWithDefault()).isEqualTo(bf.getBean("testBean"));
assertThat(bean.consumeUniqueTestBean()).isEqualTo(bf.getBean("testBean"));
List<TestBean> testBeans = bean.iterateTestBeans();
List<?> testBeans = bean.iterateTestBeans();
assertThat(testBeans).hasSize(1);
assertThat(testBeans).contains(bf.getBean("testBean", TestBean.class));
assertThat(testBeans.contains(bf.getBean("testBean"))).isTrue();
testBeans = bean.forEachTestBeans();
assertThat(testBeans).hasSize(1);
assertThat(testBeans).contains(bf.getBean("testBean", TestBean.class));
assertThat(testBeans.contains(bf.getBean("testBean"))).isTrue();
testBeans = bean.streamTestBeans();
assertThat(testBeans).hasSize(1);
assertThat(testBeans).contains(bf.getBean("testBean", TestBean.class));
assertThat(testBeans.contains(bf.getBean("testBean"))).isTrue();
testBeans = bean.sortedTestBeans();
assertThat(testBeans).hasSize(1);
assertThat(testBeans).contains(bf.getBean("testBean", TestBean.class));
assertThat(testBeans.contains(bf.getBean("testBean"))).isTrue();
}
@Test
@@ -1638,18 +1638,18 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.getUniqueTestBeanWithDefault()).isSameAs(bf.getBean("testBean"));
assertThat(bean.consumeUniqueTestBean()).isEqualTo(bf.getBean("testBean"));
List<TestBean> testBeans = bean.iterateTestBeans();
List<?> testBeans = bean.iterateTestBeans();
assertThat(testBeans).hasSize(1);
assertThat(testBeans).contains(bf.getBean("testBean", TestBean.class));
assertThat(testBeans.contains(bf.getBean("testBean"))).isTrue();
testBeans = bean.forEachTestBeans();
assertThat(testBeans).hasSize(1);
assertThat(testBeans).contains(bf.getBean("testBean", TestBean.class));
assertThat(testBeans.contains(bf.getBean("testBean"))).isTrue();
testBeans = bean.streamTestBeans();
assertThat(testBeans).hasSize(1);
assertThat(testBeans).contains(bf.getBean("testBean", TestBean.class));
assertThat(testBeans.contains(bf.getBean("testBean"))).isTrue();
testBeans = bean.sortedTestBeans();
assertThat(testBeans).hasSize(1);
assertThat(testBeans).contains(bf.getBean("testBean", TestBean.class));
assertThat(testBeans.contains(bf.getBean("testBean"))).isTrue();
}
@Test
@@ -1666,13 +1666,13 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.consumeUniqueTestBean()).isNull();
List<?> testBeans = bean.iterateTestBeans();
assertThat(testBeans).isEmpty();
assertThat(testBeans.isEmpty()).isTrue();
testBeans = bean.forEachTestBeans();
assertThat(testBeans).isEmpty();
assertThat(testBeans.isEmpty()).isTrue();
testBeans = bean.streamTestBeans();
assertThat(testBeans).isEmpty();
assertThat(testBeans.isEmpty()).isTrue();
testBeans = bean.sortedTestBeans();
assertThat(testBeans).isEmpty();
assertThat(testBeans.isEmpty()).isTrue();
}
@Test
@@ -1690,20 +1690,20 @@ public class AutowiredAnnotationBeanPostProcessorTests {
List<?> testBeans = bean.iterateTestBeans();
assertThat(testBeans).hasSize(2);
assertThat(testBeans).element(0).isSameAs(bf.getBean("testBean1"));
assertThat(testBeans).element(1).isSameAs(bf.getBean("testBean2"));
assertThat(testBeans.get(0)).isSameAs(bf.getBean("testBean1"));
assertThat(testBeans.get(1)).isSameAs(bf.getBean("testBean2"));
testBeans = bean.forEachTestBeans();
assertThat(testBeans).hasSize(2);
assertThat(testBeans).element(0).isSameAs(bf.getBean("testBean1"));
assertThat(testBeans).element(1).isSameAs(bf.getBean("testBean2"));
assertThat(testBeans.get(0)).isSameAs(bf.getBean("testBean1"));
assertThat(testBeans.get(1)).isSameAs(bf.getBean("testBean2"));
testBeans = bean.streamTestBeans();
assertThat(testBeans).hasSize(2);
assertThat(testBeans).element(0).isSameAs(bf.getBean("testBean1"));
assertThat(testBeans).element(1).isSameAs(bf.getBean("testBean2"));
assertThat(testBeans.get(0)).isSameAs(bf.getBean("testBean1"));
assertThat(testBeans.get(1)).isSameAs(bf.getBean("testBean2"));
testBeans = bean.sortedTestBeans();
assertThat(testBeans).hasSize(2);
assertThat(testBeans).element(0).isSameAs(bf.getBean("testBean1"));
assertThat(testBeans).element(1).isSameAs(bf.getBean("testBean2"));
assertThat(testBeans.get(0)).isSameAs(bf.getBean("testBean1"));
assertThat(testBeans.get(1)).isSameAs(bf.getBean("testBean2"));
}
@Test
@@ -1728,20 +1728,20 @@ public class AutowiredAnnotationBeanPostProcessorTests {
List<?> testBeans = bean.iterateTestBeans();
assertThat(testBeans).hasSize(2);
assertThat(testBeans).element(0).isSameAs(bf.getBean("testBean1"));
assertThat(testBeans).element(1).isSameAs(bf.getBean("testBean2"));
assertThat(testBeans.get(0)).isSameAs(bf.getBean("testBean1"));
assertThat(testBeans.get(1)).isSameAs(bf.getBean("testBean2"));
testBeans = bean.forEachTestBeans();
assertThat(testBeans).hasSize(2);
assertThat(testBeans).element(0).isSameAs(bf.getBean("testBean1"));
assertThat(testBeans).element(1).isSameAs(bf.getBean("testBean2"));
assertThat(testBeans.get(0)).isSameAs(bf.getBean("testBean1"));
assertThat(testBeans.get(1)).isSameAs(bf.getBean("testBean2"));
testBeans = bean.streamTestBeans();
assertThat(testBeans).hasSize(2);
assertThat(testBeans).element(0).isSameAs(bf.getBean("testBean1"));
assertThat(testBeans).element(1).isSameAs(bf.getBean("testBean2"));
assertThat(testBeans.get(0)).isSameAs(bf.getBean("testBean1"));
assertThat(testBeans.get(1)).isSameAs(bf.getBean("testBean2"));
testBeans = bean.sortedTestBeans();
assertThat(testBeans).hasSize(2);
assertThat(testBeans).element(0).isSameAs(bf.getBean("testBean2"));
assertThat(testBeans).element(1).isSameAs(bf.getBean("testBean1"));
assertThat(testBeans.get(0)).isSameAs(bf.getBean("testBean2"));
assertThat(testBeans.get(1)).isSameAs(bf.getBean("testBean1"));
}
@Test
@@ -1759,8 +1759,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
ObjectProviderInjectionBean bean = bf.getBean("annotatedBean", ObjectProviderInjectionBean.class);
List<?> testBeans = bean.sortedTestBeans();
assertThat(testBeans).hasSize(2);
assertThat(testBeans).element(0).isSameAs(bf.getBean("testBean2"));
assertThat(testBeans).element(1).isSameAs(bf.getBean("testBean1"));
assertThat(testBeans.get(0)).isSameAs(bf.getBean("testBean2"));
assertThat(testBeans.get(1)).isSameAs(bf.getBean("testBean1"));
}
@Test
@@ -1988,8 +1988,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.integerArray[0]).isSameAs(iv);
assertThat(bean.stringList).hasSize(1);
assertThat(bean.integerList).hasSize(1);
assertThat(bean.stringList).element(0).isSameAs(sv);
assertThat(bean.integerList).element(0).isSameAs(iv);
assertThat(bean.stringList.get(0)).isSameAs(sv);
assertThat(bean.integerList.get(0)).isSameAs(iv);
assertThat(bean.stringMap).hasSize(1);
assertThat(bean.integerMap).hasSize(1);
assertThat(bean.stringMap.get("stringValue")).isSameAs(sv);
@@ -2002,8 +2002,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.integerRepositoryArray[0]).isSameAs(ir);
assertThat(bean.stringRepositoryList).hasSize(1);
assertThat(bean.integerRepositoryList).hasSize(1);
assertThat(bean.stringRepositoryList).element(0).isSameAs(sr);
assertThat(bean.integerRepositoryList).element(0).isSameAs(ir);
assertThat(bean.stringRepositoryList.get(0)).isSameAs(sr);
assertThat(bean.integerRepositoryList.get(0)).isSameAs(ir);
assertThat(bean.stringRepositoryMap).hasSize(1);
assertThat(bean.integerRepositoryMap).hasSize(1);
assertThat(bean.stringRepositoryMap.get("stringRepo")).isSameAs(sr);
@@ -2034,8 +2034,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.integerArray[0]).isSameAs(iv);
assertThat(bean.stringList).hasSize(1);
assertThat(bean.integerList).hasSize(1);
assertThat(bean.stringList).element(0).isSameAs(sv);
assertThat(bean.integerList).element(0).isSameAs(iv);
assertThat(bean.stringList.get(0)).isSameAs(sv);
assertThat(bean.integerList.get(0)).isSameAs(iv);
assertThat(bean.stringMap).hasSize(1);
assertThat(bean.integerMap).hasSize(1);
assertThat(bean.stringMap.get("stringValue")).isSameAs(sv);
@@ -2048,8 +2048,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.integerRepositoryArray[0]).isSameAs(ir);
assertThat(bean.stringRepositoryList).hasSize(1);
assertThat(bean.integerRepositoryList).hasSize(1);
assertThat(bean.stringRepositoryList).element(0).isSameAs(sr);
assertThat(bean.integerRepositoryList).element(0).isSameAs(ir);
assertThat(bean.stringRepositoryList.get(0)).isSameAs(sr);
assertThat(bean.integerRepositoryList.get(0)).isSameAs(ir);
assertThat(bean.stringRepositoryMap).hasSize(1);
assertThat(bean.integerRepositoryMap).hasSize(1);
assertThat(bean.stringRepositoryMap.get("stringRepo")).isSameAs(sr);
@@ -2076,8 +2076,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.integerRepositoryArray[0]).isSameAs(ir);
assertThat(bean.stringRepositoryList).hasSize(1);
assertThat(bean.integerRepositoryList).hasSize(1);
assertThat(bean.stringRepositoryList).element(0).isSameAs(sr);
assertThat(bean.integerRepositoryList).element(0).isSameAs(ir);
assertThat(bean.stringRepositoryList.get(0)).isSameAs(sr);
assertThat(bean.integerRepositoryList.get(0)).isSameAs(ir);
assertThat(bean.stringRepositoryMap).hasSize(1);
assertThat(bean.integerRepositoryMap).hasSize(1);
assertThat(bean.stringRepositoryMap.get("stringRepo")).isSameAs(sr);
@@ -2116,8 +2116,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.integerRepositoryArray[0]).isSameAs(ir);
assertThat(bean.stringRepositoryList).hasSize(1);
assertThat(bean.integerRepositoryList).hasSize(1);
assertThat(bean.stringRepositoryList).element(0).isSameAs(sr);
assertThat(bean.integerRepositoryList).element(0).isSameAs(ir);
assertThat(bean.stringRepositoryList.get(0)).isSameAs(sr);
assertThat(bean.integerRepositoryList.get(0)).isSameAs(ir);
assertThat(bean.stringRepositoryMap).hasSize(1);
assertThat(bean.integerRepositoryMap).hasSize(1);
assertThat(bean.stringRepositoryMap.get("stringRepo")).isSameAs(sr);
@@ -2143,8 +2143,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.stringRepositoryArray[0]).isSameAs(repo);
assertThat(bean.repositoryList).hasSize(1);
assertThat(bean.stringRepositoryList).hasSize(1);
assertThat(bean.repositoryList).element(0).isSameAs(repo);
assertThat(bean.stringRepositoryList).element(0).isSameAs(repo);
assertThat(bean.repositoryList.get(0)).isSameAs(repo);
assertThat(bean.stringRepositoryList.get(0)).isSameAs(repo);
assertThat(bean.repositoryMap).hasSize(1);
assertThat(bean.stringRepositoryMap).hasSize(1);
assertThat(bean.repositoryMap.get("repo")).isSameAs(repo);
@@ -2201,8 +2201,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.stringRepositoryArray[0]).isSameAs(repo);
assertThat(bean.repositoryList).hasSize(1);
assertThat(bean.stringRepositoryList).hasSize(1);
assertThat(bean.repositoryList).element(0).isSameAs(repo);
assertThat(bean.stringRepositoryList).element(0).isSameAs(repo);
assertThat(bean.repositoryList.get(0)).isSameAs(repo);
assertThat(bean.stringRepositoryList.get(0)).isSameAs(repo);
assertThat(bean.repositoryMap).hasSize(1);
assertThat(bean.stringRepositoryMap).hasSize(1);
assertThat(bean.repositoryMap.get("repo")).isSameAs(repo);
@@ -2232,8 +2232,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.stringRepositoryArray[0]).isSameAs(repo);
assertThat(bean.repositoryList).hasSize(1);
assertThat(bean.stringRepositoryList).hasSize(1);
assertThat(bean.repositoryList).element(0).isSameAs(repo);
assertThat(bean.stringRepositoryList).element(0).isSameAs(repo);
assertThat(bean.repositoryList.get(0)).isSameAs(repo);
assertThat(bean.stringRepositoryList.get(0)).isSameAs(repo);
assertThat(bean.repositoryMap).hasSize(1);
assertThat(bean.stringRepositoryMap).hasSize(1);
assertThat(bean.repositoryMap.get("repo")).isSameAs(repo);
@@ -2272,8 +2272,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.integerArray[0]).isSameAs(iv);
assertThat(bean.stringList).hasSize(1);
assertThat(bean.integerList).hasSize(1);
assertThat(bean.stringList).element(0).isSameAs(sv);
assertThat(bean.integerList).element(0).isSameAs(iv);
assertThat(bean.stringList.get(0)).isSameAs(sv);
assertThat(bean.integerList.get(0)).isSameAs(iv);
assertThat(bean.stringMap).hasSize(1);
assertThat(bean.integerMap).hasSize(1);
assertThat(bean.stringMap.get("stringValue")).isSameAs(sv);
@@ -2286,8 +2286,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.integerRepositoryArray[0]).isSameAs(ir);
assertThat(bean.stringRepositoryList).hasSize(1);
assertThat(bean.integerRepositoryList).hasSize(1);
assertThat(bean.stringRepositoryList).element(0).isSameAs(sr);
assertThat(bean.integerRepositoryList).element(0).isSameAs(ir);
assertThat(bean.stringRepositoryList.get(0)).isSameAs(sr);
assertThat(bean.integerRepositoryList.get(0)).isSameAs(ir);
assertThat(bean.stringRepositoryMap).hasSize(1);
assertThat(bean.integerRepositoryMap).hasSize(1);
assertThat(bean.stringRepositoryMap.get("stringRepo")).isSameAs(sr);
@@ -2318,8 +2318,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.integerArray[0]).isSameAs(iv);
assertThat(bean.stringList).hasSize(1);
assertThat(bean.integerList).hasSize(1);
assertThat(bean.stringList).element(0).isSameAs(sv);
assertThat(bean.integerList).element(0).isSameAs(iv);
assertThat(bean.stringList.get(0)).isSameAs(sv);
assertThat(bean.integerList.get(0)).isSameAs(iv);
assertThat(bean.stringMap).hasSize(1);
assertThat(bean.integerMap).hasSize(1);
assertThat(bean.stringMap.get("stringValue")).isSameAs(sv);
@@ -2332,8 +2332,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.integerRepositoryArray[0]).isSameAs(ir);
assertThat(bean.stringRepositoryList).hasSize(1);
assertThat(bean.integerRepositoryList).hasSize(1);
assertThat(bean.stringRepositoryList).element(0).isSameAs(sr);
assertThat(bean.integerRepositoryList).element(0).isSameAs(ir);
assertThat(bean.stringRepositoryList.get(0)).isSameAs(sr);
assertThat(bean.integerRepositoryList.get(0)).isSameAs(ir);
assertThat(bean.stringRepositoryMap).hasSize(1);
assertThat(bean.integerRepositoryMap).hasSize(1);
assertThat(bean.stringRepositoryMap.get("stringRepo")).isSameAs(sr);
@@ -2359,8 +2359,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.integerRepositoryArray[0]).isSameAs(ir);
assertThat(bean.stringRepositoryList).hasSize(1);
assertThat(bean.integerRepositoryList).hasSize(1);
assertThat(bean.stringRepositoryList).element(0).isSameAs(sr);
assertThat(bean.integerRepositoryList).element(0).isSameAs(ir);
assertThat(bean.stringRepositoryList.get(0)).isSameAs(sr);
assertThat(bean.integerRepositoryList.get(0)).isSameAs(ir);
assertThat(bean.stringRepositoryMap).hasSize(1);
assertThat(bean.integerRepositoryMap).hasSize(1);
assertThat(bean.stringRepositoryMap.get("stringRepo")).isSameAs(sr);
@@ -2385,8 +2385,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.integerRepositoryArray[0]).isSameAs(gr);
assertThat(bean.stringRepositoryList).hasSize(1);
assertThat(bean.integerRepositoryList).hasSize(1);
assertThat(bean.stringRepositoryList).element(0).isSameAs(gr);
assertThat(bean.integerRepositoryList).element(0).isSameAs(gr);
assertThat(bean.stringRepositoryList.get(0)).isSameAs(gr);
assertThat(bean.integerRepositoryList.get(0)).isSameAs(gr);
assertThat(bean.stringRepositoryMap).hasSize(1);
assertThat(bean.integerRepositoryMap).hasSize(1);
assertThat(bean.stringRepositoryMap.get("genericRepo")).isSameAs(gr);
@@ -2410,8 +2410,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.integerRepositoryArray[0]).isSameAs(ngr);
assertThat(bean.stringRepositoryList).hasSize(1);
assertThat(bean.integerRepositoryList).hasSize(1);
assertThat(bean.stringRepositoryList).element(0).isSameAs(ngr);
assertThat(bean.integerRepositoryList).element(0).isSameAs(ngr);
assertThat(bean.stringRepositoryList.get(0)).isSameAs(ngr);
assertThat(bean.integerRepositoryList.get(0)).isSameAs(ngr);
assertThat(bean.stringRepositoryMap).hasSize(1);
assertThat(bean.integerRepositoryMap).hasSize(1);
assertThat(bean.stringRepositoryMap.get("simpleRepo")).isSameAs(ngr);
@@ -2438,8 +2438,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.integerRepositoryArray[0]).isSameAs(gr);
assertThat(bean.stringRepositoryList).hasSize(1);
assertThat(bean.integerRepositoryList).hasSize(1);
assertThat(bean.stringRepositoryList).element(0).isSameAs(sr);
assertThat(bean.integerRepositoryList).element(0).isSameAs(gr);
assertThat(bean.stringRepositoryList.get(0)).isSameAs(sr);
assertThat(bean.integerRepositoryList.get(0)).isSameAs(gr);
assertThat(bean.stringRepositoryMap).hasSize(1);
assertThat(bean.integerRepositoryMap).hasSize(1);
assertThat(bean.stringRepositoryMap.get("stringRepo")).isSameAs(sr);
@@ -2465,8 +2465,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.integerRepositoryArray[0]).isSameAs(ngr);
assertThat(bean.stringRepositoryList).hasSize(1);
assertThat(bean.integerRepositoryList).hasSize(1);
assertThat(bean.stringRepositoryList).element(0).isSameAs(sr);
assertThat(bean.integerRepositoryList).element(0).isSameAs(ngr);
assertThat(bean.stringRepositoryList.get(0)).isSameAs(sr);
assertThat(bean.integerRepositoryList.get(0)).isSameAs(ngr);
assertThat(bean.stringRepositoryMap).hasSize(1);
assertThat(bean.integerRepositoryMap).hasSize(1);
assertThat(bean.stringRepositoryMap.get("stringRepo")).isSameAs(sr);
@@ -85,7 +85,7 @@ public class InjectAnnotationBeanPostProcessorTests {
bf.getBean("testBean");
}
catch (BeanCreationException ex) {
assertThat(ex.getRootCause()).isInstanceOf(IllegalStateException.class);
assertThat(ex.getRootCause() instanceof IllegalStateException).isTrue();
}
}
@@ -195,8 +195,8 @@ public class InjectAnnotationBeanPostProcessorTests {
assertThat(bean.getTestBean3()).isNull();
assertThat(bean.getTestBean4()).isSameAs(tb);
assertThat(bean.getNestedTestBeans()).hasSize(2);
assertThat(bean.getNestedTestBeans()).element(0).isSameAs(ntb1);
assertThat(bean.getNestedTestBeans()).element(1).isSameAs(ntb2);
assertThat(bean.getNestedTestBeans().get(0)).isSameAs(ntb1);
assertThat(bean.getNestedTestBeans().get(1)).isSameAs(ntb2);
}
@Test
@@ -222,17 +222,17 @@ public class InjectAnnotationBeanPostProcessorTests {
MapConstructorInjectionBean bean = (MapConstructorInjectionBean) bf.getBean("annotatedBean");
assertThat(bean.getTestBeanMap()).hasSize(2);
assertThat(bean.getTestBeanMap()).containsKey("testBean1");
assertThat(bean.getTestBeanMap()).containsKey("testBean2");
assertThat(bean.getTestBeanMap()).containsValue(tb1);
assertThat(bean.getTestBeanMap()).containsValue(tb2);
assertThat(bean.getTestBeanMap().keySet().contains("testBean1")).isTrue();
assertThat(bean.getTestBeanMap().keySet().contains("testBean2")).isTrue();
assertThat(bean.getTestBeanMap().values().contains(tb1)).isTrue();
assertThat(bean.getTestBeanMap().values().contains(tb2)).isTrue();
bean = (MapConstructorInjectionBean) bf.getBean("annotatedBean");
assertThat(bean.getTestBeanMap()).hasSize(2);
assertThat(bean.getTestBeanMap()).containsKey("testBean1");
assertThat(bean.getTestBeanMap()).containsKey("testBean2");
assertThat(bean.getTestBeanMap()).containsValue(tb1);
assertThat(bean.getTestBeanMap()).containsValue(tb2);
assertThat(bean.getTestBeanMap().keySet().contains("testBean1")).isTrue();
assertThat(bean.getTestBeanMap().keySet().contains("testBean2")).isTrue();
assertThat(bean.getTestBeanMap().values().contains(tb1)).isTrue();
assertThat(bean.getTestBeanMap().values().contains(tb2)).isTrue();
}
@Test
@@ -247,17 +247,17 @@ public class InjectAnnotationBeanPostProcessorTests {
MapFieldInjectionBean bean = (MapFieldInjectionBean) bf.getBean("annotatedBean");
assertThat(bean.getTestBeanMap()).hasSize(2);
assertThat(bean.getTestBeanMap()).containsKey("testBean1");
assertThat(bean.getTestBeanMap()).containsKey("testBean2");
assertThat(bean.getTestBeanMap()).containsValue(tb1);
assertThat(bean.getTestBeanMap()).containsValue(tb2);
assertThat(bean.getTestBeanMap().keySet().contains("testBean1")).isTrue();
assertThat(bean.getTestBeanMap().keySet().contains("testBean2")).isTrue();
assertThat(bean.getTestBeanMap().values().contains(tb1)).isTrue();
assertThat(bean.getTestBeanMap().values().contains(tb2)).isTrue();
bean = (MapFieldInjectionBean) bf.getBean("annotatedBean");
assertThat(bean.getTestBeanMap()).hasSize(2);
assertThat(bean.getTestBeanMap()).containsKey("testBean1");
assertThat(bean.getTestBeanMap()).containsKey("testBean2");
assertThat(bean.getTestBeanMap()).containsValue(tb1);
assertThat(bean.getTestBeanMap()).containsValue(tb2);
assertThat(bean.getTestBeanMap().keySet().contains("testBean1")).isTrue();
assertThat(bean.getTestBeanMap().keySet().contains("testBean2")).isTrue();
assertThat(bean.getTestBeanMap().values().contains(tb1)).isTrue();
assertThat(bean.getTestBeanMap().values().contains(tb2)).isTrue();
}
@Test
@@ -270,14 +270,14 @@ public class InjectAnnotationBeanPostProcessorTests {
MapMethodInjectionBean bean = (MapMethodInjectionBean) bf.getBean("annotatedBean");
assertThat(bean.getTestBeanMap()).hasSize(1);
assertThat(bean.getTestBeanMap()).containsKey("testBean");
assertThat(bean.getTestBeanMap()).containsValue(tb);
assertThat(bean.getTestBeanMap().keySet().contains("testBean")).isTrue();
assertThat(bean.getTestBeanMap().values().contains(tb)).isTrue();
assertThat(bean.getTestBean()).isSameAs(tb);
bean = (MapMethodInjectionBean) bf.getBean("annotatedBean");
assertThat(bean.getTestBeanMap()).hasSize(1);
assertThat(bean.getTestBeanMap()).containsKey("testBean");
assertThat(bean.getTestBeanMap()).containsValue(tb);
assertThat(bean.getTestBeanMap().keySet().contains("testBean")).isTrue();
assertThat(bean.getTestBeanMap().values().contains(tb)).isTrue();
assertThat(bean.getTestBean()).isSameAs(tb);
}
@@ -301,8 +301,8 @@ public class InjectAnnotationBeanPostProcessorTests {
MapMethodInjectionBean bean = (MapMethodInjectionBean) bf.getBean("annotatedBean");
TestBean tb = (TestBean) bf.getBean("testBean1");
assertThat(bean.getTestBeanMap()).hasSize(1);
assertThat(bean.getTestBeanMap()).containsKey("testBean1");
assertThat(bean.getTestBeanMap()).containsValue(tb);
assertThat(bean.getTestBeanMap().keySet().contains("testBean1")).isTrue();
assertThat(bean.getTestBeanMap().values().contains(tb)).isTrue();
assertThat(bean.getTestBean()).isSameAs(tb);
}
@@ -530,7 +530,7 @@ public class InjectAnnotationBeanPostProcessorTests {
OptionalListFieldInjectionBean bean = (OptionalListFieldInjectionBean) bf.getBean("annotatedBean");
assertThat(bean.getTestBean()).isPresent();
assertThat(bean.getTestBean().get()).element(0).isSameAs(bf.getBean("testBean"));
assertThat(bean.getTestBean().get().get(0)).isSameAs(bf.getBean("testBean"));
}
@Test
@@ -548,7 +548,7 @@ public class InjectAnnotationBeanPostProcessorTests {
OptionalListMethodInjectionBean bean = (OptionalListMethodInjectionBean) bf.getBean("annotatedBean");
assertThat(bean.getTestBean()).isPresent();
assertThat(bean.getTestBean().get()).element(0).isSameAs(bf.getBean("testBean"));
assertThat(bean.getTestBean().get().get(0)).isSameAs(bf.getBean("testBean"));
}
@Test
@@ -115,7 +115,7 @@ class AotServicesTests {
AotServices<?> loaded = AotServices
.factories(new TestSpringFactoriesClassLoader("aot-services.factories"))
.load(TestService.class);
assertThat(loaded).element(0).isInstanceOf(TestServiceImpl.class);
assertThat(loaded.iterator().next()).isInstanceOf(TestServiceImpl.class);
}
@Test
@@ -45,8 +45,6 @@ import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.testfixture.beans.AnnotatedBean;
import org.springframework.beans.testfixture.beans.GenericBean;
import org.springframework.beans.testfixture.beans.TestBean;
import org.springframework.beans.testfixture.beans.factory.aot.CustomBean;
import org.springframework.beans.testfixture.beans.factory.aot.CustomPropertyValue;
import org.springframework.beans.testfixture.beans.factory.aot.InnerBeanConfiguration;
import org.springframework.beans.testfixture.beans.factory.aot.MockBeanRegistrationsCode;
import org.springframework.beans.testfixture.beans.factory.aot.SimpleBean;
@@ -607,23 +605,6 @@ class BeanDefinitionMethodGeneratorTests {
});
}
@Test
void generateBeanDefinitionMethodWhenCustomPropertyValueUsesCustomDelegate() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(CustomBean.class);
beanDefinition.getPropertyValues().addPropertyValue(
"customPropertyValue", new CustomPropertyValue("test"));
RegisteredBean bean = registerBean(beanDefinition);
BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator(
this.methodGeneratorFactory, bean, "test",
Collections.emptyList());
MethodReference method = generator.generateBeanDefinitionMethod(
this.generationContext, this.beanRegistrationsCode);
compile(method, (actual, compiled) ->
assertThat(actual.getPropertyValues().get("customPropertyValue"))
.isInstanceOfSatisfying(CustomPropertyValue.class, customPropertyValue
-> assertThat(customPropertyValue.value()).isEqualTo("test")));
}
@Test
void generateBeanDefinitionMethodWhenHasAotContributionsAppliesContributions() {
RegisteredBean registeredBean = registerBean(
@@ -18,7 +18,6 @@ package org.springframework.beans.factory.aot;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -29,12 +28,12 @@ import java.util.function.Supplier;
import javax.lang.model.element.Modifier;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.reactivestreams.Publisher;
import org.springframework.aot.generate.GeneratedClass;
import org.springframework.aot.generate.ValueCodeGenerator.Delegate;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
import org.springframework.aot.test.generate.TestGenerationContext;
@@ -51,7 +50,6 @@ import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.support.ManagedSet;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.testfixture.beans.factory.aot.CustomPropertyValue;
import org.springframework.beans.testfixture.beans.factory.aot.DeferredTypeBuilder;
import org.springframework.core.test.tools.Compiled;
import org.springframework.core.test.tools.TestCompiler;
@@ -260,10 +258,10 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
compile((actual, compiled) -> {
ConstructorArgumentValues argumentValues = actual.getConstructorArgumentValues();
List<ValueHolder> values = argumentValues.getGenericArgumentValues();
assertThat(values).element(0).satisfies(assertValueHolder(String.class, null, null));
assertThat(values).element(1).satisfies(assertValueHolder(2, Long.class, null));
assertThat(values).element(2).satisfies(assertValueHolder("value", null, "param1"));
assertThat(values).element(3).satisfies(assertValueHolder("another", CharSequence.class, "param2"));
assertThat(values.get(0)).satisfies(assertValueHolder(String.class, null, null));
assertThat(values.get(1)).satisfies(assertValueHolder(2, Long.class, null));
assertThat(values.get(2)).satisfies(assertValueHolder("value", null, "param1"));
assertThat(values.get(3)).satisfies(assertValueHolder("another", CharSequence.class, "param2"));
assertThat(values).hasSize(4);
assertThat(argumentValues.getIndexedArgumentValues()).isEmpty();
});
@@ -313,7 +311,7 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
assertThat(actual.getPropertyValues().contains("myService")).isTrue();
assertThat(actual.getPropertyValues().get("myService"))
.isInstanceOfSatisfying(RuntimeBeanReference.class,
beanReference -> assertThat(beanReference.getBeanName()).isEqualTo("test"));
beanReference -> assertThat(beanReference.getBeanName()).isEqualTo("test"));
});
}
@@ -325,7 +323,7 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
compile((actual, compiled) -> {
Object value = actual.getPropertyValues().get("value");
assertThat(value).isInstanceOf(ManagedList.class);
assertThat(((List<?>) value)).element(0).isInstanceOf(BeanReference.class);
assertThat(((List<?>) value).get(0)).isInstanceOf(BeanReference.class);
});
}
@@ -337,7 +335,7 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
compile((actual, compiled) -> {
Object value = actual.getPropertyValues().get("value");
assertThat(value).isInstanceOf(ManagedSet.class);
assertThat(((Set<?>) value)).element(0).isInstanceOf(BeanReference.class);
assertThat(((Set<?>) value).iterator().next()).isInstanceOf(BeanReference.class);
});
}
@@ -363,25 +361,10 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
assertThat(actual.getPropertyValues().get("prefix")).isEqualTo("Hello");
assertThat(actual.getPropertyValues().get("name")).isEqualTo("World");
});
assertHasMethodInvokeHints(PropertyValuesFactoryBean.class, "setPrefix", "setName");
assertHasMethodInvokeHints(PropertyValuesFactoryBean.class, "setPrefix", "setName" );
assertHasDeclaredFieldsHint(PropertyValuesFactoryBean.class);
}
@Test
void propertyValuesWhenCustomValuesUsingDelegate() {
this.beanDefinition.setTargetType(PropertyValuesBean.class);
this.beanDefinition.getPropertyValues().add("test", new CustomPropertyValue("test"));
this.beanDefinition.getPropertyValues().add("spring", new CustomPropertyValue("framework"));
compile(value -> true, List.of(new CustomPropertyValue.ValueCodeGeneratorDelegate()), (actual, compiled) -> {
assertThat(actual.getPropertyValues().get("test")).isInstanceOfSatisfying(CustomPropertyValue.class,
customPropertyValue -> assertThat(customPropertyValue.value()).isEqualTo("test"));
assertThat(actual.getPropertyValues().get("spring")).isInstanceOfSatisfying(CustomPropertyValue.class,
customPropertyValue -> assertThat(customPropertyValue.value()).isEqualTo("framework"));
});
assertHasMethodInvokeHints(PropertyValuesBean.class, "setTest", "setSpring");
assertHasDeclaredFieldsHint(PropertyValuesBean.class);
}
@Test
void attributesWhenAllFiltered() {
this.beanDefinition.setAttribute("a", "A");
@@ -429,8 +412,8 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
this.beanDefinition.addQualifier(new AutowireCandidateQualifier("com.example.Another", ChronoUnit.SECONDS));
compile((actual, compiled) -> {
List<AutowireCandidateQualifier> qualifiers = new ArrayList<>(actual.getQualifiers());
assertThat(qualifiers).element(0).satisfies(isQualifierFor("com.example.Qualifier", "id"));
assertThat(qualifiers).element(1).satisfies(isQualifierFor("com.example.Another", ChronoUnit.SECONDS));
assertThat(qualifiers.get(0)).satisfies(isQualifierFor("com.example.Qualifier", "id"));
assertThat(qualifiers.get(1)).satisfies(isQualifierFor("com.example.Another", ChronoUnit.SECONDS));
assertThat(qualifiers).hasSize(2);
});
}
@@ -457,36 +440,28 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
@Nested
class InitDestroyMethodTests {
private static final String privateInitMethod = InitDestroyBean.class.getName() + ".privateInit";
private final String privateInitMethod = InitDestroyBean.class.getName() + ".privateInit";
private final String privateDestroyMethod = InitDestroyBean.class.getName() + ".privateDestroy";
private static final String privateDestroyMethod = InitDestroyBean.class.getName() + ".privateDestroy";
@BeforeEach
void setTargetType() {
beanDefinition.setTargetType(InitDestroyBean.class);
}
@Test
void noInitMethod() {
beanDefinition.setTargetType(InitDestroyBean.class);
compile((beanDef, compiled) -> assertThat(beanDef.getInitMethodNames()).isNull());
}
@Test
void singleInitMethod() {
beanDefinition.setTargetType(InitDestroyBean.class);
beanDefinition.setInitMethodName("init");
compile((beanDef, compiled) -> assertThat(beanDef.getInitMethodNames()).containsExactly("init"));
assertHasMethodInvokeHints(InitDestroyBean.class, "init");
}
@Test
void singleInitMethodFromInterface() {
beanDefinition.setTargetType(InitializableTestBean.class);
beanDefinition.setInitMethodName("initialize");
compile((beanDef, compiled) -> assertThat(beanDef.getInitMethodNames()).containsExactly("initialize"));
assertHasMethodInvokeHints(InitializableTestBean.class, "initialize");
assertHasMethodInvokeHints(Initializable.class, "initialize");
}
@Test
void privateInitMethod() {
beanDefinition.setTargetType(InitDestroyBean.class);
beanDefinition.setInitMethodName(privateInitMethod);
compile((beanDef, compiled) -> assertThat(beanDef.getInitMethodNames()).containsExactly(privateInitMethod));
assertHasMethodInvokeHints(InitDestroyBean.class, "privateInit");
@@ -494,7 +469,6 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
@Test
void multipleInitMethods() {
beanDefinition.setTargetType(InitDestroyBean.class);
beanDefinition.setInitMethodNames("init", privateInitMethod);
compile((beanDef, compiled) -> assertThat(beanDef.getInitMethodNames()).containsExactly("init", privateInitMethod));
assertHasMethodInvokeHints(InitDestroyBean.class, "init", "privateInit");
@@ -502,33 +476,20 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
@Test
void noDestroyMethod() {
beanDefinition.setTargetType(InitDestroyBean.class);
compile((beanDef, compiled) -> assertThat(beanDef.getDestroyMethodNames()).isNull());
assertReflectionOnPublisher();
}
@Test
void singleDestroyMethod() {
beanDefinition.setTargetType(InitDestroyBean.class);
beanDefinition.setDestroyMethodName("destroy");
compile((beanDef, compiled) -> assertThat(beanDef.getDestroyMethodNames()).containsExactly("destroy"));
assertHasMethodInvokeHints(InitDestroyBean.class, "destroy");
assertReflectionOnPublisher();
}
@Test
void singleDestroyMethodFromInterface() {
beanDefinition.setTargetType(DisposableTestBean.class);
beanDefinition.setDestroyMethodName("dispose");
compile((beanDef, compiled) -> assertThat(beanDef.getDestroyMethodNames()).containsExactly("dispose"));
assertHasMethodInvokeHints(DisposableTestBean.class, "dispose");
assertHasMethodInvokeHints(Disposable.class, "dispose");
assertReflectionOnPublisher();
}
@Test
void privateDestroyMethod() {
beanDefinition.setTargetType(InitDestroyBean.class);
beanDefinition.setDestroyMethodName(privateDestroyMethod);
compile((beanDef, compiled) -> assertThat(beanDef.getDestroyMethodNames()).containsExactly(privateDestroyMethod));
assertHasMethodInvokeHints(InitDestroyBean.class, "privateDestroy");
@@ -537,7 +498,6 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
@Test
void multipleDestroyMethods() {
beanDefinition.setTargetType(InitDestroyBean.class);
beanDefinition.setDestroyMethodNames("destroy", privateDestroyMethod);
compile((beanDef, compiled) -> assertThat(beanDef.getDestroyMethodNames()).containsExactly("destroy", privateDestroyMethod));
assertHasMethodInvokeHints(InitDestroyBean.class, "destroy", "privateDestroy");
@@ -552,8 +512,8 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
private void assertHasMethodInvokeHints(Class<?> beanType, String... methodNames) {
assertThat(methodNames).allMatch(methodName -> RuntimeHintsPredicates.reflection()
.onMethod(beanType, methodName).invoke()
.test(this.generationContext.getRuntimeHints()));
.onMethod(beanType, methodName).invoke()
.test(this.generationContext.getRuntimeHints()));
}
private void assertHasDeclaredFieldsHint(Class<?> beanType) {
@@ -566,18 +526,12 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
compile(attribute -> true, result);
}
private void compile(Predicate<String> attributeFilter,
BiConsumer<RootBeanDefinition, Compiled> result) {
compile(attributeFilter, Collections.emptyList(), result);
}
private void compile(Predicate<String> attributeFilter, List<Delegate> additionalDelegates,
BiConsumer<RootBeanDefinition, Compiled> result) {
private void compile(Predicate<String> attributeFilter, BiConsumer<RootBeanDefinition, Compiled> result) {
DeferredTypeBuilder typeBuilder = new DeferredTypeBuilder();
GeneratedClass generatedClass = this.generationContext.getGeneratedClasses().addForFeature("TestCode", typeBuilder);
BeanDefinitionPropertiesCodeGenerator codeGenerator = new BeanDefinitionPropertiesCodeGenerator(
this.generationContext.getRuntimeHints(), attributeFilter,
generatedClass.getMethods(), additionalDelegates, (name, value) -> null);
generatedClass.getMethods(), (name, value) -> null);
CodeBlock generatedCode = codeGenerator.generateCode(this.beanDefinition);
typeBuilder.set(type -> {
type.addModifiers(Modifier.PUBLIC);
@@ -615,31 +569,6 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
}
interface Initializable {
void initialize();
}
static class InitializableTestBean implements Initializable {
@Override
public void initialize() {
}
}
interface Disposable {
void dispose();
}
static class DisposableTestBean implements Disposable {
@Override
public void dispose() {
}
}
static class PropertyValuesBean {
private Class<?> test;
@@ -36,8 +36,6 @@ import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.aot.generate.GeneratedClass;
import org.springframework.aot.generate.ValueCodeGenerator;
import org.springframework.aot.generate.ValueCodeGeneratorDelegates;
import org.springframework.aot.test.generate.TestGenerationContext;
import org.springframework.beans.factory.config.BeanReference;
import org.springframework.beans.factory.config.RuntimeBeanNameReference;
@@ -49,38 +47,33 @@ import org.springframework.beans.testfixture.beans.factory.aot.DeferredTypeBuild
import org.springframework.core.ResolvableType;
import org.springframework.core.test.tools.Compiled;
import org.springframework.core.test.tools.TestCompiler;
import org.springframework.core.testfixture.aot.generate.value.EnumWithClassBody;
import org.springframework.core.testfixture.aot.generate.value.ExampleClass;
import org.springframework.core.testfixture.aot.generate.value.ExampleClass$$GeneratedBy;
import org.springframework.javapoet.CodeBlock;
import org.springframework.javapoet.MethodSpec;
import org.springframework.javapoet.ParameterizedTypeName;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
/**
* Tests for {@link BeanDefinitionPropertyValueCodeGeneratorDelegates}. This
* also tests that code generated by {@link ValueCodeGeneratorDelegates}
* compiles.
* Tests for {@link BeanDefinitionPropertyValueCodeGenerator}.
*
* @author Stephane Nicoll
* @author Phillip Webb
* @author Sebastien Deleuze
* @since 6.0
* @see BeanDefinitionPropertyValueCodeGeneratorTests
*/
class BeanDefinitionPropertyValueCodeGeneratorDelegatesTests {
class BeanDefinitionPropertyValueCodeGeneratorTests {
private static ValueCodeGenerator createValueCodeGenerator(GeneratedClass generatedClass) {
return ValueCodeGenerator.with(BeanDefinitionPropertyValueCodeGeneratorDelegates.INSTANCES)
.add(ValueCodeGeneratorDelegates.INSTANCES)
.scoped(generatedClass.getMethods());
private static BeanDefinitionPropertyValueCodeGenerator createPropertyValuesCodeGenerator(GeneratedClass generatedClass) {
return new BeanDefinitionPropertyValueCodeGenerator(generatedClass.getMethods(), null);
}
private void compile(Object value, BiConsumer<Object, Compiled> result) {
TestGenerationContext generationContext = new TestGenerationContext();
DeferredTypeBuilder typeBuilder = new DeferredTypeBuilder();
GeneratedClass generatedClass = generationContext.getGeneratedClasses().addForFeature("TestCode", typeBuilder);
CodeBlock generatedCode = createValueCodeGenerator(generatedClass).generateCode(value);
CodeBlock generatedCode = createPropertyValuesCodeGenerator(generatedClass).generateCode(value);
typeBuilder.set(type -> {
type.addModifiers(Modifier.PUBLIC);
type.addSuperinterface(
@@ -108,72 +101,90 @@ class BeanDefinitionPropertyValueCodeGeneratorDelegatesTests {
@Test
void generateWhenBoolean() {
compile(true, (instance, compiled) ->
assertThat(instance).isEqualTo(Boolean.TRUE));
compile(true, (instance, compiled) -> {
assertThat(instance).isEqualTo(Boolean.TRUE);
assertThat(compiled.getSourceFile()).contains("true");
});
}
@Test
void generateWhenByte() {
compile((byte) 2, (instance, compiled) ->
assertThat(instance).isEqualTo((byte) 2));
compile((byte) 2, (instance, compiled) -> {
assertThat(instance).isEqualTo((byte) 2);
assertThat(compiled.getSourceFile()).contains("(byte) 2");
});
}
@Test
void generateWhenShort() {
compile((short) 3, (instance, compiled) ->
assertThat(instance).isEqualTo((short) 3));
compile((short) 3, (instance, compiled) -> {
assertThat(instance).isEqualTo((short) 3);
assertThat(compiled.getSourceFile()).contains("(short) 3");
});
}
@Test
void generateWhenInt() {
compile(4, (instance, compiled) ->
assertThat(instance).isEqualTo(4));
compile(4, (instance, compiled) -> {
assertThat(instance).isEqualTo(4);
assertThat(compiled.getSourceFile()).contains("return 4;");
});
}
@Test
void generateWhenLong() {
compile(5L, (instance, compiled) ->
assertThat(instance).isEqualTo(5L));
compile(5L, (instance, compiled) -> {
assertThat(instance).isEqualTo(5L);
assertThat(compiled.getSourceFile()).contains("5L");
});
}
@Test
void generateWhenFloat() {
compile(0.1F, (instance, compiled) ->
assertThat(instance).isEqualTo(0.1F));
compile(0.1F, (instance, compiled) -> {
assertThat(instance).isEqualTo(0.1F);
assertThat(compiled.getSourceFile()).contains("0.1F");
});
}
@Test
void generateWhenDouble() {
compile(0.2, (instance, compiled) ->
assertThat(instance).isEqualTo(0.2));
compile(0.2, (instance, compiled) -> {
assertThat(instance).isEqualTo(0.2);
assertThat(compiled.getSourceFile()).contains("(double) 0.2");
});
}
@Test
void generateWhenChar() {
compile('a', (instance, compiled) ->
assertThat(instance).isEqualTo('a'));
compile('a', (instance, compiled) -> {
assertThat(instance).isEqualTo('a');
assertThat(compiled.getSourceFile()).contains("'a'");
});
}
@Test
void generateWhenSimpleEscapedCharReturnsEscaped() {
testEscaped('\b');
testEscaped('\t');
testEscaped('\n');
testEscaped('\f');
testEscaped('\r');
testEscaped('\"');
testEscaped('\'');
testEscaped('\\');
testEscaped('\b', "'\\b'");
testEscaped('\t', "'\\t'");
testEscaped('\n', "'\\n'");
testEscaped('\f', "'\\f'");
testEscaped('\r', "'\\r'");
testEscaped('\"', "'\"'");
testEscaped('\'', "'\\''");
testEscaped('\\', "'\\\\'");
}
@Test
void generatedWhenUnicodeEscapedCharReturnsEscaped() {
testEscaped('\u007f');
testEscaped('\u007f', "'\\u007f'");
}
private void testEscaped(char value) {
compile(value, (instance, compiled) ->
assertThat(instance).isEqualTo(value));
private void testEscaped(char value, String expectedSourceContent) {
compile(value, (instance, compiled) -> {
assertThat(instance).isEqualTo(value);
assertThat(compiled.getSourceFile()).contains(expectedSourceContent);
});
}
}
@@ -183,8 +194,10 @@ class BeanDefinitionPropertyValueCodeGeneratorDelegatesTests {
@Test
void generateWhenString() {
compile("test\n", (instance, compiled) ->
assertThat(instance).isEqualTo("test\n"));
compile("test\n", (instance, compiled) -> {
assertThat(instance).isEqualTo("test\n");
assertThat(compiled.getSourceFile()).contains("\n");
});
}
}
@@ -194,8 +207,10 @@ class BeanDefinitionPropertyValueCodeGeneratorDelegatesTests {
@Test
void generateWhenCharset() {
compile(StandardCharsets.UTF_8, (instance, compiled) ->
assertThat(instance).isEqualTo(Charset.forName("UTF-8")));
compile(StandardCharsets.UTF_8, (instance, compiled) -> {
assertThat(instance).isEqualTo(Charset.forName("UTF-8"));
assertThat(compiled.getSourceFile()).contains("\"UTF-8\"");
});
}
}
@@ -205,14 +220,18 @@ class BeanDefinitionPropertyValueCodeGeneratorDelegatesTests {
@Test
void generateWhenEnum() {
compile(ChronoUnit.DAYS, (instance, compiled) ->
assertThat(instance).isEqualTo(ChronoUnit.DAYS));
compile(ChronoUnit.DAYS, (instance, compiled) -> {
assertThat(instance).isEqualTo(ChronoUnit.DAYS);
assertThat(compiled.getSourceFile()).contains("ChronoUnit.DAYS");
});
}
@Test
void generateWhenEnumWithClassBody() {
compile(EnumWithClassBody.TWO, (instance, compiled) ->
assertThat(instance).isEqualTo(EnumWithClassBody.TWO));
compile(EnumWithClassBody.TWO, (instance, compiled) -> {
assertThat(instance).isEqualTo(EnumWithClassBody.TWO);
assertThat(compiled.getSourceFile()).contains("EnumWithClassBody.TWO");
});
}
}
@@ -247,16 +266,18 @@ class BeanDefinitionPropertyValueCodeGeneratorDelegatesTests {
@Test
void generateWhenNoneResolvableType() {
ResolvableType resolvableType = ResolvableType.NONE;
compile(resolvableType, (instance, compiled) ->
assertThat(instance).isEqualTo(resolvableType));
compile(resolvableType, (instance, compiled) -> {
assertThat(instance).isEqualTo(resolvableType);
assertThat(compiled.getSourceFile()).contains("ResolvableType.NONE");
});
}
@Test
void generateWhenGenericResolvableType() {
ResolvableType resolvableType = ResolvableType
.forClassWithGenerics(List.class, String.class);
compile(resolvableType, (instance, compiled) ->
assertThat(instance).isEqualTo(resolvableType));
compile(resolvableType, (instance, compiled) -> assertThat(instance)
.isEqualTo(resolvableType));
}
@Test
@@ -277,22 +298,28 @@ class BeanDefinitionPropertyValueCodeGeneratorDelegatesTests {
@Test
void generateWhenPrimitiveArray() {
byte[] bytes = { 0, 1, 2 };
compile(bytes, (instance, compiler) ->
assertThat(instance).isEqualTo(bytes));
compile(bytes, (instance, compiler) -> {
assertThat(instance).isEqualTo(bytes);
assertThat(compiler.getSourceFile()).contains("new byte[]");
});
}
@Test
void generateWhenWrapperArray() {
Byte[] bytes = { 0, 1, 2 };
compile(bytes, (instance, compiler) ->
assertThat(instance).isEqualTo(bytes));
compile(bytes, (instance, compiler) -> {
assertThat(instance).isEqualTo(bytes);
assertThat(compiler.getSourceFile()).contains("new Byte[]");
});
}
@Test
void generateWhenClassArray() {
Class<?>[] classes = new Class<?>[] { InputStream.class, OutputStream.class };
compile(classes, (instance, compiler) ->
assertThat(instance).isEqualTo(classes));
compile(classes, (instance, compiler) -> {
assertThat(instance).isEqualTo(classes);
assertThat(compiler.getSourceFile()).contains("new Class[]");
});
}
}
@@ -375,7 +402,10 @@ class BeanDefinitionPropertyValueCodeGeneratorDelegatesTests {
@Test
void generateWhenEmptyList() {
List<String> list = List.of();
compile(list, (instance, compiler) -> assertThat(instance).isEqualTo(list));
compile(list, (instance, compiler) -> {
assertThat(instance).isEqualTo(list);
assertThat(compiler.getSourceFile()).contains("Collections.emptyList();");
});
}
}
@@ -393,14 +423,20 @@ class BeanDefinitionPropertyValueCodeGeneratorDelegatesTests {
@Test
void generateWhenEmptySet() {
Set<String> set = Set.of();
compile(set, (instance, compiler) -> assertThat(instance).isEqualTo(set));
compile(set, (instance, compiler) -> {
assertThat(instance).isEqualTo(set);
assertThat(compiler.getSourceFile()).contains("Collections.emptySet();");
});
}
@Test
void generateWhenLinkedHashSet() {
Set<String> set = new LinkedHashSet<>(List.of("a", "b", "c"));
compile(set, (instance, compiler) ->
assertThat(instance).isEqualTo(set).isInstanceOf(LinkedHashSet.class));
compile(set, (instance, compiler) -> {
assertThat(instance).isEqualTo(set).isInstanceOf(LinkedHashSet.class);
assertThat(compiler.getSourceFile())
.contains("new LinkedHashSet(List.of(");
});
}
@Test
@@ -417,8 +453,10 @@ class BeanDefinitionPropertyValueCodeGeneratorDelegatesTests {
@Test
void generateWhenSmallMap() {
Map<String, String> map = Map.of("k1", "v1", "k2", "v2");
compile(map, (instance, compiler) ->
assertThat(instance).isEqualTo(map));
compile(map, (instance, compiler) -> {
assertThat(instance).isEqualTo(map);
assertThat(compiler.getSourceFile()).contains("Map.of(");
});
}
@Test
@@ -427,7 +465,10 @@ class BeanDefinitionPropertyValueCodeGeneratorDelegatesTests {
for (int i = 1; i <= 11; i++) {
map.put("k" + i, "v" + i);
}
compile(map, (instance, compiler) -> assertThat(instance).isEqualTo(map));
compile(map, (instance, compiler) -> {
assertThat(instance).isEqualTo(map);
assertThat(compiler.getSourceFile()).contains("Map.ofEntries(");
});
}
@Test
@@ -477,4 +518,47 @@ class BeanDefinitionPropertyValueCodeGeneratorDelegatesTests {
}
@Nested
static class ExceptionTests {
@Test
void generateWhenUnsupportedDataTypeThrowsException() {
SampleValue sampleValue = new SampleValue("one");
assertThatIllegalArgumentException().isThrownBy(() -> generateCode(sampleValue))
.withMessageContaining("Failed to generate code for")
.withMessageContaining(sampleValue.toString())
.withMessageContaining(SampleValue.class.getName())
.havingCause()
.withMessageContaining("Code generation does not support")
.withMessageContaining(SampleValue.class.getName());
}
@Test
void generateWhenListOfUnsupportedElement() {
SampleValue one = new SampleValue("one");
SampleValue two = new SampleValue("two");
List<SampleValue> list = List.of(one, two);
assertThatIllegalArgumentException().isThrownBy(() -> generateCode(list))
.withMessageContaining("Failed to generate code for")
.withMessageContaining(list.toString())
.withMessageContaining(list.getClass().getName())
.havingCause()
.withMessageContaining("Failed to generate code for")
.withMessageContaining(one.toString())
.withMessageContaining("?")
.havingCause()
.withMessageContaining("Code generation does not support ?");
}
private void generateCode(Object value) {
TestGenerationContext context = new TestGenerationContext();
GeneratedClass generatedClass = context.getGeneratedClasses()
.addForFeature("Test", type -> {});
createPropertyValuesCodeGenerator(generatedClass).generateCode(value);
}
record SampleValue(String name) {}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2022 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.core.testfixture.aot.generate.value;
package org.springframework.beans.factory.aot;
/**
* Test enum that include a class body.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2022 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.
@@ -14,13 +14,13 @@
* limitations under the License.
*/
package org.springframework.core.testfixture.aot.generate.value;
package org.springframework.beans.factory.aot;
/**
* Fake CGLIB generated class.
*
* @author Phillip Webb
*/
public class ExampleClass$$GeneratedBy extends ExampleClass {
class ExampleClass$$GeneratedBy extends ExampleClass {
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2022 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.core.testfixture.aot.generate.value;
package org.springframework.beans.factory.aot;
/**
* Public example class used for test.
@@ -66,7 +66,7 @@ public class CustomScopeConfigurerTests {
CustomScopeConfigurer figurer = new CustomScopeConfigurer();
figurer.setScopes(scopes);
figurer.postProcessBeanFactory(factory);
assertThat(factory.getRegisteredScope(FOO_SCOPE)).isInstanceOf(NoOpScope.class);
assertThat(factory.getRegisteredScope(FOO_SCOPE) instanceof NoOpScope).isTrue();
}
@Test
@@ -76,7 +76,7 @@ public class CustomScopeConfigurerTests {
CustomScopeConfigurer figurer = new CustomScopeConfigurer();
figurer.setScopes(scopes);
figurer.postProcessBeanFactory(factory);
assertThat(factory.getRegisteredScope(FOO_SCOPE)).isInstanceOf(NoOpScope.class);
assertThat(factory.getRegisteredScope(FOO_SCOPE) instanceof NoOpScope).isTrue();
}
@Test
@@ -49,7 +49,7 @@ public class PropertyPathFactoryBeanTests {
assertThat(xbf.getType("otb.spouse")).isEqualTo(ITestBean.class);
Object result1 = xbf.getBean("otb.spouse");
Object result2 = xbf.getBean("otb.spouse");
assertThat(result1).isInstanceOf(TestBean.class);
assertThat(result1 instanceof TestBean).isTrue();
assertThat(result1).isSameAs(result2);
assertThat(((TestBean) result1).getAge()).isEqualTo(99);
}
@@ -63,9 +63,9 @@ public class PropertyPathFactoryBeanTests {
Object result1 = xbf.getBean("tb.spouse");
Object result2 = xbf.getBean("propertyPath3");
Object result3 = xbf.getBean("propertyPath3");
assertThat(result1).isInstanceOf(TestBean.class);
assertThat(result2).isInstanceOf(TestBean.class);
assertThat(result3).isInstanceOf(TestBean.class);
assertThat(result1 instanceof TestBean).isTrue();
assertThat(result2 instanceof TestBean).isTrue();
assertThat(result3 instanceof TestBean).isTrue();
assertThat(((TestBean) result1).getAge()).isEqualTo(11);
assertThat(((TestBean) result2).getAge()).isEqualTo(11);
assertThat(((TestBean) result3).getAge()).isEqualTo(11);
@@ -89,7 +89,7 @@ public class PropertyPathFactoryBeanTests {
TestBean spouse = (TestBean) xbf.getBean("otb.spouse");
TestBean tbWithInner = (TestBean) xbf.getBean("tbWithInner");
assertThat(tbWithInner.getSpouse()).isSameAs(spouse);
assertThat(tbWithInner.getFriends()).isNotEmpty();
assertThat(!tbWithInner.getFriends().isEmpty()).isTrue();
assertThat(tbWithInner.getFriends().iterator().next()).isSameAs(spouse);
}
@@ -405,7 +405,7 @@ public class PropertyResourceConfigurerTests {
assertThat(tb2.getStringArray()[0]).isEqualTo(System.getProperty("os.name"));
assertThat(tb2.getStringArray()[1]).isEqualTo("98");
assertThat(tb2.getFriends()).hasSize(2);
assertThat(tb2.getFriends()).element(0).isEqualTo("na98me");
assertThat(tb2.getFriends().iterator().next()).isEqualTo("na98me");
assertThat(tb2.getFriends().toArray()[1]).isEqualTo(tb2);
assertThat(tb2.getSomeSet()).hasSize(3);
assertThat(tb2.getSomeSet().contains("na98me")).isTrue();
@@ -198,10 +198,10 @@ public class ServiceLocatorFactoryBeanTests {
assertThat(testBean3).isNotSameAs(testBean2);
assertThat(testBean4).isNotSameAs(testBean2);
assertThat(testBean4).isNotSameAs(testBean3);
assertThat(testBean1).isNotInstanceOf(ExtendedTestService.class);
assertThat(testBean2).isNotInstanceOf(ExtendedTestService.class);
assertThat(testBean3).isNotInstanceOf(ExtendedTestService.class);
assertThat(testBean4).isInstanceOf(ExtendedTestService.class);
assertThat(testBean1 instanceof ExtendedTestService).isFalse();
assertThat(testBean2 instanceof ExtendedTestService).isFalse();
assertThat(testBean3 instanceof ExtendedTestService).isFalse();
assertThat(testBean4 instanceof ExtendedTestService).isTrue();
}
@Test
@@ -99,7 +99,7 @@ public class YamlMapFactoryBeanTests {
assertThat(map).hasSize(1);
assertThat(map.containsKey("foo")).isTrue();
Object object = map.get("foo");
assertThat(object).isInstanceOf(LinkedHashMap.class);
assertThat(object instanceof LinkedHashMap).isTrue();
@SuppressWarnings("unchecked")
Map<String, Object> sub = (Map<String, Object>) object;
assertThat(sub.containsKey("key1.key2")).isTrue();
@@ -114,7 +114,7 @@ public class YamlMapFactoryBeanTests {
assertThat(map).hasSize(1);
assertThat(map.containsKey("foo")).isTrue();
Object object = map.get("foo");
assertThat(object).isInstanceOf(LinkedHashMap.class);
assertThat(object instanceof LinkedHashMap).isTrue();
@SuppressWarnings("unchecked")
Map<String, Object> sub = (Map<String, Object>) object;
assertThat(sub).hasSize(1);
@@ -48,7 +48,7 @@ class ServiceLoaderTests {
bd.getPropertyValues().add("serviceType", DocumentBuilderFactory.class.getName());
bf.registerBeanDefinition("service", bd);
ServiceLoader<?> serviceLoader = (ServiceLoader<?>) bf.getBean("service");
assertThat(serviceLoader).element(0).isInstanceOf(DocumentBuilderFactory.class);
assertThat(serviceLoader.iterator().next() instanceof DocumentBuilderFactory).isTrue();
}
@Test
@@ -57,7 +57,7 @@ class ServiceLoaderTests {
RootBeanDefinition bd = new RootBeanDefinition(ServiceFactoryBean.class);
bd.getPropertyValues().add("serviceType", DocumentBuilderFactory.class.getName());
bf.registerBeanDefinition("service", bd);
assertThat(bf.getBean("service")).isInstanceOf(DocumentBuilderFactory.class);
assertThat(bf.getBean("service") instanceof DocumentBuilderFactory).isTrue();
}
@Test
@@ -67,7 +67,7 @@ class ServiceLoaderTests {
bd.getPropertyValues().add("serviceType", DocumentBuilderFactory.class.getName());
bf.registerBeanDefinition("service", bd);
List<?> serviceList = (List<?>) bf.getBean("service");
assertThat(serviceList).element(0).isInstanceOf(DocumentBuilderFactory.class);
assertThat(serviceList.get(0) instanceof DocumentBuilderFactory).isTrue();
}
}
@@ -35,13 +35,13 @@ public class BeanDefinitionTests {
bd.setLazyInit(true);
bd.setScope("request");
RootBeanDefinition otherBd = new RootBeanDefinition(TestBean.class);
assertThat(bd).isNotEqualTo(otherBd);
assertThat(otherBd).isNotEqualTo(bd);
assertThat(!bd.equals(otherBd)).isTrue();
assertThat(!otherBd.equals(bd)).isTrue();
otherBd.setAbstract(true);
otherBd.setLazyInit(true);
otherBd.setScope("request");
assertThat(bd).isEqualTo(otherBd);
assertThat(otherBd).isEqualTo(bd);
assertThat(bd.equals(otherBd)).isTrue();
assertThat(otherBd.equals(bd)).isTrue();
assertThat(bd.hashCode()).isEqualTo(otherBd.hashCode());
}
@@ -52,14 +52,14 @@ public class BeanDefinitionTests {
bd.getPropertyValues().add("age", "99");
RootBeanDefinition otherBd = new RootBeanDefinition(TestBean.class);
otherBd.getPropertyValues().add("name", "myName");
assertThat(bd).isNotEqualTo(otherBd);
assertThat(otherBd).isNotEqualTo(bd);
assertThat(!bd.equals(otherBd)).isTrue();
assertThat(!otherBd.equals(bd)).isTrue();
otherBd.getPropertyValues().add("age", "11");
assertThat(bd).isNotEqualTo(otherBd);
assertThat(otherBd).isNotEqualTo(bd);
assertThat(!bd.equals(otherBd)).isTrue();
assertThat(!otherBd.equals(bd)).isTrue();
otherBd.getPropertyValues().add("age", "99");
assertThat(bd).isEqualTo(otherBd);
assertThat(otherBd).isEqualTo(bd);
assertThat(bd.equals(otherBd)).isTrue();
assertThat(otherBd.equals(bd)).isTrue();
assertThat(bd.hashCode()).isEqualTo(otherBd.hashCode());
}
@@ -70,14 +70,14 @@ public class BeanDefinitionTests {
bd.getConstructorArgumentValues().addIndexedArgumentValue(1, 5);
RootBeanDefinition otherBd = new RootBeanDefinition(TestBean.class);
otherBd.getConstructorArgumentValues().addGenericArgumentValue("test");
assertThat(bd).isNotEqualTo(otherBd);
assertThat(otherBd).isNotEqualTo(bd);
assertThat(!bd.equals(otherBd)).isTrue();
assertThat(!otherBd.equals(bd)).isTrue();
otherBd.getConstructorArgumentValues().addIndexedArgumentValue(1, 9);
assertThat(bd).isNotEqualTo(otherBd);
assertThat(otherBd).isNotEqualTo(bd);
assertThat(!bd.equals(otherBd)).isTrue();
assertThat(!otherBd.equals(bd)).isTrue();
otherBd.getConstructorArgumentValues().addIndexedArgumentValue(1, 5);
assertThat(bd).isEqualTo(otherBd);
assertThat(otherBd).isEqualTo(bd);
assertThat(bd.equals(otherBd)).isTrue();
assertThat(otherBd.equals(bd)).isTrue();
assertThat(bd.hashCode()).isEqualTo(otherBd.hashCode());
}
@@ -89,14 +89,14 @@ public class BeanDefinitionTests {
RootBeanDefinition otherBd = new RootBeanDefinition(TestBean.class);
otherBd.getConstructorArgumentValues().addGenericArgumentValue("test", "int");
otherBd.getConstructorArgumentValues().addIndexedArgumentValue(1, 5);
assertThat(bd).isNotEqualTo(otherBd);
assertThat(otherBd).isNotEqualTo(bd);
assertThat(!bd.equals(otherBd)).isTrue();
assertThat(!otherBd.equals(bd)).isTrue();
otherBd.getConstructorArgumentValues().addIndexedArgumentValue(1, 5, "int");
assertThat(bd).isNotEqualTo(otherBd);
assertThat(otherBd).isNotEqualTo(bd);
assertThat(!bd.equals(otherBd)).isTrue();
assertThat(!otherBd.equals(bd)).isTrue();
otherBd.getConstructorArgumentValues().addIndexedArgumentValue(1, 5, "long");
assertThat(bd).isEqualTo(otherBd);
assertThat(otherBd).isEqualTo(bd);
assertThat(bd.equals(otherBd)).isTrue();
assertThat(otherBd.equals(bd)).isTrue();
assertThat(bd.hashCode()).isEqualTo(otherBd.hashCode());
}
@@ -111,21 +111,21 @@ public class BeanDefinitionTests {
otherBd.setScope("request");
otherBd.setAbstract(true);
otherBd.setLazyInit(true);
assertThat(bd).isNotEqualTo(otherBd);
assertThat(otherBd).isNotEqualTo(bd);
assertThat(!bd.equals(otherBd)).isTrue();
assertThat(!otherBd.equals(bd)).isTrue();
otherBd.setParentName("parent");
assertThat(bd).isEqualTo(otherBd);
assertThat(otherBd).isEqualTo(bd);
assertThat(bd.equals(otherBd)).isTrue();
assertThat(otherBd.equals(bd)).isTrue();
assertThat(bd.hashCode()).isEqualTo(otherBd.hashCode());
bd.getPropertyValues();
assertThat(bd).isEqualTo(otherBd);
assertThat(otherBd).isEqualTo(bd);
assertThat(bd.equals(otherBd)).isTrue();
assertThat(otherBd.equals(bd)).isTrue();
assertThat(bd.hashCode()).isEqualTo(otherBd.hashCode());
bd.getConstructorArgumentValues();
assertThat(bd).isEqualTo(otherBd);
assertThat(otherBd).isEqualTo(bd);
assertThat(bd.equals(otherBd)).isTrue();
assertThat(otherBd.equals(bd)).isTrue();
assertThat(bd.hashCode()).isEqualTo(otherBd.hashCode());
}
@@ -137,14 +137,14 @@ public class BeanDefinitionTests {
bd.setScope("request");
BeanDefinitionHolder holder = new BeanDefinitionHolder(bd, "bd");
RootBeanDefinition otherBd = new RootBeanDefinition(TestBean.class);
assertThat(bd).isNotEqualTo(otherBd);
assertThat(otherBd).isNotEqualTo(bd);
assertThat(!bd.equals(otherBd)).isTrue();
assertThat(!otherBd.equals(bd)).isTrue();
otherBd.setAbstract(true);
otherBd.setLazyInit(true);
otherBd.setScope("request");
BeanDefinitionHolder otherHolder = new BeanDefinitionHolder(bd, "bd");
assertThat(holder).isEqualTo(otherHolder);
assertThat(otherHolder).isEqualTo(holder);
assertThat(holder.equals(otherHolder)).isTrue();
assertThat(otherHolder.equals(holder)).isTrue();
assertThat(holder.hashCode()).isEqualTo(otherHolder.hashCode());
}
@@ -564,8 +564,8 @@ class BeanFactoryGenericsTests {
new ClassPathResource("genericBeanTests.xml", getClass()));
GenericIntegerBean gb = (GenericIntegerBean) bf.getBean("integerBean");
assertThat(gb.getGenericProperty()).isEqualTo(10);
assertThat(gb.getGenericListProperty()).element(0).isEqualTo(20);
assertThat(gb.getGenericListProperty()).element(1).isEqualTo(30);
assertThat(gb.getGenericListProperty().get(0)).isEqualTo(20);
assertThat(gb.getGenericListProperty().get(1)).isEqualTo(30);
}
@Test
@@ -574,9 +574,9 @@ class BeanFactoryGenericsTests {
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
new ClassPathResource("genericBeanTests.xml", getClass()));
GenericSetOfIntegerBean gb = (GenericSetOfIntegerBean) bf.getBean("setOfIntegerBean");
assertThat(gb.getGenericProperty()).element(0).isEqualTo(10);
assertThat(gb.getGenericListProperty().get(0)).element(0).isEqualTo(20);
assertThat(gb.getGenericListProperty().get(1)).element(0).isEqualTo(30);
assertThat(gb.getGenericProperty().iterator().next()).isEqualTo(10);
assertThat(gb.getGenericListProperty().get(0).iterator().next()).isEqualTo(20);
assertThat(gb.getGenericListProperty().get(1).iterator().next()).isEqualTo(30);
}
@Test
@@ -811,18 +811,18 @@ class BeanFactoryGenericsTests {
resolved.add(instance);
}
assertThat(resolved).hasSize(2);
assertThat(resolved).element(0).isSameAs(bf.getBean("store1"));
assertThat(resolved).element(1).isSameAs(bf.getBean("store2"));
assertThat(resolved.get(0)).isSameAs(bf.getBean("store1"));
assertThat(resolved.get(1)).isSameAs(bf.getBean("store2"));
resolved = numberStoreProvider.stream().toList();
assertThat(resolved).hasSize(2);
assertThat(resolved).element(0).isSameAs(bf.getBean("store1"));
assertThat(resolved).element(1).isSameAs(bf.getBean("store2"));
assertThat(resolved.get(0)).isSameAs(bf.getBean("store1"));
assertThat(resolved.get(1)).isSameAs(bf.getBean("store2"));
resolved = numberStoreProvider.orderedStream().toList();
assertThat(resolved).hasSize(2);
assertThat(resolved).element(0).isSameAs(bf.getBean("store2"));
assertThat(resolved).element(1).isSameAs(bf.getBean("store1"));
assertThat(resolved.get(0)).isSameAs(bf.getBean("store2"));
assertThat(resolved.get(1)).isSameAs(bf.getBean("store1"));
resolved = new ArrayList<>();
for (NumberStore<Double> instance : doubleStoreProvider) {
@@ -865,8 +865,8 @@ class BeanFactoryGenericsTests {
ObjectProvider<NumberStore<?>> numberStoreProvider = bf.getBeanProvider(ResolvableType.forClass(NumberStore.class));
List<NumberStore<?>> resolved = numberStoreProvider.orderedStream().toList();
assertThat(resolved).hasSize(2);
assertThat(resolved).element(0).isSameAs(bf.getBean("store2"));
assertThat(resolved).element(1).isSameAs(bf.getBean("store1"));
assertThat(resolved.get(0)).isSameAs(bf.getBean("store2"));
assertThat(resolved.get(1)).isSameAs(bf.getBean("store1"));
}
@@ -59,10 +59,12 @@ public class Spr8954Tests {
@SuppressWarnings("rawtypes")
Map<String, FactoryBean> fbBeans = bf.getBeansOfType(FactoryBean.class);
assertThat(fbBeans).containsOnlyKeys("&foo");
assertThat(fbBeans).hasSize(1);
assertThat(fbBeans.keySet()).contains("&foo");
Map<String, AnInterface> aiBeans = bf.getBeansOfType(AnInterface.class);
assertThat(aiBeans).containsOnlyKeys("&foo");
assertThat(aiBeans).hasSize(1);
assertThat(aiBeans.keySet()).contains("&foo");
}
@Test
@@ -71,10 +73,12 @@ public class Spr8954Tests {
@SuppressWarnings("rawtypes")
Map<String, FactoryBean> fbBeans = bf.getBeansOfType(FactoryBean.class);
assertThat(fbBeans).containsOnlyKeys("&foo");
assertThat(fbBeans.size()).isEqualTo(1);
assertThat(fbBeans.keySet().iterator().next()).isEqualTo("&foo");
Map<String, AnInterface> aiBeans = bf.getBeansOfType(AnInterface.class);
assertThat(aiBeans).containsOnlyKeys("&foo");
assertThat(aiBeans).hasSize(1);
assertThat(aiBeans.keySet()).contains("&foo");
}
/**
@@ -86,7 +90,8 @@ public class Spr8954Tests {
assertThat(Arrays.asList(names)).contains("&foo");
Map<String, AnInterface> beans = bf.getBeansOfType(AnInterface.class, false, false);
assertThat(beans).containsOnlyKeys("&foo");
assertThat(beans).hasSize(1);
assertThat(beans.keySet()).contains("&foo");
}
@@ -55,9 +55,9 @@ public class CollectionMergingTests {
TestBean bean = (TestBean) this.beanFactory.getBean("childWithList");
List<?> list = bean.getSomeList();
assertThat(list).as("Incorrect size").hasSize(3);
assertThat(list).element(0).isEqualTo("Rob Harrop");
assertThat(list).element(1).isEqualTo("Rod Johnson");
assertThat(list).element(2).isEqualTo("Juergen Hoeller");
assertThat(list.get(0)).isEqualTo("Rob Harrop");
assertThat(list.get(1)).isEqualTo("Rod Johnson");
assertThat(list.get(2)).isEqualTo("Juergen Hoeller");
}
@Test
@@ -66,7 +66,7 @@ public class CollectionMergingTests {
List<?> list = bean.getSomeList();
assertThat(list).isNotNull();
assertThat(list).hasSize(3);
assertThat(list.get(2)).isInstanceOf(TestBean.class);
assertThat(list.get(2) instanceof TestBean).isTrue();
}
@Test
@@ -87,7 +87,7 @@ public class CollectionMergingTests {
Iterator it = set.iterator();
it.next();
Object o = it.next();
assertThat(o).isInstanceOf(TestBean.class);
assertThat(o instanceof TestBean).isTrue();
assertThat(((TestBean) o).getName()).isEqualTo("Sally");
}
@@ -108,7 +108,7 @@ public class CollectionMergingTests {
assertThat(map).isNotNull();
assertThat(map).hasSize(2);
assertThat(map.get("Rob")).isNotNull();
assertThat(map.get("Rob")).isInstanceOf(TestBean.class);
assertThat(map.get("Rob") instanceof TestBean).isTrue();
assertThat(((TestBean) map.get("Rob")).getName()).isEqualTo("Sally");
}
@@ -127,9 +127,9 @@ public class CollectionMergingTests {
TestBean bean = (TestBean) this.beanFactory.getBean("childWithListInConstructor");
List<?> list = bean.getSomeList();
assertThat(list).as("Incorrect size").hasSize(3);
assertThat(list).element(0).isEqualTo("Rob Harrop");
assertThat(list).element(1).isEqualTo("Rod Johnson");
assertThat(list).element(2).isEqualTo("Juergen Hoeller");
assertThat(list.get(0)).isEqualTo("Rob Harrop");
assertThat(list.get(1)).isEqualTo("Rod Johnson");
assertThat(list.get(2)).isEqualTo("Juergen Hoeller");
}
@Test
@@ -138,8 +138,8 @@ public class CollectionMergingTests {
List<?> list = bean.getSomeList();
assertThat(list).isNotNull();
assertThat(list).hasSize(3);
assertThat(list).element(2).isNotNull();
assertThat(list.get(2)).isInstanceOf(TestBean.class);
assertThat(list.get(2)).isNotNull();
assertThat(list.get(2) instanceof TestBean).isTrue();
}
@Test
@@ -160,7 +160,7 @@ public class CollectionMergingTests {
Iterator it = set.iterator();
it.next();
Object o = it.next();
assertThat(o).isInstanceOf(TestBean.class);
assertThat(o instanceof TestBean).isTrue();
assertThat(((TestBean) o).getName()).isEqualTo("Sally");
}
@@ -180,7 +180,7 @@ public class CollectionMergingTests {
Map<?, ?> map = bean.getSomeMap();
assertThat(map).isNotNull();
assertThat(map).hasSize(2);
assertThat(map.get("Rob")).isInstanceOf(TestBean.class);
assertThat(map.get("Rob") instanceof TestBean).isTrue();
assertThat(((TestBean) map.get("Rob")).getName()).isEqualTo("Sally");
}
@@ -85,8 +85,8 @@ public class CollectionsWithDefaultTypesTests {
List l = (List) jumble.getJumble();
assertThat(l.get(0).equals("literal")).isTrue();
Integer[] array1 = (Integer[]) l.get(1);
assertThat(array1[0]).isEqualTo(2);
assertThat(array1[1]).isEqualTo(4);
assertThat(array1[0].equals(2)).isTrue();
assertThat(array1[1].equals(4)).isTrue();
int[] array2 = (int[]) l.get(2);
assertThat(array2[0]).isEqualTo(3);
assertThat(array2[1]).isEqualTo(5);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2022 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 @@ class EventPublicationTests {
void defaultsEventReceived() throws Exception {
List<DefaultsDefinition> defaultsList = this.eventListener.getDefaults();
assertThat(defaultsList).isNotEmpty();
assertThat(defaultsList).element(0).isInstanceOf(DocumentDefaultsDefinition.class);
assertThat(defaultsList.get(0)).isInstanceOf(DocumentDefaultsDefinition.class);
DocumentDefaultsDefinition defaults = (DocumentDefaultsDefinition) defaultsList.get(0);
assertThat(defaults.getLazyInit()).isEqualTo("true");
assertThat(defaults.getAutowire()).isEqualTo("constructor");
@@ -199,8 +199,8 @@ public class FactoryMethodTests {
assertThat(xbf.getType("externalFactoryMethodWithoutArgs")).isEqualTo(TestBean.class);
assertThat(xbf.getType("externalFactoryMethodWithArgs")).isEqualTo(TestBean.class);
String[] names = xbf.getBeanNamesForType(TestBean.class);
assertThat(Arrays.asList(names)).contains("externalFactoryMethodWithoutArgs");
assertThat(Arrays.asList(names)).contains("externalFactoryMethodWithArgs");
assertThat(Arrays.asList(names).contains("externalFactoryMethodWithoutArgs")).isTrue();
assertThat(Arrays.asList(names).contains("externalFactoryMethodWithArgs")).isTrue();
TestBean tb = (TestBean) xbf.getBean("externalFactoryMethodWithoutArgs");
assertThat(tb.getAge()).isEqualTo(2);
@@ -212,8 +212,8 @@ public class FactoryMethodTests {
assertThat(xbf.getType("externalFactoryMethodWithoutArgs")).isEqualTo(TestBean.class);
assertThat(xbf.getType("externalFactoryMethodWithArgs")).isEqualTo(TestBean.class);
names = xbf.getBeanNamesForType(TestBean.class);
assertThat(Arrays.asList(names)).contains("externalFactoryMethodWithoutArgs");
assertThat(Arrays.asList(names)).contains("externalFactoryMethodWithArgs");
assertThat(Arrays.asList(names).contains("externalFactoryMethodWithoutArgs")).isTrue();
assertThat(Arrays.asList(names).contains("externalFactoryMethodWithArgs")).isTrue();
}
@Test
@@ -337,16 +337,16 @@ public class FactoryMethodTests {
// Check that listInstance is not considered a bean of type FactoryMethods.
assertThat(List.class.isAssignableFrom(xbf.getType("listInstance"))).isTrue();
String[] names = xbf.getBeanNamesForType(FactoryMethods.class);
assertThat(Arrays.asList(names)).doesNotContain("listInstance");
assertThat(Arrays.asList(names).contains("listInstance")).isFalse();
names = xbf.getBeanNamesForType(List.class);
assertThat(Arrays.asList(names)).contains("listInstance");
assertThat(Arrays.asList(names).contains("listInstance")).isTrue();
xbf.preInstantiateSingletons();
assertThat(List.class.isAssignableFrom(xbf.getType("listInstance"))).isTrue();
names = xbf.getBeanNamesForType(FactoryMethods.class);
assertThat(Arrays.asList(names)).doesNotContain("listInstance");
assertThat(Arrays.asList(names).contains("listInstance")).isFalse();
names = xbf.getBeanNamesForType(List.class);
assertThat(Arrays.asList(names)).contains("listInstance");
assertThat(Arrays.asList(names).contains("listInstance")).isTrue();
List<?> list = (List<?>) xbf.getBean("listInstance");
assertThat(list).isEqualTo(Collections.EMPTY_LIST);
}
@@ -126,7 +126,7 @@ public class UtilNamespaceHandlerTests {
@Test
void testSimpleList() {
List<?> list = (List) this.beanFactory.getBean("simpleList");
assertThat(list).element(0).isEqualTo("Rob Harrop");
assertThat(list.get(0)).isEqualTo("Rob Harrop");
List<?> list2 = (List) this.beanFactory.getBean("simpleList");
assertThat(list).isSameAs(list2);
}
@@ -134,9 +134,9 @@ public class UtilNamespaceHandlerTests {
@Test
void testScopedList() {
List<?> list = (List) this.beanFactory.getBean("scopedList");
assertThat(list).element(0).isEqualTo("Rob Harrop");
assertThat(list.get(0)).isEqualTo("Rob Harrop");
List<?> list2 = (List) this.beanFactory.getBean("scopedList");
assertThat(list2).element(0).isEqualTo("Rob Harrop");
assertThat(list2.get(0)).isEqualTo("Rob Harrop");
assertThat(list).isNotSameAs(list2);
}
@@ -177,7 +177,7 @@ public class UtilNamespaceHandlerTests {
List<?> list = bean.getSomeList();
assertThat(list).hasSize(1);
assertThat(list).element(0).isEqualTo("foo");
assertThat(list.get(0)).isEqualTo("foo");
Set<?> set = bean.getSomeSet();
assertThat(set).hasSize(1);
@@ -208,7 +208,7 @@ public class UtilNamespaceHandlerTests {
List<?> list = bean.getSomeList();
assertThat(list).hasSize(1);
assertThat(list).element(0).isEqualTo("foo");
assertThat(list.get(0)).isEqualTo("foo");
Set<?> set = bean.getSomeSet();
assertThat(set).hasSize(1);
@@ -229,7 +229,7 @@ public class UtilNamespaceHandlerTests {
List<?> list = bean.getSomeList();
assertThat(list).hasSize(1);
assertThat(list).element(0).isEqualTo(Integer.MIN_VALUE);
assertThat(list.get(0)).isEqualTo(Integer.MIN_VALUE);
Set<?> set = bean.getSomeSet();
assertThat(set).hasSize(2);
@@ -255,7 +255,7 @@ public class UtilNamespaceHandlerTests {
List<?> list = bean.getSomeList();
assertThat(list).hasSize(1);
assertThat(list).element(0).isEqualTo(bean);
assertThat(list.get(0)).isEqualTo(bean);
Set<?> set = bean.getSomeSet();
assertThat(set).hasSize(1);
@@ -274,7 +274,7 @@ public class UtilNamespaceHandlerTests {
List<?> list = bean.getSomeList();
assertThat(Proxy.isProxyClass(list.getClass())).isTrue();
assertThat(list).hasSize(1);
assertThat(list).element(0).isEqualTo(bean);
assertThat(list.get(0)).isEqualTo(bean);
Set<?> set = bean.getSomeSet();
assertThat(Proxy.isProxyClass(set.getClass())).isFalse();
@@ -295,7 +295,7 @@ public class UtilNamespaceHandlerTests {
List<?> list = bean.getSomeList();
assertThat(Proxy.isProxyClass(list.getClass())).isFalse();
assertThat(list).hasSize(1);
assertThat(list).element(0).isEqualTo(bean);
assertThat(list.get(0)).isEqualTo(bean);
Set<?> set = bean.getSomeSet();
assertThat(Proxy.isProxyClass(set.getClass())).isTrue();
@@ -316,7 +316,7 @@ public class UtilNamespaceHandlerTests {
List<?> list = bean.getSomeList();
assertThat(Proxy.isProxyClass(list.getClass())).isFalse();
assertThat(list).hasSize(1);
assertThat(list).element(0).isEqualTo(bean);
assertThat(list.get(0)).isEqualTo(bean);
Set<?> set = bean.getSomeSet();
assertThat(Proxy.isProxyClass(set.getClass())).isFalse();
@@ -70,17 +70,17 @@ public class XmlBeanCollectionTests {
ListFactoryBean listFactory = new ListFactoryBean();
listFactory.setSourceList(new LinkedList());
listFactory.afterPropertiesSet();
assertThat(listFactory.getObject()).isInstanceOf(ArrayList.class);
assertThat(listFactory.getObject() instanceof ArrayList).isTrue();
SetFactoryBean setFactory = new SetFactoryBean();
setFactory.setSourceSet(new TreeSet());
setFactory.afterPropertiesSet();
assertThat(setFactory.getObject()).isInstanceOf(LinkedHashSet.class);
assertThat(setFactory.getObject() instanceof LinkedHashSet).isTrue();
MapFactoryBean mapFactory = new MapFactoryBean();
mapFactory.setSourceMap(new TreeMap());
mapFactory.afterPropertiesSet();
assertThat(mapFactory.getObject()).isInstanceOf(LinkedHashMap.class);
assertThat(mapFactory.getObject() instanceof LinkedHashMap).isTrue();
}
@Test
@@ -154,7 +154,7 @@ public class XmlBeanCollectionTests {
TestBean loner = (TestBean) this.beanFactory.getBean("loner");
TestBean dave = (TestBean) this.beanFactory.getBean("david");
assertThat(loner.getFriends().size()).isEqualTo(1);
assertThat(loner.getFriends()).contains(dave);
assertThat(loner.getFriends().contains(dave)).isTrue();
}
@Test
@@ -198,14 +198,14 @@ public class XmlBeanCollectionTests {
public void testMapWithLiteralsAndReferences() {
HasMap hasMap = (HasMap) this.beanFactory.getBean("mixedMap");
assertThat(hasMap.getMap().size()).isEqualTo(5);
assertThat(hasMap.getMap().get("foo")).isEqualTo(10);
assertThat(hasMap.getMap().get("foo").equals(10)).isTrue();
TestBean jenny = (TestBean) this.beanFactory.getBean("jenny");
assertThat(hasMap.getMap().get("jenny")).isSameAs(jenny);
assertThat(hasMap.getMap().get(5).equals("david")).isTrue();
assertThat(hasMap.getMap().get("bar")).isInstanceOf(Long.class);
assertThat(hasMap.getMap().get("bar")).isEqualTo(100L);
assertThat(hasMap.getMap().get("baz")).isInstanceOf(Integer.class);
assertThat(hasMap.getMap().get("baz")).isEqualTo(200);
assertThat(hasMap.getMap().get("bar") instanceof Long).isTrue();
assertThat(hasMap.getMap().get("bar").equals(100L)).isTrue();
assertThat(hasMap.getMap().get("baz") instanceof Integer).isTrue();
assertThat(hasMap.getMap().get("baz").equals(200)).isTrue();
}
@Test
@@ -230,14 +230,14 @@ public class XmlBeanCollectionTests {
assertThat(hasMap.getMap().size()).isEqualTo(4);
assertThat(hasMap.getMap().get(null).equals("bar")).isTrue();
TestBean jenny = (TestBean) this.beanFactory.getBean("jenny");
assertThat(hasMap.getMap().get("jenny")).isEqualTo(jenny);
assertThat(hasMap.getMap().get("jenny").equals(jenny)).isTrue();
// Check list
List l = (List) hasMap.getMap().get("list");
assertThat(l).isNotNull();
assertThat(l.size()).isEqualTo(4);
assertThat(l.get(0).equals("zero")).isTrue();
assertThat(l).element(3).isNull();
assertThat(l.get(3)).isNull();
// Check nested map in list
Map m = (Map) l.get(1);
@@ -250,7 +250,7 @@ public class XmlBeanCollectionTests {
l = (List) l.get(2);
assertThat(l).isNotNull();
assertThat(l.size()).isEqualTo(2);
assertThat(l.get(0)).isEqualTo(jenny);
assertThat(l.get(0).equals(jenny)).isTrue();
assertThat(l.get(1).equals("ba")).isTrue();
// Check nested map
@@ -296,8 +296,8 @@ public class XmlBeanCollectionTests {
HasMap hasMap = (HasMap) this.beanFactory.getBean("identityMap");
assertThat(hasMap.getIdentityMap().size()).isEqualTo(2);
HashSet set = new HashSet(hasMap.getIdentityMap().keySet());
assertThat(set).contains("foo");
assertThat(set).contains("jenny");
assertThat(set.contains("foo")).isTrue();
assertThat(set.contains("jenny")).isTrue();
}
@Test
@@ -364,43 +364,43 @@ public class XmlBeanCollectionTests {
@Test
public void testListFactory() {
List list = (List) this.beanFactory.getBean("listFactory");
assertThat(list).isInstanceOf(LinkedList.class);
assertThat(list instanceof LinkedList).isTrue();
assertThat(list.size()).isEqualTo(2);
assertThat(list).element(0).isEqualTo("bar");
assertThat(list).element(1).isEqualTo("jenny");
assertThat(list.get(0)).isEqualTo("bar");
assertThat(list.get(1)).isEqualTo("jenny");
}
@Test
public void testPrototypeListFactory() {
List list = (List) this.beanFactory.getBean("pListFactory");
assertThat(list).isInstanceOf(LinkedList.class);
assertThat(list instanceof LinkedList).isTrue();
assertThat(list.size()).isEqualTo(2);
assertThat(list).element(0).isEqualTo("bar");
assertThat(list).element(1).isEqualTo("jenny");
assertThat(list.get(0)).isEqualTo("bar");
assertThat(list.get(1)).isEqualTo("jenny");
}
@Test
public void testSetFactory() {
Set set = (Set) this.beanFactory.getBean("setFactory");
assertThat(set).isInstanceOf(TreeSet.class);
assertThat(set instanceof TreeSet).isTrue();
assertThat(set.size()).isEqualTo(2);
assertThat(set).contains("bar");
assertThat(set).contains("jenny");
assertThat(set.contains("bar")).isTrue();
assertThat(set.contains("jenny")).isTrue();
}
@Test
public void testPrototypeSetFactory() {
Set set = (Set) this.beanFactory.getBean("pSetFactory");
assertThat(set).isInstanceOf(TreeSet.class);
assertThat(set instanceof TreeSet).isTrue();
assertThat(set.size()).isEqualTo(2);
assertThat(set).contains("bar");
assertThat(set).contains("jenny");
assertThat(set.contains("bar")).isTrue();
assertThat(set.contains("jenny")).isTrue();
}
@Test
public void testMapFactory() {
Map map = (Map) this.beanFactory.getBean("mapFactory");
assertThat(map).isInstanceOf(TreeMap.class);
assertThat(map instanceof TreeMap).isTrue();
assertThat(map.size()).isEqualTo(2);
assertThat(map.get("foo")).isEqualTo("bar");
assertThat(map.get("jen")).isEqualTo("jenny");
@@ -409,7 +409,7 @@ public class XmlBeanCollectionTests {
@Test
public void testPrototypeMapFactory() {
Map map = (Map) this.beanFactory.getBean("pMapFactory");
assertThat(map).isInstanceOf(TreeMap.class);
assertThat(map instanceof TreeMap).isTrue();
assertThat(map.size()).isEqualTo(2);
assertThat(map.get("foo")).isEqualTo("bar");
assertThat(map.get("jen")).isEqualTo("jenny");
@@ -430,8 +430,8 @@ public class XmlBeanCollectionTests {
public void testEnumSetFactory() {
Set set = (Set) this.beanFactory.getBean("enumSetFactory");
assertThat(set.size()).isEqualTo(2);
assertThat(set).contains("ONE");
assertThat(set).contains("TWO");
assertThat(set.contains("ONE")).isTrue();
assertThat(set.contains("TWO")).isTrue();
}

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