Compare commits

..

1 Commits

Author SHA1 Message Date
Spring Builds d045d40702 Release v6.0.5 2023-02-15 16:05:32 +00:00
592 changed files with 4344 additions and 5690 deletions
+1 -1
View File
@@ -29,7 +29,7 @@ spring-test/test-output/
# Maven artifacts
pom.xml
/target/
target/
# Eclipse artifacts, including WTP generated manifests
bin
+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.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)
# <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-5.3.x/jobs/build/badge)](https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-5.3.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
View File
@@ -1,10 +1,5 @@
# Security Policy
## JAR signing
Spring Framework JARs released on Maven Central are signed.
You'll find more information about the key here: https://spring.io/GPG-KEY-spring.txt
## Supported Versions
Please see the
+5 -3
View File
@@ -78,7 +78,7 @@ configure([rootProject] + javaProjects) { project ->
}
checkstyle {
toolVersion = "10.9.1"
toolVersion = "10.7.0"
configDirectory.set(rootProject.file("src/checkstyle"))
}
@@ -127,8 +127,10 @@ configure([rootProject] + javaProjects) { project ->
"https://hc.apache.org/httpcomponents-client-5.2.x/current/httpclient5/apidocs/",
"https://projectreactor.io/docs/test/release/api/",
"https://junit.org/junit4/javadoc/4.13.2/",
// TODO Uncomment link to JUnit 5 docs once we execute Gradle with Java 18+.
// See https://github.com/spring-projects/spring-framework/issues/27497
// TODO Uncomment link to JUnit 5 docs once we have sorted out
// the following warning in the build.
//
// warning: The code being documented uses packages in the unnamed module, but the packages defined in https://junit.org/junit5/docs/5.9.2/api/ are in named modules.
//
// "https://junit.org/junit5/docs/5.9.2/api/",
"https://www.reactive-streams.org/reactive-streams-1.0.3-javadoc/",
+1 -1
View File
@@ -28,7 +28,7 @@ javadoc {
}
dependencies {
asciidoctorExtensions "io.spring.asciidoctor.backends:spring-asciidoctor-backends:0.0.5"
asciidoctorExtensions "io.spring.asciidoctor.backends:spring-asciidoctor-backends:0.0.4"
}
/**
@@ -1,9 +0,0 @@
aot=core.aot
aot-basics=core.aot.basics
aot-refresh=core.aot.refresh
aot-bean-factory-initialization-contributions=core.aot.bean-factory-initialization-contributions
aot-bean-registration-contributions=core.aot.bean-registration-contributions
aot-hints=core.aot.hints
aot-hints-import-runtime-hints=core.aot.hints.import-runtime-hints
aot-hints-reflective=core.aot.hints.reflective
aot-hints-register-reflection-for-binding=core.aot.hints.register-reflection-for-binding
@@ -1,11 +1,6 @@
// Spring Portfolio
:docs-site: https://docs.spring.io
:docs-spring-boot: {docs-site}/spring-boot/docs/current/reference
:docs-spring-gemfire: {docs-site}/spring-gemfire/docs/current/reference
:docs-spring-security: {docs-site}/spring-security/reference
// spring-asciidoctor-backends Settings
:chomp: default headers packages
:fold: all
:docs-site: https://docs.spring.io
// Spring Framework
:docs-spring-framework: {docs-site}/spring-framework/docs/{spring-version}
:api-spring-framework: {docs-spring-framework}/javadoc-api/org/springframework
@@ -13,6 +8,10 @@
:docs-kotlin: {docdir}/../../main/kotlin/org/springframework/docs
:docs-resources: {docdir}/../../main/resources
:spring-framework-main-code: https://github.com/spring-projects/spring-framework/tree/main
// Spring portfolio Links
:docs-spring-boot: {docs-site}/spring-boot/docs/current/reference
:docs-spring-gemfire: {docs-site}/spring-gemfire/docs/current/reference
:docs-spring-security: {docs-site}/spring-security/reference
// Third-party Links
:docs-graalvm: https://www.graalvm.org/22.3/reference-manual
:gh-rsocket: https://github.com/rsocket
File diff suppressed because it is too large Load Diff
@@ -16,9 +16,9 @@ Applying such optimizations early implies the following restrictions:
* The classpath is fixed and fully defined at build time.
* The beans defined in your application cannot change at runtime, meaning:
** `@Profile`, in particular profile-specific configuration needs to be chosen at build time.
** `Environment` properties that impact the presence of a bean (`@Conditional`) are only considered at build time.
* Bean definitions with instance suppliers (lambdas or method references) cannot be transformed ahead-of-time (see related https://github.com/spring-projects/spring-framework/issues/29555[spring-framework#29555] issue).
* The return type of methods annotated with `@Bean` should be the most specific type possible (typically the concrete class, not an interface) in order to support proper type inference without invoking the corresponding `@Bean` method at build time.
** Environment properties that impact the presence of a bean (`@Conditional`) are only considered at build time.
* Bean definitions with instance suppliers (lambdas or method references) can't be transformed Ahead of Time (see https://github.com/spring-projects/spring-framework/issues/29555[spring-framework#29555] related issue)
* The return type of methods annotated with `@Bean` should be the most specific one in order to allow proper hint inference (typically the concrete class, not an interface).
When these restrictions are in place, it becomes possible to perform ahead-of-time processing at build time and generate additional assets.
A Spring AOT processed application typically generates:
@@ -123,7 +123,7 @@ easy to do in Spring. You do not actually have to do anything or know anything a
the Spring internals (or even about classes such as the `FieldRetrievingFactoryBean`).
The following example enumeration shows how easy injecting an enum value is:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package jakarta.persistence;
@@ -134,7 +134,7 @@ The following example enumeration shows how easy injecting an enum value is:
EXTENDED
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
package jakarta.persistence
@@ -148,7 +148,7 @@ The following example enumeration shows how easy injecting an enum value is:
Now consider the following setter of type `PersistenceContextType` and the corresponding bean definition:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package example;
@@ -162,7 +162,7 @@ Now consider the following setter of type `PersistenceContextType` and the corre
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
package example
@@ -796,7 +796,7 @@ element results in a single `SimpleDateFormat` bean definition). Spring features
number of convenience classes that support this scenario. In the following example, we
use the `NamespaceHandlerSupport` class:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package org.springframework.samples.xml;
@@ -810,7 +810,7 @@ use the `NamespaceHandlerSupport` class:
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
package org.springframework.samples.xml
@@ -847,7 +847,7 @@ responsible for parsing one distinct top-level XML element defined in the schema
the parser, we' have access to the XML element (and thus to its subelements, too) so that
we can parse our custom XML content, as you can see in the following example:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package org.springframework.samples.xml;
@@ -884,7 +884,7 @@ the basic grunt work of creating a single `BeanDefinition`.
<2> We supply the `AbstractSingleBeanDefinitionParser` superclass with the type that our
single `BeanDefinition` represents.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
package org.springframework.samples.xml
@@ -1056,7 +1056,7 @@ setter method for the `components` property. This makes it hard (or rather impos
to configure a bean definition for the `Component` class by using setter injection.
The following listing shows the `Component` class:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package com.foo;
@@ -1087,7 +1087,7 @@ The following listing shows the `Component` class:
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
package com.foo
@@ -1114,7 +1114,7 @@ The typical solution to this issue is to create a custom `FactoryBean` that expo
setter property for the `components` property. The following listing shows such a custom
`FactoryBean`:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package com.foo;
@@ -1154,7 +1154,7 @@ setter property for the `components` property. The following listing shows such
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
package com.foo
@@ -1226,7 +1226,7 @@ listing shows:
Again following <<core.appendix.xsd-custom-introduction, the process described earlier>>,
we then create a custom `NamespaceHandler`:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package com.foo;
@@ -1240,7 +1240,7 @@ we then create a custom `NamespaceHandler`:
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
package com.foo
@@ -1259,7 +1259,7 @@ Next up is the custom `BeanDefinitionParser`. Remember that we are creating
a `BeanDefinition` that describes a `ComponentFactoryBean`. The following
listing shows our custom `BeanDefinitionParser` implementation:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package com.foo;
@@ -1308,7 +1308,7 @@ listing shows our custom `BeanDefinitionParser` implementation:
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
package com.foo
@@ -1403,14 +1403,14 @@ the named JCache for us. We can also modify the existing `BeanDefinition` for th
`'checkingAccountService'` so that it has a dependency on this new
JCache-initializing `BeanDefinition`. The following listing shows our `JCacheInitializer`:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package com.foo;
public class JCacheInitializer {
private final String name;
private String name;
public JCacheInitializer(String name) {
this.name = name;
@@ -1421,7 +1421,7 @@ JCache-initializing `BeanDefinition`. The following listing shows our `JCacheIni
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
package com.foo
@@ -1453,7 +1453,7 @@ the XSD schema that describes the custom attribute, as follows:
Next, we need to create the associated `NamespaceHandler`, as follows:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package com.foo;
@@ -1469,7 +1469,7 @@ Next, we need to create the associated `NamespaceHandler`, as follows:
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
package com.foo
@@ -1490,7 +1490,7 @@ Next, we need to create the parser. Note that, in this case, because we are goin
an XML attribute, we write a `BeanDefinitionDecorator` rather than a `BeanDefinitionParser`.
The following listing shows our `BeanDefinitionDecorator` implementation:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package com.foo;
@@ -1544,7 +1544,7 @@ The following listing shows our `BeanDefinitionDecorator` implementation:
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
package com.foo
@@ -949,7 +949,7 @@ order in which the constructor arguments are defined in a bean definition is the
in which those arguments are supplied to the appropriate constructor when the bean is
being instantiated. Consider the following class:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package x.y;
@@ -961,7 +961,7 @@ being instantiated. Consider the following class:
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
package x.y
@@ -993,7 +993,7 @@ case with the preceding example). When a simple type is used, such as
`<value>true</value>`, Spring cannot determine the type of the value, and so cannot match
by type without help. Consider the following class:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package examples;
@@ -1012,7 +1012,7 @@ by type without help. Consider the following class:
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
package examples
@@ -1077,7 +1077,7 @@ https://download.oracle.com/javase/8/docs/api/java/beans/ConstructorProperties.h
JDK annotation to explicitly name your constructor arguments. The sample class would
then have to look as follows:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package examples;
@@ -1093,7 +1093,7 @@ then have to look as follows:
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
package examples
@@ -2276,9 +2276,10 @@ and by <<beans-factory-client,making a `getBean("B")` call to the container>> as
typically new) bean B instance every time bean A needs it. The following example
shows this approach:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages",fold="none"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
// a class that uses a stateful Command-style class to perform some processing
package fiona.apple;
// Spring-API imports
@@ -2286,10 +2287,6 @@ shows this approach:
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* A class that uses a stateful Command-style class to perform
* some processing.
*/
public class CommandManager implements ApplicationContextAware {
private ApplicationContext applicationContext;
@@ -2313,17 +2310,16 @@ shows this approach:
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages",fold="none"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
// a class that uses a stateful Command-style class to perform some processing
package fiona.apple
// Spring-API imports
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationContextAware
// A class that uses a stateful Command-style class to perform
// some processing.
class CommandManager : ApplicationContextAware {
private lateinit var applicationContext: ApplicationContext
@@ -2386,7 +2382,7 @@ Spring container dynamically overrides the implementation of the `createCommand(
method. The `CommandManager` class does not have any Spring dependencies, as
the reworked example shows:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages",fold="none"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package fiona.apple;
@@ -2407,7 +2403,7 @@ the reworked example shows:
protected abstract Command createCommand();
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages",fold="none"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
package fiona.apple
@@ -4218,7 +4214,7 @@ it is created by the container and prints the resulting string to the system con
The following listing shows the custom `BeanPostProcessor` implementation class definition:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package scripting;
@@ -4238,11 +4234,9 @@ The following listing shows the custom `BeanPostProcessor` implementation class
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
package scripting
import org.springframework.beans.factory.config.BeanPostProcessor
class InstantiationTracingBeanPostProcessor : BeanPostProcessor {
@@ -1978,7 +1978,7 @@ The definition of `TemplateParserContext` follows:
This section lists the classes used in the examples throughout this chapter.
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Inventor.Java
----
package org.spring.samples.spel.inventor;
@@ -2051,20 +2051,18 @@ This section lists the classes used in the examples throughout this chapter.
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Inventor.kt
----
package org.spring.samples.spel.inventor
class Inventor(
var name: String,
var nationality: String,
var inventions: Array<String>? = null,
var birthdate: Date = GregorianCalendar().time,
var placeOfBirth: PlaceOfBirth? = null)
class Inventor(
var name: String,
var nationality: String,
var inventions: Array<String>? = null,
var birthdate: Date = GregorianCalendar().time,
var placeOfBirth: PlaceOfBirth? = null)
----
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.PlaceOfBirth.java
----
package org.spring.samples.spel.inventor;
@@ -2100,15 +2098,13 @@ This section lists the classes used in the examples throughout this chapter.
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.PlaceOfBirth.kt
----
package org.spring.samples.spel.inventor
class PlaceOfBirth(var city: String, var country: String? = null) {
----
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Society.java
----
package org.spring.samples.spel.inventor;
@@ -2151,7 +2147,7 @@ This section lists the classes used in the examples throughout this chapter.
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Society.kt
----
package org.spring.samples.spel.inventor
@@ -640,7 +640,7 @@ support for additional `PropertyEditor` instances to an `ApplicationContext`.
Consider the following example, which defines a user class called `ExoticType` and
another class called `DependsOnExoticType`, which needs `ExoticType` set as a property:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package example;
@@ -663,7 +663,7 @@ another class called `DependsOnExoticType`, which needs `ExoticType` set as a pr
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
package example
@@ -689,14 +689,12 @@ string, which a `PropertyEditor` converts into an actual
The `PropertyEditor` implementation could look similar to the following:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
// converts string representation to ExoticType object
package example;
import java.beans.PropertyEditorSupport;
// converts string representation to ExoticType object
public class ExoticTypeEditor extends PropertyEditorSupport {
public void setAsText(String text) {
@@ -704,14 +702,14 @@ The `PropertyEditor` implementation could look similar to the following:
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
// converts string representation to ExoticType object
package example
import java.beans.PropertyEditorSupport
// converts string representation to ExoticType object
class ExoticTypeEditor : PropertyEditorSupport() {
override fun setAsText(text: String) {
@@ -754,7 +752,7 @@ instances for each bean creation attempt.
The following example shows how to create your own `PropertyEditorRegistrar` implementation:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package com.foo.editors.spring;
@@ -770,7 +768,7 @@ The following example shows how to create your own `PropertyEditorRegistrar` imp
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
package com.foo.editors.spring
@@ -878,7 +876,7 @@ where type conversion is needed.
The SPI to implement type conversion logic is simple and strongly typed, as the following
interface definition shows:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes"]
----
package org.springframework.core.convert.converter;
@@ -903,7 +901,7 @@ Several converter implementations are provided in the `core.convert.support` pac
a convenience. These include converters from strings to numbers and other common types.
The following listing shows the `StringToInteger` class, which is a typical `Converter` implementation:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes"]
----
package org.springframework.core.convert.support;
@@ -924,7 +922,7 @@ When you need to centralize the conversion logic for an entire class hierarchy
(for example, when converting from `String` to `Enum` objects), you can implement
`ConverterFactory`, as the following example shows:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes"]
----
package org.springframework.core.convert.converter;
@@ -940,7 +938,7 @@ where T is a subclass of R.
Consider the `StringToEnumConverterFactory` as an example:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes"]
----
package org.springframework.core.convert.support;
@@ -977,7 +975,7 @@ context that you can use when you implement your conversion logic. Such context
type conversion be driven by a field annotation or by generic information declared on a
field signature. The following listing shows the interface definition of `GenericConverter`:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes"]
----
package org.springframework.core.convert.converter;
@@ -1041,7 +1039,7 @@ might match only if the target entity type declares a static finder method (for
`ConversionService` defines a unified API for executing type conversion logic at
runtime. Converters are often run behind the following facade interface:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes"]
----
package org.springframework.core.convert;
@@ -1225,7 +1223,7 @@ provides a unified type conversion API for both SPIs.
The `Formatter` SPI to implement field formatting logic is simple and strongly typed. The
following listing shows the `Formatter` interface definition:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes"]
----
package org.springframework.format;
@@ -1270,7 +1268,7 @@ a `java.text.DateFormat`.
The following `DateFormatter` is an example `Formatter` implementation:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package org.springframework.format.datetime;
@@ -1304,7 +1302,7 @@ The following `DateFormatter` is an example `Formatter` implementation:
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
class DateFormatter(private val pattern: String) : Formatter<Date> {
@@ -1336,7 +1334,7 @@ Field formatting can be configured by field type or annotation. To bind
an annotation to a `Formatter`, implement `AnnotationFormatterFactory`. The following
listing shows the definition of the `AnnotationFormatterFactory` interface:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes"]
----
package org.springframework.format;
@@ -1352,14 +1350,15 @@ listing shows the definition of the `AnnotationFormatterFactory` interface:
To create an implementation:
. Parameterize `A` to be the field `annotationType` with which you wish to associate
. Parameterize A to be the field `annotationType` with which you wish to associate
formatting logic -- for example `org.springframework.format.annotation.DateTimeFormat`.
. Have `getFieldTypes()` return the types of fields on which the annotation can be used.
. Have `getPrinter()` return a `Printer` to print the value of an annotated field.
. Have `getParser()` return a `Parser` to parse a `clientValue` for an annotated field.
The following example `AnnotationFormatterFactory` implementation binds the `@NumberFormat`
annotation to a formatter to let a number style or pattern be specified:
annotation to a formatter to let a number style or pattern be
specified:
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
@@ -1367,12 +1366,10 @@ annotation to a formatter to let a number style or pattern be specified:
public final class NumberFormatAnnotationFormatterFactory
implements AnnotationFormatterFactory<NumberFormat> {
private static final Set<Class<?>> FIELD_TYPES = Set.of(Short.class,
Integer.class, Long.class, Float.class, Double.class,
BigDecimal.class, BigInteger.class);
public Set<Class<?>> getFieldTypes() {
return FIELD_TYPES;
return new HashSet<Class<?>>(asList(new Class<?>[] {
Short.class, Integer.class, Long.class, Float.class,
Double.class, BigDecimal.class, BigInteger.class }));
}
public Printer<Number> getPrinter(NumberFormat annotation, Class<?> fieldType) {
@@ -1386,13 +1383,16 @@ annotation to a formatter to let a number style or pattern be specified:
private Formatter<Number> configureFormatterFrom(NumberFormat annotation, Class<?> fieldType) {
if (!annotation.pattern().isEmpty()) {
return new NumberStyleFormatter(annotation.pattern());
} else {
Style style = annotation.style();
if (style == Style.PERCENT) {
return new PercentStyleFormatter();
} else if (style == Style.CURRENCY) {
return new CurrencyStyleFormatter();
} else {
return new NumberStyleFormatter();
}
}
// else
return switch(annotation.style()) {
case Style.PERCENT -> new PercentStyleFormatter();
case Style.CURRENCY -> new CurrencyStyleFormatter();
default -> new NumberStyleFormatter();
};
}
}
----
@@ -1428,7 +1428,7 @@ annotation to a formatter to let a number style or pattern be specified:
}
----
To trigger formatting, you can annotate fields with `@NumberFormat`, as the following
To trigger formatting, you can annotate fields with @NumberFormat, as the following
example shows:
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
@@ -1490,7 +1490,7 @@ for use with Spring's `DataBinder` and the Spring Expression Language (SpEL).
The following listing shows the `FormatterRegistry` SPI:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes"]
----
package org.springframework.format;
@@ -1526,7 +1526,7 @@ these rules once, and they are applied whenever formatting is needed.
`FormatterRegistrar` is an SPI for registering formatters and converters through the
FormatterRegistry. The following listing shows its interface definition:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes"]
----
package org.springframework.format;
@@ -1578,22 +1578,20 @@ For example, the following Java configuration registers a global `yyyyMMdd` form
public FormattingConversionService conversionService() {
// Use the DefaultFormattingConversionService but do not register defaults
DefaultFormattingConversionService conversionService =
new DefaultFormattingConversionService(false);
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(false);
// Ensure @NumberFormat is still supported
conversionService.addFormatterForFieldAnnotation(
new NumberFormatAnnotationFormatterFactory());
conversionService.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory());
// Register JSR-310 date conversion with a specific global format
DateTimeFormatterRegistrar dateTimeRegistrar = new DateTimeFormatterRegistrar();
dateTimeRegistrar.setDateFormatter(DateTimeFormatter.ofPattern("yyyyMMdd"));
dateTimeRegistrar.registerFormatters(conversionService);
DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
registrar.setDateFormatter(DateTimeFormatter.ofPattern("yyyyMMdd"));
registrar.registerFormatters(conversionService);
// Register date conversion with a specific global format
DateFormatterRegistrar dateRegistrar = new DateFormatterRegistrar();
dateRegistrar.setFormatter(new DateFormatter("yyyyMMdd"));
dateRegistrar.registerFormatters(conversionService);
DateFormatterRegistrar registrar = new DateFormatterRegistrar();
registrar.setFormatter(new DateFormatter("yyyyMMdd"));
registrar.registerFormatters(conversionService);
return conversionService;
}
@@ -1614,14 +1612,14 @@ For example, the following Java configuration registers a global `yyyyMMdd` form
addFormatterForFieldAnnotation(NumberFormatAnnotationFormatterFactory())
// Register JSR-310 date conversion with a specific global format
val dateTimeRegistrar = DateTimeFormatterRegistrar()
dateTimeRegistrar.setDateFormatter(DateTimeFormatter.ofPattern("yyyyMMdd"))
dateTimeRegistrar.registerFormatters(this)
val registrar = DateTimeFormatterRegistrar()
registrar.setDateFormatter(DateTimeFormatter.ofPattern("yyyyMMdd"))
registrar.registerFormatters(this)
// Register date conversion with a specific global format
val dateRegistrar = DateFormatterRegistrar()
dateRegistrar.setFormatter(DateFormatter("yyyyMMdd"))
dateRegistrar.registerFormatters(this)
val registrar = DateFormatterRegistrar()
registrar.setFormatter(DateFormatter("yyyyMMdd"))
registrar.registerFormatters(this)
}
}
}
@@ -622,7 +622,7 @@ transactions being created and then rolled back in response to the
`UnsupportedOperationException` instance. The following listing shows the `FooService`
interface:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
// the service interface that we want to make transactional
@@ -641,7 +641,7 @@ interface:
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
// the service interface that we want to make transactional
@@ -662,7 +662,7 @@ interface:
The following example shows an implementation of the preceding interface:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package x.y.service;
@@ -690,7 +690,7 @@ The following example shows an implementation of the preceding interface:
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
package x.y.service
@@ -893,7 +893,7 @@ return type is reactive.
The following listing shows a modified version of the previously used `FooService`, but
this time the code uses reactive types:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
// the reactive service interface that we want to make transactional
@@ -912,7 +912,7 @@ this time the code uses reactive types:
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
// the reactive service interface that we want to make transactional
@@ -933,7 +933,7 @@ this time the code uses reactive types:
The following example shows an implementation of the preceding interface:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package x.y.service;
@@ -961,7 +961,7 @@ The following example shows an implementation of the preceding interface:
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
package x.y.service
@@ -2028,7 +2028,7 @@ configuration and AOP in general.
The following code shows the simple profiling aspect discussed earlier:
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
package x.y;
@@ -2065,15 +2065,9 @@ The following code shows the simple profiling aspect discussed earlier:
}
}
----
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
.Kotlin
----
package x.y
import org.aspectj.lang.ProceedingJoinPoint
import org.springframework.util.StopWatch
import org.springframework.core.Ordered
class SimpleProfiler : Ordered {
private var order: Int = 0
@@ -582,7 +582,7 @@ a similar contract to the JMS `MessageListener` interface but also gives the mes
method access to the JMS `Session` from which the `Message` was received.
The following listing shows the definition of the `SessionAwareMessageListener` interface:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes"]
----
package org.springframework.jms.listener;
@@ -31,7 +31,7 @@ The core class in Spring's JMX framework is the `MBeanExporter`. This class is
responsible for taking your Spring beans and registering them with a JMX `MBeanServer`.
For example, consider the following class:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes"]
----
package org.springframework.jmx;
@@ -358,7 +358,7 @@ an operation or an attribute.
The following example shows the annotated version of the `JmxTestBean` class that we
used in <<jmx-exporting-mbeanserver>>:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes"]
----
package org.springframework.jmx;
@@ -1067,7 +1067,7 @@ example, consider the scenario where one would like to be informed (through a
`Notification`) each and every time an attribute of a target MBean changes. The following
example writes notifications to the console:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes"]
----
package com.example;
@@ -1317,7 +1317,7 @@ published, and invoke the `sendNotification(Notification)` on the
In the following example, exported instances of the `JmxTestBean` publish a
`NotificationEvent` every time the `add(int, int)` operation is invoked:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes"]
----
package org.springframework.jmx;
@@ -9,30 +9,6 @@ Traces provide a holistic view of an entire system, crossing application boundar
Spring Framework instruments various parts of its own codebase to publish observations if an `ObservationRegistry` is configured.
You can learn more about {docs-spring-boot}/html/actuator.html#actuator.metrics[configuring the observability infrastructure in Spring Boot].
[[integration.observability.list]]
== List of produced Observations
Spring Framework instruments various features for observability.
As outlined <<integration.observability,at the beginning of this section>>, observations can generate timer Metrics and/or Traces depending on the configuration.
.Observations produced by Spring Framework
[%autowidth]
|===
|Observation name |Description
|<<integration.observability.http-client,`"http.client.requests"`>>
|Time spent for HTTP client exchanges
|<<integration.observability.http-server,`"http.server.requests"`>>
|Processing time for HTTP server exchanges at the Framework level
|===
NOTE: Observations are using Micrometer's official naming convention, but Metrics names will be automatically converted
https://micrometer.io/docs/concepts#_naming_meters[to the format preferred by the monitoring system backend]
(Prometheus, Atlas, Graphite, InfluxDB...).
[[integration.observability.concepts]]
== Micrometer Observation concepts
@@ -816,7 +816,8 @@ its properties from the job data mapped to properties of the job instance. So, i
the `ExampleJob` contains a bean property named `timeout`, and the `JobDetail`
has it applied automatically:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,java,indent=0]
[subs="verbatim"]
----
package example;
@@ -826,7 +827,7 @@ has it applied automatically:
/**
* Setter called after the ExampleJob is instantiated
* with the value from the JobDetailFactoryBean.
* with the value from the JobDetailFactoryBean (5)
*/
public void setTimeout(int timeout) {
this.timeout = timeout;
@@ -33,7 +33,7 @@ implement. Note that this interface is defined in plain Java. Dependent objects
are injected with a reference to the `Messenger` do not know that the underlying
implementation is a Groovy script. The following listing shows the `Messenger` interface:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes"]
----
package org.springframework.scripting;
@@ -45,7 +45,7 @@ implementation is a Groovy script. The following listing shows the `Messenger` i
The following example defines a class that has a dependency on the `Messenger` interface:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes"]
----
package org.springframework.scripting;
@@ -65,14 +65,15 @@ The following example defines a class that has a dependency on the `Messenger` i
The following example implements the `Messenger` interface in Groovy:
[source,groovy,indent=0,subs="verbatim,quotes",chomp="-packages",fold="none"]
[source,groovy,indent=0,subs="verbatim,quotes"]
----
package org.springframework.scripting.groovy
// from the file 'Messenger.groovy'
package org.springframework.scripting.groovy;
// Import the Messenger interface (written in Java) that is to be implemented
// import the Messenger interface (written in Java) that is to be implemented
import org.springframework.scripting.Messenger
// Define the implementation in Groovy in file 'Messenger.groovy'
// define the implementation in Groovy
class GroovyMessenger implements Messenger {
String message
@@ -275,7 +276,7 @@ surrounded by quotation marks. The following listing shows the changes that you
(the developer) should make to the `Messenger.groovy` source file when the
execution of the program is paused:
[source,groovy,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,groovy,indent=0,subs="verbatim,quotes"]
----
package org.springframework.scripting
@@ -330,13 +331,13 @@ feature works:
<lang:groovy id="messenger">
<lang:inline-script>
package org.springframework.scripting.groovy
package org.springframework.scripting.groovy;
import org.springframework.scripting.Messenger
import org.springframework.scripting.Messenger
class GroovyMessenger implements Messenger {
String message
}
class GroovyMessenger implements Messenger {
String message
}
</lang:inline-script>
<lang:property name="message" value="I Can Do The Frug" />
@@ -362,13 +363,13 @@ constructors and properties 100% clear, the following mixture of code and config
does not work:
.An approach that cannot work
[source,groovy,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,groovy,indent=0,subs="verbatim,quotes"]
----
package org.springframework.scripting.groovy
// from the file 'Messenger.groovy'
package org.springframework.scripting.groovy;
import org.springframework.scripting.Messenger
// from the file 'Messenger.groovy'
class GroovyMessenger implements Messenger {
GroovyMessenger() {}
@@ -419,7 +420,7 @@ If you have read this chapter straight from the top, you have already
<<dynamic-language-a-first-example, seen an example>> of a Groovy-dynamic-language-backed
bean. Now consider another example (again using an example from the Spring test suite):
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes"]
----
package org.springframework.scripting;
@@ -431,11 +432,11 @@ bean. Now consider another example (again using an example from the Spring test
The following example implements the `Calculator` interface in Groovy:
[source,groovy,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,groovy,indent=0,subs="verbatim,quotes"]
----
// from the file 'calculator.groovy'
package org.springframework.scripting.groovy
// from the file 'calculator.groovy'
class GroovyCalculator implements Calculator {
int add(int x, int y) {
@@ -456,7 +457,7 @@ The following bean definition uses the calculator defined in Groovy:
Finally, the following small application exercises the preceding configuration:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes"]
----
package org.springframework.scripting;
@@ -595,7 +596,7 @@ Now we can show a fully working example of using a BeanShell-based bean that imp
the `Messenger` interface that was defined earlier in this chapter. We again show the
definition of the `Messenger` interface:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes"]
----
package org.springframework.scripting;
@@ -675,8 +676,9 @@ beans, you have to enable the "`refreshable beans`" functionality. See
The following example shows an `org.springframework.web.servlet.mvc.Controller` implemented
by using the Groovy dynamic language:
[source,groovy,indent=0,subs="verbatim,quotes",chomp="-packages"]
[source,groovy,indent=0,subs="verbatim,quotes"]
----
// from the file '/WEB-INF/groovy/FortuneController.groovy'
package org.springframework.showcase.fortune.web
import org.springframework.showcase.fortune.service.FortuneService
@@ -687,7 +689,6 @@ by using the Groovy dynamic language:
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
// from the file '/WEB-INF/groovy/FortuneController.groovy'
class FortuneController implements Controller {
@Property FortuneService fortuneService
@@ -251,7 +251,7 @@ By default global configuration enables the following:
* `GET`, `HEAD`, and `POST` methods.
`allowedCredentials` is not enabled by default, since that establishes a trust level
that exposes sensitive user-specific information (such as cookies and CSRF tokens) and
that exposes sensitive user-specific information( such as cookies and CSRF tokens) and
should be used only where appropriate. When it is enabled either `allowOrigins` must be
set to one or more specific domain (but not the special value `"*"`) or alternatively
the `allowOriginPatterns` property may be used to match to a dynamic set of origins.
@@ -2504,7 +2504,7 @@ reactive type, as the following example shows:
----
Note that use of `@ModelAttribute` is optional -- for example, to set its attributes.
By default, any argument that is not a simple value type (as determined by
By default, any argument that is not a simple value type( as determined by
{api-spring-framework}/beans/BeanUtils.html#isSimpleProperty-java.lang.Class-[BeanUtils#isSimpleProperty])
and is not resolved by any other argument resolver is treated as if it were annotated
with `@ModelAttribute`.
+12 -12
View File
@@ -9,17 +9,17 @@ javaPlatform {
dependencies {
api(platform("com.fasterxml.jackson:jackson-bom:2.14.2"))
api(platform("io.micrometer:micrometer-bom:1.10.4"))
api(platform("io.netty:netty-bom:4.1.90.Final"))
api(platform("io.netty:netty-bom:4.1.89.Final"))
api(platform("io.netty:netty5-bom:5.0.0.Alpha5"))
api(platform("io.projectreactor:reactor-bom:2022.0.5"))
api(platform("io.projectreactor:reactor-bom:2022.0.3"))
api(platform("io.rsocket:rsocket-bom:1.1.3"))
api(platform("org.apache.groovy:groovy-bom:4.0.8"))
api(platform("org.apache.logging.log4j:log4j-bom:2.20.0"))
api(platform("org.eclipse.jetty:jetty-bom:11.0.14"))
api(platform("org.apache.logging.log4j:log4j-bom:2.19.0"))
api(platform("org.eclipse.jetty:jetty-bom:11.0.13"))
api(platform("org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.6.4"))
api(platform("org.jetbrains.kotlinx:kotlinx-serialization-bom:1.4.0"))
api(platform("org.junit:junit-bom:5.9.2"))
api(platform("org.mockito:mockito-bom:5.2.0"))
api(platform("org.mockito:mockito-bom:5.1.1"))
constraints {
api("com.fasterxml:aalto-xml:1.3.1")
@@ -55,9 +55,9 @@ dependencies {
api("io.r2dbc:r2dbc-spi:1.0.0.RELEASE")
api("io.reactivex.rxjava3:rxjava:3.1.5")
api("io.smallrye.reactive:mutiny:1.8.0")
api("io.undertow:undertow-core:2.3.4.Final")
api("io.undertow:undertow-servlet:2.3.4.Final")
api("io.undertow:undertow-websockets-jsr:2.3.4.Final")
api("io.undertow:undertow-core:2.3.3.Final")
api("io.undertow:undertow-servlet:2.3.3.Final")
api("io.undertow:undertow-websockets-jsr:2.3.3.Final")
api("io.vavr:vavr:0.10.4")
api("jakarta.activation:jakarta.activation-api:2.0.1")
api("jakarta.annotation:jakarta.annotation-api:2.0.0")
@@ -99,10 +99,10 @@ dependencies {
api("org.apache.httpcomponents.client5:httpclient5:5.2.1")
api("org.apache.httpcomponents.core5:httpcore5-reactive:5.2.1")
api("org.apache.poi:poi-ooxml:5.2.3")
api("org.apache.tomcat.embed:tomcat-embed-core:10.1.7")
api("org.apache.tomcat.embed:tomcat-embed-websocket:10.1.7")
api("org.apache.tomcat:tomcat-util:10.1.7")
api("org.apache.tomcat:tomcat-websocket:10.1.7")
api("org.apache.tomcat.embed:tomcat-embed-core:10.1.5")
api("org.apache.tomcat.embed:tomcat-embed-websocket:10.1.5")
api("org.apache.tomcat:tomcat-util:10.1.5")
api("org.apache.tomcat:tomcat-websocket:10.1.5")
api("org.aspectj:aspectjrt:1.9.9.1")
api("org.aspectj:aspectjtools:1.9.9.1")
api("org.aspectj:aspectjweaver:1.9.9.1")
+1 -1
View File
@@ -1,4 +1,4 @@
version=6.0.7
version=6.0.5
org.gradle.caching=true
org.gradle.jvmargs=-Xmx2048m
@@ -248,26 +248,20 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
/**
* Set by the creator of this advice object if the argument names are known.
* <p>This could be for example because they have been explicitly specified in XML
* Set by creator of this advice object if the argument names are known.
* <p>This could be for example because they have been explicitly specified in XML,
* or in an advice annotation.
* @param argumentNames comma delimited list of argument names
* @param argNames comma delimited list of arg names
*/
public void setArgumentNames(String argumentNames) {
String[] tokens = StringUtils.commaDelimitedListToStringArray(argumentNames);
public void setArgumentNames(String argNames) {
String[] tokens = StringUtils.commaDelimitedListToStringArray(argNames);
setArgumentNamesFromStringArray(tokens);
}
/**
* Set by the creator of this advice object if the argument names are known.
* <p>This could be for example because they have been explicitly specified in XML
* or in an advice annotation.
* @param argumentNames list of argument names
*/
public void setArgumentNamesFromStringArray(String... argumentNames) {
this.argumentNames = new String[argumentNames.length];
for (int i = 0; i < argumentNames.length; i++) {
this.argumentNames[i] = argumentNames[i].strip();
public void setArgumentNamesFromStringArray(String... args) {
this.argumentNames = new String[args.length];
for (int i = 0; i < args.length; i++) {
this.argumentNames[i] = args[i].strip();
if (!isVariableName(this.argumentNames[i])) {
throw new IllegalArgumentException(
"'argumentNames' property of AbstractAspectJAdvice contains an argument name '" +
@@ -38,14 +38,6 @@ import org.springframework.util.StringUtils;
* for an advice method from the pointcut expression, returning, and throwing clauses.
* If an unambiguous interpretation is not available, it returns {@code null}.
*
* <h3>Algorithm Summary</h3>
* <p>If an unambiguous binding can be deduced, then it is.
* If the advice requirements cannot possibly be satisfied, then {@code null}
* is returned. By setting the {@link #setRaiseExceptions(boolean) raiseExceptions}
* property to {@code true}, descriptive exceptions will be thrown instead of
* returning {@code null} in the case that the parameter names cannot be discovered.
*
* <h3>Algorithm Details</h3>
* <p>This class interprets arguments in the following way:
* <ol>
* <li>If the first parameter of the method is of type {@link JoinPoint}
@@ -73,15 +65,15 @@ import org.springframework.util.StringUtils;
* zero we proceed to the next stage. If {@code a} &gt; 1 then an
* {@code AmbiguousBindingException} is raised. If {@code a} == 1,
* and there are no unbound arguments of type {@code Annotation+},
* then an {@code IllegalArgumentException} is raised. If there is
* then an {@code IllegalArgumentException} is raised. if there is
* exactly one such argument, then the corresponding parameter name is
* assigned the value from the pointcut expression.</li>
* <li>If a {@code returningName} has been set, and there are no unbound arguments
* <li>If a returningName has been set, and there are no unbound arguments
* then an {@code IllegalArgumentException} is raised. If there is
* more than one unbound argument then an
* {@code AmbiguousBindingException} is raised. If there is exactly
* one unbound argument then the corresponding parameter name is assigned
* the value of the {@code returningName}.</li>
* the value &lt;returningName&gt;.</li>
* <li>If there remain unbound arguments, then the pointcut expression is
* examined once more for {@code this}, {@code target}, and
* {@code args} pointcut expressions used in the binding form (binding
@@ -107,12 +99,20 @@ import org.springframework.util.StringUtils;
* <p>The behavior on raising an {@code IllegalArgumentException} or
* {@code AmbiguousBindingException} is configurable to allow this discoverer
* to be used as part of a chain-of-responsibility. By default the condition will
* be logged and the {@link #getParameterNames(Method)} method will simply return
* be logged and the {@code getParameterNames(..)} method will simply return
* {@code null}. If the {@link #setRaiseExceptions(boolean) raiseExceptions}
* property is set to {@code true}, the conditions will be thrown as
* {@code IllegalArgumentException} and {@code AmbiguousBindingException},
* respectively.
*
* <p>Was that perfectly clear? ;)
*
* <p>Short version: If an unambiguous binding can be deduced, then it is.
* If the advice requirements cannot possibly be satisfied, then {@code null}
* is returned. By setting the {@link #setRaiseExceptions(boolean) raiseExceptions}
* property to {@code true}, descriptive exceptions will be thrown instead of
* returning {@code null} in the case that the parameter names cannot be discovered.
*
* @author Adrian Colyer
* @author Juergen Hoeller
* @since 2.0
@@ -197,7 +197,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
/**
* If {@code afterReturning} advice binds the return value, the
* {@code returning} variable name must be specified.
* returning variable name must be specified.
* @param returningName the name of the returning variable
*/
public void setReturningName(@Nullable String returningName) {
@@ -206,17 +206,18 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
/**
* If {@code afterThrowing} advice binds the thrown value, the
* {@code throwing} variable name must be specified.
* throwing variable name must be specified.
* @param throwingName the name of the throwing variable
*/
public void setThrowingName(@Nullable String throwingName) {
this.throwingName = throwingName;
}
/**
* Deduce the parameter names for an advice method.
* <p>See the {@link AspectJAdviceParameterNameDiscoverer class-level javadoc}
* for this class for details on the algorithm used.
* <p>See the {@link AspectJAdviceParameterNameDiscoverer class level javadoc}
* for this class for details of the algorithm used.
* @param method the target {@link Method}
* @return the parameter names
*/
@@ -308,7 +309,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
}
/**
* If the first parameter is of type JoinPoint or ProceedingJoinPoint, bind "thisJoinPoint" as
* If the first parameter is of type JoinPoint or ProceedingJoinPoint,bind "thisJoinPoint" as
* parameter name and return true, else return false.
*/
private boolean maybeBindThisJoinPoint() {
@@ -347,14 +348,14 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
// Second candidate we've found - ambiguous binding
throw new AmbiguousBindingException("Binding of throwing parameter '" +
this.throwingName + "' is ambiguous: could be bound to argument " +
throwableIndex + " or " + i);
throwableIndex + " or argument " + i);
}
}
}
if (throwableIndex == -1) {
throw new IllegalStateException("Binding of throwing parameter '" + this.throwingName +
"' could not be completed as no available arguments are a subtype of Throwable");
throw new IllegalStateException("Binding of throwing parameter '" + this.throwingName
+ "' could not be completed as no available arguments are a subtype of Throwable");
}
else {
bindParameterName(throwableIndex, this.throwingName);
@@ -373,7 +374,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
if (this.returningName != null) {
if (this.numberOfRemainingUnboundArguments > 1) {
throw new AmbiguousBindingException("Binding of returning parameter '" + this.returningName +
"' is ambiguous: there are " + this.numberOfRemainingUnboundArguments + " candidates.");
"' is ambiguous, there are " + this.numberOfRemainingUnboundArguments + " candidates.");
}
// We're all set... find the unbound parameter, and bind it.
@@ -386,6 +387,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
}
}
/**
* Parse the string pointcut expression looking for:
* &#64;this, &#64;target, &#64;args, &#64;within, &#64;withincode, &#64;annotation.
@@ -429,7 +431,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
int numAnnotationSlots = countNumberOfUnboundAnnotationArguments();
if (numAnnotationSlots > 1) {
throw new AmbiguousBindingException("Found " + varNames.size() +
" potential annotation variable(s) and " +
" potential annotation variable(s), and " +
numAnnotationSlots + " potential argument slots");
}
else if (numAnnotationSlots == 1) {
@@ -450,7 +452,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
}
}
/**
/*
* If the token starts meets Java identifier conventions, it's in.
*/
@Nullable
@@ -486,7 +488,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
private void maybeBindThisOrTargetOrArgsFromPointcutExpression() {
if (this.numberOfRemainingUnboundArguments > 1) {
throw new AmbiguousBindingException("Still " + this.numberOfRemainingUnboundArguments
+ " unbound args at this()/target()/args() binding stage, with no way to determine between them");
+ " unbound args at this(),target(),args() binding stage, with no way to determine between them");
}
List<String> varNames = new ArrayList<>();
@@ -518,9 +520,10 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
}
}
if (varNames.size() > 1) {
throw new AmbiguousBindingException("Found " + varNames.size() +
" candidate this(), target(), or args() variables but only one unbound argument slot");
" candidate this(), target() or args() variables but only one unbound argument slot");
}
else if (varNames.size() == 1) {
for (int j = 0; j < this.parameterNameBindings.length; j++) {
@@ -593,7 +596,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
// else varNames.size must be 0 and we have nothing to bind.
}
/**
/*
* We've found the start of a binding pointcut at the given index into the
* token array. Now we need to extract the pointcut body and return it.
*/
@@ -646,8 +649,8 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
private void maybeBindPrimitiveArgsFromPointcutExpression() {
int numUnboundPrimitives = countNumberOfUnboundPrimitiveArguments();
if (numUnboundPrimitives > 1) {
throw new AmbiguousBindingException("Found " + numUnboundPrimitives +
" unbound primitive arguments with no way to distinguish between them.");
throw new AmbiguousBindingException("Found '" + numUnboundPrimitives +
"' unbound primitive arguments with no way to distinguish between them.");
}
if (numUnboundPrimitives == 1) {
// Look for arg variable and bind it if we find exactly one...
@@ -693,7 +696,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
return false;
}
/**
/*
* Return {@code true} if the given argument type is a subclass
* of the given supertype.
*/
@@ -721,7 +724,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
return count;
}
/**
/*
* Find the argument index with the given type, and bind the given
* {@code varName} in that position.
*/
@@ -738,10 +741,22 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
/**
* Simple record to hold the extracted text from a pointcut body, together
* Simple struct to hold the extracted text from a pointcut body, together
* with the number of tokens consumed in extracting it.
*/
private record PointcutBody(int numTokensConsumed, @Nullable String text) {}
private static class PointcutBody {
private final int numTokensConsumed;
@Nullable
private final String text;
public PointcutBody(int tokens, @Nullable String text) {
this.numTokensConsumed = tokens;
this.text = text;
}
}
/**
* Thrown in response to an ambiguous binding being detected when
@@ -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.
@@ -117,7 +117,7 @@ public class TypePatternClassFilter implements ClassFilter {
}
@Override
public boolean equals(@Nullable Object obj) {
public boolean equals(Object obj) {
return (this == obj || (obj instanceof TypePatternClassFilter that &&
ObjectUtils.nullSafeEquals(this.typePattern, that.typePattern)));
}
@@ -121,21 +121,21 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
*/
@SuppressWarnings("unchecked")
@Nullable
protected static AspectJAnnotation findAspectJAnnotationOnMethod(Method method) {
for (Class<?> annotationType : ASPECTJ_ANNOTATION_CLASSES) {
AspectJAnnotation annotation = findAnnotation(method, (Class<Annotation>) annotationType);
if (annotation != null) {
return annotation;
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
@Nullable
private static AspectJAnnotation findAnnotation(Method method, Class<? extends Annotation> annotationType) {
Annotation annotation = AnnotationUtils.findAnnotation(method, annotationType);
if (annotation != null) {
return new AspectJAnnotation(annotation);
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
A result = AnnotationUtils.findAnnotation(method, toLookFor);
if (result != null) {
return new AspectJAnnotation<>(result);
}
else {
return null;
@@ -156,8 +156,9 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
/**
* Class modeling an AspectJ annotation, exposing its type enumeration and
* pointcut String.
* @param <A> the annotation type
*/
protected static class AspectJAnnotation {
protected static class AspectJAnnotation<A extends Annotation> {
private static final String[] EXPRESSION_ATTRIBUTES = {"pointcut", "value"};
@@ -170,7 +171,7 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
AfterThrowing.class, AspectJAnnotationType.AtAfterThrowing //
);
private final Annotation annotation;
private final A annotation;
private final AspectJAnnotationType annotationType;
@@ -178,11 +179,11 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
private final String argumentNames;
public AspectJAnnotation(Annotation annotation) {
public AspectJAnnotation(A annotation) {
this.annotation = annotation;
this.annotationType = determineAnnotationType(annotation);
try {
this.pointcutExpression = resolvePointcutExpression(annotation);
this.pointcutExpression = resolveExpression(annotation);
Object argNames = AnnotationUtils.getValue(annotation, "argNames");
this.argumentNames = (argNames instanceof String names ? names : "");
}
@@ -191,7 +192,7 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
}
}
private AspectJAnnotationType determineAnnotationType(Annotation annotation) {
private AspectJAnnotationType determineAnnotationType(A annotation) {
AspectJAnnotationType type = annotationTypeMap.get(annotation.annotationType());
if (type != null) {
return type;
@@ -199,21 +200,21 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
throw new IllegalStateException("Unknown annotation type: " + annotation);
}
private String resolvePointcutExpression(Annotation annotation) {
private String resolveExpression(A annotation) {
for (String attributeName : EXPRESSION_ATTRIBUTES) {
Object val = AnnotationUtils.getValue(annotation, attributeName);
if (val instanceof String str && !str.isEmpty()) {
return str;
}
}
throw new IllegalStateException("Failed to resolve pointcut expression in: " + annotation);
throw new IllegalStateException("Failed to resolve expression in: " + annotation);
}
public AspectJAnnotationType getAnnotationType() {
return this.annotationType;
}
public Annotation getAnnotation() {
public A getAnnotation() {
return this.annotation;
}
@@ -238,22 +239,19 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
*/
private static class AspectJAnnotationParameterNameDiscoverer implements ParameterNameDiscoverer {
private static final String[] EMPTY_ARRAY = new String[0];
@Override
@Nullable
public String[] getParameterNames(Method method) {
if (method.getParameterCount() == 0) {
return EMPTY_ARRAY;
return new String[0];
}
AspectJAnnotation annotation = findAspectJAnnotationOnMethod(method);
AspectJAnnotation<?> annotation = findAspectJAnnotationOnMethod(method);
if (annotation == null) {
return null;
}
StringTokenizer nameTokens = new StringTokenizer(annotation.getArgumentNames(), ",");
int numTokens = nameTokens.countTokens();
if (numTokens > 0) {
String[] names = new String[numTokens];
if (nameTokens.countTokens() > 0) {
String[] names = new String[nameTokens.countTokens()];
for (int i = 0; i < names.length; i++) {
names[i] = nameTokens.nextToken();
}
@@ -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.
@@ -35,8 +35,7 @@ import org.springframework.lang.Nullable;
/**
* Internal implementation of AspectJPointcutAdvisor.
*
* <p>Note that there will be one instance of this advisor for each target method.
* Note that there will be one instance of this advisor for each target method.
*
* @author Rod Johnson
* @author Juergen Hoeller
@@ -213,7 +212,7 @@ final class InstantiationModelAwarePointcutAdvisorImpl
* creation of the advice.
*/
private void determineAdviceType() {
AspectJAnnotation aspectJAnnotation =
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.aspectJAdviceMethod);
if (aspectJAnnotation == null) {
this.isBeforeAdvice = false;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,10 @@ import org.springframework.lang.Nullable;
* Subinterface of {@link org.springframework.aop.aspectj.AspectInstanceFactory}
* that returns {@link AspectMetadata} associated with AspectJ-annotated classes.
*
* <p>Ideally, AspectInstanceFactory would include this method itself, but because
* AspectMetadata uses Java-5-only {@link org.aspectj.lang.reflect.AjType},
* we need to split out this subinterface.
*
* @author Rod Johnson
* @since 2.0
* @see AspectMetadata
@@ -31,13 +35,13 @@ import org.springframework.lang.Nullable;
public interface MetadataAwareAspectInstanceFactory extends AspectInstanceFactory {
/**
* Get the AspectJ AspectMetadata for this factory's aspect.
* Return the AspectJ AspectMetadata for this factory's aspect.
* @return the aspect metadata
*/
AspectMetadata getAspectMetadata();
/**
* Get the best possible creation mutex for this factory.
* Return the best possible creation mutex for this factory.
* @return the mutex object (may be {@code null} for no mutex to use)
* @since 4.3
*/
@@ -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.
@@ -87,7 +87,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
new InstanceComparator<>(
Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
(Converter<Method, Annotation>) method -> {
AspectJAnnotation ann = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
AspectJAnnotation<?> ann = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
return (ann != null ? ann.getAnnotation() : null);
});
Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
@@ -216,7 +216,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
@Nullable
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
AspectJAnnotation aspectJAnnotation =
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
@@ -240,7 +240,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
AspectJAnnotation aspectJAnnotation =
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2007 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.
@@ -21,13 +21,20 @@ import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.aop.MethodMatcher;
/**
* Internal framework record, combining a {@link MethodInterceptor} instance
* with a {@link MethodMatcher} for use as an element in the advisor chain.
* Internal framework class, combining a MethodInterceptor instance
* with a MethodMatcher for use as an element in the advisor chain.
*
* @author Rod Johnson
* @author Sam Brannen
* @param interceptor the {@code MethodInterceptor}
* @param matcher the {@code MethodMatcher}
*/
record InterceptorAndDynamicMethodMatcher(MethodInterceptor interceptor, MethodMatcher matcher) {
class InterceptorAndDynamicMethodMatcher {
final MethodInterceptor interceptor;
final MethodMatcher methodMatcher;
public InterceptorAndDynamicMethodMatcher(MethodInterceptor interceptor, MethodMatcher methodMatcher) {
this.interceptor = interceptor;
this.methodMatcher = methodMatcher;
}
}
@@ -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.
@@ -169,8 +169,8 @@ public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Clonea
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.matcher().matches(this.method, targetClass, this.arguments)) {
return dm.interceptor().invoke(this);
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
@@ -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.
@@ -92,7 +92,8 @@ public class BeanFactoryAdvisorRetrievalHelper {
}
catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException bce) {
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
String bceBeanName = bce.getBeanName();
if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
if (logger.isTraceEnabled()) {
@@ -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.
@@ -58,11 +58,11 @@ public abstract class AbstractBeanFactoryBasedTargetSourceCreator
protected final Log logger = LogFactory.getLog(getClass());
@Nullable
private ConfigurableBeanFactory beanFactory;
/** Internally used DefaultListableBeanFactory instances, keyed by bean name. */
private final Map<String, DefaultListableBeanFactory> internalBeanFactories = new HashMap<>();
private final Map<String, DefaultListableBeanFactory> internalBeanFactories =
new HashMap<>();
@Override
@@ -77,7 +77,6 @@ public abstract class AbstractBeanFactoryBasedTargetSourceCreator
/**
* Return the BeanFactory that this TargetSourceCreators runs in.
*/
@Nullable
protected final BeanFactory getBeanFactory() {
return this.beanFactory;
}
@@ -1,10 +0,0 @@
/**
* Various {@link org.springframework.aop.framework.autoproxy.TargetSourceCreator}
* implementations for use with Spring's AOP auto-proxying support.
*/
@NonNullApi
@NonNullFields
package org.springframework.aop.framework.autoproxy.target;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
@@ -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.
@@ -55,8 +55,8 @@ class ScopedProxyBeanRegistrationAotProcessor implements BeanRegistrationAotProc
@Override
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
Class<?> beanClass = registeredBean.getBeanClass();
if (beanClass.equals(ScopedProxyFactoryBean.class)) {
Class<?> beanType = registeredBean.getBeanType().toClass();
if (beanType.equals(ScopedProxyFactoryBean.class)) {
String targetBeanName = getTargetBeanName(registeredBean.getMergedBeanDefinition());
BeanDefinition targetBeanDefinition =
getTargetBeanDefinition(registeredBean.getBeanFactory(), targetBeanName);
@@ -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.
@@ -19,7 +19,6 @@ package org.springframework.aop.support;
import java.io.Serializable;
import org.springframework.aop.ClassFilter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -46,7 +45,7 @@ public class RootClassFilter implements ClassFilter, Serializable {
}
@Override
public boolean equals(@Nullable Object obj) {
public boolean equals(Object obj) {
return (this == obj || (obj instanceof RootClassFilter that &&
this.clazz.equals(that.clazz)));
}
@@ -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.
@@ -183,7 +183,7 @@ public class AnnotationMatchingPointcut implements Pointcut {
}
@Override
public boolean equals(@Nullable Object obj) {
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
@@ -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.
@@ -24,7 +24,6 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.aop.TargetSource;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
/**
@@ -170,7 +169,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour
@Override
public boolean equals(@Nullable Object other) {
public boolean equals(Object other) {
if (this == other) {
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.
@@ -181,7 +181,7 @@ public class CommonsPool2TargetSource extends AbstractPoolingTargetSource implem
}
/**
* Set whether the call should block when the pool is exhausted.
* Set whether the call should bock when the pool is exhausted.
*/
public void setBlockWhenExhausted(boolean blockWhenExhausted) {
this.blockWhenExhausted = blockWhenExhausted;
@@ -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.
@@ -131,7 +131,7 @@ public final class EmptyTargetSource implements TargetSource, Serializable {
}
@Override
public boolean equals(@Nullable Object other) {
public boolean equals(Object other) {
if (this == other) {
return true;
}
@@ -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.
@@ -19,7 +19,6 @@ package org.springframework.aop.target;
import java.io.Serializable;
import org.springframework.aop.TargetSource;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -101,7 +100,7 @@ public class HotSwappableTargetSource implements TargetSource, Serializable {
* objects are equal.
*/
@Override
public boolean equals(@Nullable Object obj) {
public boolean equals(Object obj) {
return (this == obj || (obj instanceof HotSwappableTargetSource that &&
this.target.equals(that.target)));
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -65,6 +65,7 @@ public class LazyInitTargetSource extends AbstractBeanFactoryBasedTargetSource {
@Override
@Nullable
public synchronized Object getTarget() throws BeansException {
if (this.target == null) {
this.target = getBeanFactory().getBean(getTargetBeanName());
@@ -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.
@@ -19,7 +19,6 @@ package org.springframework.aop.target;
import java.io.Serializable;
import org.springframework.aop.TargetSource;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
@@ -83,7 +82,7 @@ public class SingletonTargetSource implements TargetSource, Serializable {
* targets or the targets are equal.
*/
@Override
public boolean equals(@Nullable Object other) {
public boolean equals(Object other) {
if (this == other) {
return true;
}
@@ -1,10 +0,0 @@
/**
* Support for dynamic, refreshable {@link org.springframework.aop.TargetSource}
* implementations for use with Spring AOP.
*/
@NonNullApi
@NonNullFields
package org.springframework.aop.target.dynamic;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
@@ -1,10 +0,0 @@
/**
* Various {@link org.springframework.aop.TargetSource} implementations for use
* with Spring AOP.
*/
@NonNullApi
@NonNullFields
package org.springframework.aop.target;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
@@ -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.
@@ -17,6 +17,7 @@
package org.springframework.aop.aspectj;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
@@ -42,17 +43,17 @@ class AspectJAdviceParameterNameDiscovererTests {
@Test
void noArgs() {
assertParameterNames(getMethod("noArgs"), "execution(* *(..))");
assertParameterNames(getMethod("noArgs"), "execution(* *(..))", new String[0]);
}
@Test
void joinPointOnly() {
assertParameterNames(getMethod("tjp"), "execution(* *(..))", "thisJoinPoint");
assertParameterNames(getMethod("tjp"), "execution(* *(..))", new String[] {"thisJoinPoint"});
}
@Test
void joinPointStaticPartOnly() {
assertParameterNames(getMethod("tjpsp"), "execution(* *(..))", "thisJoinPointStaticPart");
assertParameterNames(getMethod("tjpsp"), "execution(* *(..))", new String[] {"thisJoinPointStaticPart"});
}
@Test
@@ -63,18 +64,18 @@ class AspectJAdviceParameterNameDiscovererTests {
@Test
void oneThrowable() {
assertParameterNamesExtended(getMethod("oneThrowable"), "foo()", null, "ex", "ex");
assertParameterNames(getMethod("oneThrowable"), "foo()", null, "ex", new String[] {"ex"});
}
@Test
void oneJPAndOneThrowable() {
assertParameterNamesExtended(getMethod("jpAndOneThrowable"), "foo()", null, "ex", "thisJoinPoint", "ex");
assertParameterNames(getMethod("jpAndOneThrowable"), "foo()", null, "ex", new String[] {"thisJoinPoint", "ex"});
}
@Test
void oneJPAndTwoThrowables() {
assertException(getMethod("jpAndTwoThrowables"), "foo()", null, "ex", AmbiguousBindingException.class,
"Binding of throwing parameter 'ex' is ambiguous: could be bound to argument 1 or 2");
"Binding of throwing parameter 'ex' is ambiguous: could be bound to argument 1 or argument 2");
}
@Test
@@ -85,13 +86,13 @@ class AspectJAdviceParameterNameDiscovererTests {
@Test
void returning() {
assertParameterNamesExtended(getMethod("oneObject"), "foo()", "obj", null, "obj");
assertParameterNames(getMethod("oneObject"), "foo()", "obj", null, new String[] {"obj"});
}
@Test
void ambiguousReturning() {
assertException(getMethod("twoObjects"), "foo()", "obj", null, AmbiguousBindingException.class,
"Binding of returning parameter 'obj' is ambiguous: there are 2 candidates.");
"Binding of returning parameter 'obj' is ambiguous, there are 2 candidates.");
}
@Test
@@ -102,22 +103,22 @@ class AspectJAdviceParameterNameDiscovererTests {
@Test
void thisBindingOneCandidate() {
assertParameterNames(getMethod("oneObject"), "this(x)", "x");
assertParameterNames(getMethod("oneObject"), "this(x)", new String[] {"x"});
}
@Test
void thisBindingWithAlternateTokenizations() {
assertParameterNames(getMethod("oneObject"), "this( x )", "x");
assertParameterNames(getMethod("oneObject"), "this( x)", "x");
assertParameterNames(getMethod("oneObject"), "this (x )", "x");
assertParameterNames(getMethod("oneObject"), "this(x )", "x");
assertParameterNames(getMethod("oneObject"), "foo() && this(x)", "x");
assertParameterNames(getMethod("oneObject"), "this( x )", new String[] {"x"});
assertParameterNames(getMethod("oneObject"), "this( x)", new String[] {"x"});
assertParameterNames(getMethod("oneObject"), "this (x )", new String[] {"x"});
assertParameterNames(getMethod("oneObject"), "this(x )", new String[] {"x"});
assertParameterNames(getMethod("oneObject"), "foo() && this(x)", new String[] {"x"});
}
@Test
void thisBindingTwoCandidates() {
assertException(getMethod("oneObject"), "this(x) || this(y)", AmbiguousBindingException.class,
"Found 2 candidate this(), target(), or args() variables but only one unbound argument slot");
"Found 2 candidate this(), target() or args() variables but only one unbound argument slot");
}
@Test
@@ -130,22 +131,22 @@ class AspectJAdviceParameterNameDiscovererTests {
@Test
void targetBindingOneCandidate() {
assertParameterNames(getMethod("oneObject"), "target(x)", "x");
assertParameterNames(getMethod("oneObject"), "target(x)", new String[] {"x"});
}
@Test
void targetBindingWithAlternateTokenizations() {
assertParameterNames(getMethod("oneObject"), "target( x )", "x");
assertParameterNames(getMethod("oneObject"), "target( x)", "x");
assertParameterNames(getMethod("oneObject"), "target (x )", "x");
assertParameterNames(getMethod("oneObject"), "target(x )", "x");
assertParameterNames(getMethod("oneObject"), "foo() && target(x)", "x");
assertParameterNames(getMethod("oneObject"), "target( x )", new String[] {"x"});
assertParameterNames(getMethod("oneObject"), "target( x)", new String[] {"x"});
assertParameterNames(getMethod("oneObject"), "target (x )", new String[] {"x"});
assertParameterNames(getMethod("oneObject"), "target(x )", new String[] {"x"});
assertParameterNames(getMethod("oneObject"), "foo() && target(x)", new String[] {"x"});
}
@Test
void targetBindingTwoCandidates() {
assertException(getMethod("oneObject"), "target(x) || target(y)", AmbiguousBindingException.class,
"Found 2 candidate this(), target(), or args() variables but only one unbound argument slot");
"Found 2 candidate this(), target() or args() variables but only one unbound argument slot");
}
@Test
@@ -158,24 +159,24 @@ class AspectJAdviceParameterNameDiscovererTests {
@Test
void argsBindingOneObject() {
assertParameterNames(getMethod("oneObject"), "args(x)", "x");
assertParameterNames(getMethod("oneObject"), "args(x)", new String[] {"x"});
}
@Test
void argsBindingOneObjectTwoCandidates() {
assertException(getMethod("oneObject"), "args(x,y)", AmbiguousBindingException.class,
"Found 2 candidate this(), target(), or args() variables but only one unbound argument slot");
"Found 2 candidate this(), target() or args() variables but only one unbound argument slot");
}
@Test
void ambiguousArgsBinding() {
assertException(getMethod("twoObjects"), "args(x,y)", AmbiguousBindingException.class,
"Still 2 unbound args at this()/target()/args() binding stage, with no way to determine between them");
"Still 2 unbound args at this(),target(),args() binding stage, with no way to determine between them");
}
@Test
void argsOnePrimitive() {
assertParameterNames(getMethod("onePrimitive"), "args(count)", "count");
assertParameterNames(getMethod("onePrimitive"), "args(count)", new String[] {"count"});
}
@Test
@@ -187,37 +188,37 @@ class AspectJAdviceParameterNameDiscovererTests {
@Test
void thisAndPrimitive() {
assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && this(obj)",
"obj", "count");
new String[] {"obj", "count"});
}
@Test
void targetAndPrimitive() {
assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && target(obj)",
"obj", "count");
new String[] {"obj", "count"});
}
@Test
void throwingAndPrimitive() {
assertParameterNamesExtended(getMethod("oneThrowableOnePrimitive"), "args(count)", null, "ex",
"ex", "count");
assertParameterNames(getMethod("oneThrowableOnePrimitive"), "args(count)", null, "ex",
new String[] {"ex", "count"});
}
@Test
void allTogetherNow() {
assertParameterNamesExtended(getMethod("theBigOne"), "this(foo) && args(x)", null, "ex",
"thisJoinPoint", "ex", "x", "foo");
assertParameterNames(getMethod("theBigOne"), "this(foo) && args(x)", null, "ex",
new String[] {"thisJoinPoint", "ex", "x", "foo"});
}
@Test
void referenceBinding() {
assertParameterNames(getMethod("onePrimitive"),"somepc(foo)", "foo");
assertParameterNames(getMethod("onePrimitive"),"somepc(foo)", new String[] {"foo"});
}
@Test
void referenceBindingWithAlternateTokenizations() {
assertParameterNames(getMethod("onePrimitive"),"call(bar *) && somepc(foo)", "foo");
assertParameterNames(getMethod("onePrimitive"),"somepc ( foo )", "foo");
assertParameterNames(getMethod("onePrimitive"),"somepc( foo)", "foo");
assertParameterNames(getMethod("onePrimitive"),"call(bar *) && somepc(foo)", new String[] {"foo"});
assertParameterNames(getMethod("onePrimitive"),"somepc ( foo )", new String[] {"foo"});
assertParameterNames(getMethod("onePrimitive"),"somepc( foo)", new String[] {"foo"});
}
}
@@ -229,38 +230,38 @@ class AspectJAdviceParameterNameDiscovererTests {
@Test
void atThis() {
assertParameterNames(getMethod("oneAnnotation"),"@this(a)", "a");
assertParameterNames(getMethod("oneAnnotation"),"@this(a)", new String[] {"a"});
}
@Test
void atTarget() {
assertParameterNames(getMethod("oneAnnotation"),"@target(a)", "a");
assertParameterNames(getMethod("oneAnnotation"),"@target(a)", new String[] {"a"});
}
@Test
void atArgs() {
assertParameterNames(getMethod("oneAnnotation"),"@args(a)", "a");
assertParameterNames(getMethod("oneAnnotation"),"@args(a)", new String[] {"a"});
}
@Test
void atWithin() {
assertParameterNames(getMethod("oneAnnotation"),"@within(a)", "a");
assertParameterNames(getMethod("oneAnnotation"),"@within(a)", new String[] {"a"});
}
@Test
void atWithincode() {
assertParameterNames(getMethod("oneAnnotation"),"@withincode(a)", "a");
assertParameterNames(getMethod("oneAnnotation"),"@withincode(a)", new String[] {"a"});
}
@Test
void atAnnotation() {
assertParameterNames(getMethod("oneAnnotation"),"@annotation(a)", "a");
assertParameterNames(getMethod("oneAnnotation"),"@annotation(a)", new String[] {"a"});
}
@Test
void ambiguousAnnotationTwoVars() {
assertException(getMethod("twoAnnotations"),"@annotation(a) && @this(x)", AmbiguousBindingException.class,
"Found 2 potential annotation variable(s) and 2 potential argument slots");
"Found 2 potential annotation variable(s), and 2 potential argument slots");
}
@Test
@@ -271,14 +272,15 @@ class AspectJAdviceParameterNameDiscovererTests {
@Test
void annotationMedley() {
assertParameterNamesExtended(getMethod("annotationMedley"),"@annotation(a) && args(count) && this(foo)",
null, "ex", "ex", "foo", "count", "a");
assertParameterNames(getMethod("annotationMedley"),"@annotation(a) && args(count) && this(foo)",
null, "ex", new String[] {"ex", "foo", "count", "a"});
}
@Test
void annotationBinding() {
assertParameterNames(getMethod("pjpAndAnAnnotation"),
"execution(* *(..)) && @annotation(ann)", "thisJoinPoint", "ann");
"execution(* *(..)) && @annotation(ann)",
new String[] {"thisJoinPoint","ann"});
}
}
@@ -294,23 +296,33 @@ class AspectJAdviceParameterNameDiscovererTests {
throw new AssertionError("Bad test specification, no method '" + name + "' found in test class");
}
private void assertParameterNames(Method method, String pointcut, String... parameterNames) {
assertParameterNamesExtended(method, pointcut, null, null, parameterNames);
private void assertParameterNames(Method method, String pointcut, String[] parameterNames) {
assertParameterNames(method, pointcut, null, null, parameterNames);
}
private void assertParameterNamesExtended(
Method method, String pointcut, String returning, String throwing, String... parameterNames) {
private void assertParameterNames(
Method method, String pointcut, String returning, String throwing, String[] parameterNames) {
assertThat(parameterNames)
.as("bad test specification, must have same number of parameter names as method arguments")
.hasSize(method.getParameterCount());
assertThat(parameterNames.length).as("bad test specification, must have same number of parameter names as method arguments").isEqualTo(method.getParameterCount());
AspectJAdviceParameterNameDiscoverer discoverer = new AspectJAdviceParameterNameDiscoverer(pointcut);
discoverer.setRaiseExceptions(true);
discoverer.setReturningName(returning);
discoverer.setThrowingName(throwing);
String[] discoveredNames = discoverer.getParameterNames(method);
assertThat(discoverer.getParameterNames(method)).isEqualTo(parameterNames);
String formattedExpectedNames = Arrays.toString(parameterNames);
String formattedActualNames = Arrays.toString(discoveredNames);
assertThat(discoveredNames.length).as("Expecting " + parameterNames.length + " parameter names in return set '" +
formattedExpectedNames + "', but found " + discoveredNames.length +
" '" + formattedActualNames + "'").isEqualTo(parameterNames.length);
for (int i = 0; i < discoveredNames.length; i++) {
assertThat(discoveredNames[i]).as("Parameter names must never be null").isNotNull();
assertThat(discoveredNames[i]).as("Expecting parameter " + i + " to be named '" +
parameterNames[i] + "' but was '" + discoveredNames[i] + "'").isEqualTo(parameterNames[i]);
}
}
private void assertException(Method method, String pointcut, Class<? extends Throwable> exceptionType, String message) {
@@ -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.
@@ -38,55 +38,56 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
* @author Adrian Colyer
* @author Juergen Hoeller
* @author Chris Beams
* @author Sam Brannen
*/
class ArgumentBindingTests {
public class ArgumentBindingTests {
@Test
void bindingInPointcutUsedByAdvice() {
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TestBean());
public void testBindingInPointcutUsedByAdvice() {
TestBean tb = new TestBean();
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(tb);
proxyFactory.addAspect(NamedPointcutWithArgs.class);
ITestBean proxiedTestBean = proxyFactory.getProxy();
assertThatIllegalArgumentException()
.isThrownBy(() -> proxiedTestBean.setName("enigma"))
.withMessage("enigma");
assertThatIllegalArgumentException().isThrownBy(() ->
proxiedTestBean.setName("Supercalifragalisticexpialidocious"));
}
@Test
void annotationArgumentNameBinding() {
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TransactionalBean());
public void testAnnotationArgumentNameBinding() {
TransactionalBean tb = new TransactionalBean();
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(tb);
proxyFactory.addAspect(PointcutWithAnnotationArgument.class);
ITransactionalBean proxiedTestBean = proxyFactory.getProxy();
assertThatIllegalStateException()
.isThrownBy(proxiedTestBean::doInTransaction)
.withMessage("Invoked with @Transactional");
assertThatIllegalStateException().isThrownBy(
proxiedTestBean::doInTransaction);
}
@Test
void parameterNameDiscoverWithReferencePointcut() throws Exception {
public void testParameterNameDiscoverWithReferencePointcut() throws Exception {
AspectJAdviceParameterNameDiscoverer discoverer =
new AspectJAdviceParameterNameDiscoverer("somepc(formal) && set(* *)");
discoverer.setRaiseExceptions(true);
Method method = getClass().getDeclaredMethod("methodWithOneParam", String.class);
assertThat(discoverer.getParameterNames(method)).containsExactly("formal");
Method methodUsedForParameterTypeDiscovery =
getClass().getMethod("methodWithOneParam", String.class);
String[] pnames = discoverer.getParameterNames(methodUsedForParameterTypeDiscovery);
assertThat(pnames.length).as("one parameter name").isEqualTo(1);
assertThat(pnames[0]).isEqualTo("formal");
}
@SuppressWarnings("unused")
private void methodWithOneParam(String aParam) {
public void methodWithOneParam(String aParam) {
}
interface ITransactionalBean {
public interface ITransactionalBean {
@Transactional
void doInTransaction();
}
static class TransactionalBean implements ITransactionalBean {
public static class TransactionalBean implements ITransactionalBean {
@Override
@Transactional
@@ -94,35 +95,38 @@ class ArgumentBindingTests {
}
}
/**
* Mimics Spring's @Transactional annotation without actually introducing the dependency.
*/
@Retention(RetentionPolicy.RUNTIME)
@interface Transactional {
}
}
@Aspect
static class PointcutWithAnnotationArgument {
/**
* Represents Spring's Transactional annotation without actually introducing the dependency
*/
@Retention(RetentionPolicy.RUNTIME)
@interface Transactional {
}
@Around(value = "execution(* org.springframework..*.*(..)) && @annotation(transactional)")
public Object around(ProceedingJoinPoint pjp, Transactional transactional) throws Throwable {
throw new IllegalStateException("Invoked with @Transactional");
}
}
@Aspect
static class NamedPointcutWithArgs {
@Pointcut("execution(* *(..)) && args(s,..)")
public void pointcutWithArgs(String s) {}
@Around("pointcutWithArgs(aString)")
public Object doAround(ProceedingJoinPoint pjp, String aString) throws Throwable {
throw new IllegalArgumentException(aString);
}
@Aspect
class PointcutWithAnnotationArgument {
@Around(value = "execution(* org.springframework..*.*(..)) && @annotation(transaction)")
public Object around(ProceedingJoinPoint pjp, Transactional transaction) throws Throwable {
System.out.println("Invoked with transaction " + transaction);
throw new IllegalStateException();
}
}
@Aspect
class NamedPointcutWithArgs {
@Pointcut("execution(* *(..)) && args(s,..)")
public void pointcutWithArgs(String s) {}
@Around("pointcutWithArgs(aString)")
public Object doAround(ProceedingJoinPoint pjp, String aString) throws Throwable {
System.out.println("got '" + aString + "' at '" + pjp + "'");
throw new IllegalArgumentException(aString);
}
}
@@ -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.
@@ -21,8 +21,6 @@ import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.springframework.lang.Nullable;
/**
* Abstract superclass for counting advices etc.
*
@@ -61,7 +59,7 @@ public class MethodCounter implements Serializable {
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(@Nullable Object other) {
public boolean equals(Object other) {
return (other != null && other.getClass() == this.getClass());
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2016 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.
@@ -19,8 +19,6 @@ package org.springframework.aop.testfixture.interceptor;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.lang.Nullable;
/**
* Trivial interceptor that can be introduced in a chain to display it.
*
@@ -47,14 +45,14 @@ public class NopInterceptor implements MethodInterceptor {
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof NopInterceptor that)) {
public boolean equals(Object other) {
if (!(other instanceof NopInterceptor)) {
return false;
}
return this.count == that.count;
if (this == other) {
return true;
}
return this.count == ((NopInterceptor) other).count;
}
@Override
@@ -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.
@@ -17,8 +17,8 @@
package org.springframework.cache.aspectj;
/**
* Utility to trick the compiler to throw valid checked exceptions masked as
* runtime exceptions within the interceptor.
* Utility to trick the compiler to throw a valid checked
* exceptions within the interceptor.
*
* @author Stephane Nicoll
*/
@@ -36,5 +36,4 @@ final class AnyThrow {
private static <E extends Throwable> void throwAny(Throwable e) throws E {
throw (E) e;
}
}
@@ -1,9 +0,0 @@
/**
* AspectJ-based caching support.
*/
@NonNullApi
@NonNullFields
package org.springframework.cache.aspectj;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
@@ -1,11 +0,0 @@
/**
* AspectJ-based dependency injection support driven by the
* {@link org.springframework.beans.factory.annotation.Configurable @Configurable}
* annotation.
*/
@NonNullApi
@NonNullFields
package org.springframework.context.annotation.aspectj;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
@@ -1,9 +0,0 @@
/**
* AspectJ-based scheduling support.
*/
@NonNullApi
@NonNullFields
package org.springframework.scheduling.aspectj;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
@@ -1,9 +0,0 @@
/**
* AspectJ-based transaction management support.
*/
@NonNullApi
@NonNullFields
package org.springframework.transaction.aspectj;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
@@ -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.
@@ -16,7 +16,6 @@
package org.springframework.cache.config;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
/**
@@ -46,11 +45,16 @@ public class TestEntity {
}
@Override
public boolean equals(@Nullable Object obj) {
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
return (obj instanceof TestEntity that && ObjectUtils.nullSafeEquals(this.id, that.id));
if (obj == null) {
return false;
}
if (obj instanceof TestEntity) {
return ObjectUtils.nullSafeEquals(this.id, ((TestEntity) obj).id);
}
return false;
}
}
@@ -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.
@@ -29,7 +29,6 @@ import java.time.temporal.Temporal;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -247,8 +246,7 @@ public abstract class BeanUtils {
// A single public constructor
return (Constructor<T>) ctors[0];
}
else if (ctors.length == 0) {
// No public constructors -> check non-public
else if (ctors.length == 0){
ctors = clazz.getDeclaredConstructors();
if (ctors.length == 1) {
// A single non-public constructor, e.g. from a non-public record type
@@ -792,11 +790,11 @@ public abstract class BeanUtils {
actualEditable = editable;
}
PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
Set<String> ignoredProps = (ignoreProperties != null ? new HashSet<>(Arrays.asList(ignoreProperties)) : null);
List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);
for (PropertyDescriptor targetPd : targetPds) {
Method writeMethod = targetPd.getWriteMethod();
if (writeMethod != null && (ignoredProps == null || !ignoredProps.contains(targetPd.getName()))) {
if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) {
PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
if (sourcePd != null) {
Method readMethod = sourcePd.getReadMethod();
@@ -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.
@@ -88,9 +88,8 @@ abstract class PropertyDescriptorUtils {
BasicPropertyDescriptor pd = pdMap.get(propertyName);
if (pd != null) {
if (setter) {
Method writeMethod = pd.getWriteMethod();
if (writeMethod == null ||
writeMethod.getParameterTypes()[0].isAssignableFrom(method.getParameterTypes()[0])) {
if (pd.getWriteMethod() == null ||
pd.getWriteMethod().getParameterTypes()[0].isAssignableFrom(method.getParameterTypes()[0])) {
pd.setWriteMethod(method);
}
else {
@@ -98,9 +97,8 @@ abstract class PropertyDescriptorUtils {
}
}
else {
Method readMethod = pd.getReadMethod();
if (readMethod == null ||
(readMethod.getReturnType() == method.getReturnType() && method.getName().startsWith("is"))) {
if (pd.getReadMethod() == null ||
(pd.getReadMethod().getReturnType() == method.getReturnType() && method.getName().startsWith("is"))) {
pd.setReadMethod(method);
}
}
@@ -280,7 +280,6 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
}
@Override
@Nullable
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
Class<?> beanClass = registeredBean.getBeanClass();
String beanName = registeredBean.getBeanName();
@@ -324,10 +323,10 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
checkLookupMethods(beanClass, beanName);
// Pick up subclass with fresh lookup method override from above
if (this.beanFactory instanceof AbstractAutowireCapableBeanFactory aacBeanFactory) {
if (this.beanFactory instanceof AbstractAutowireCapableBeanFactory aacbf) {
RootBeanDefinition mbd = (RootBeanDefinition) this.beanFactory.getMergedBeanDefinition(beanName);
if (mbd.getFactoryMethodName() == null && mbd.hasBeanClass()) {
return aacBeanFactory.getInstantiationStrategy().getActualBeanClass(mbd, beanName, aacBeanFactory);
return aacbf.getInstantiationStrategy().getActualBeanClass(mbd, beanName, this.beanFactory);
}
}
return beanClass;
@@ -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.
@@ -157,7 +157,6 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
}
@Override
@Nullable
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
RootBeanDefinition beanDefinition = registeredBean.getMergedBeanDefinition();
beanDefinition.resolveDestroyMethodIfNecessary();
@@ -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.
@@ -20,7 +20,6 @@ import java.util.stream.Stream;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
/**
@@ -32,7 +31,7 @@ import org.springframework.util.ClassUtils;
class JakartaAnnotationsRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
if (ClassUtils.isPresent("jakarta.inject.Inject", classLoader)) {
Stream.of("jakarta.inject.Inject", "jakarta.inject.Qualifier").forEach(annotationType ->
hints.reflection().registerType(ClassUtils.resolveClassName(annotationType, classLoader)));
@@ -25,7 +25,6 @@ import java.util.Set;
import org.springframework.beans.SimpleTypeConverter;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.DependencyDescriptor;
@@ -241,11 +240,10 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
}
}
if (targetAnnotation == null) {
BeanFactory beanFactory = getBeanFactory();
// Look for matching annotation on the target class
if (beanFactory != null) {
if (getBeanFactory() != null) {
try {
Class<?> beanType = beanFactory.getType(bdHolder.getBeanName());
Class<?> beanType = getBeanFactory().getType(bdHolder.getBeanName());
if (beanType != null) {
targetAnnotation = AnnotationUtils.getAnnotation(ClassUtils.getUserClass(beanType), type);
}
@@ -138,7 +138,7 @@ class BeanDefinitionMethodGenerator {
ClassName topLevelClassName = target.topLevelClassName();
GeneratedClass generatedClass = generationContext.getGeneratedClasses()
.getOrAddForFeatureComponent("BeanDefinitions", topLevelClassName, type -> {
type.addJavadoc("Bean definitions for {@link $T}.", topLevelClassName);
type.addJavadoc("Bean definitions for {@link $T}", topLevelClassName);
type.addModifiers(Modifier.PUBLIC);
});
@@ -159,7 +159,7 @@ class BeanDefinitionMethodGenerator {
private static GeneratedClass createInnerClass(GeneratedClass generatedClass, String name, ClassName target) {
return generatedClass.getOrAdd(name, type -> {
type.addJavadoc("Bean definitions for {@link $T}.", target);
type.addJavadoc("Bean definitions for {@link $T}", target);
type.addModifiers(Modifier.PUBLIC, Modifier.STATIC);
});
}
@@ -186,7 +186,7 @@ class BeanDefinitionMethodGenerator {
this.aotContributions.forEach(aotContribution -> aotContribution.applyTo(generationContext, codeGenerator));
return generatedMethods.add("getBeanDefinition", method -> {
method.addJavadoc("Get the $L definition for '$L'.",
method.addJavadoc("Get the $L definition for '$L'",
(!this.registeredBean.isInnerBean()) ? "bean" : "inner-bean",
getName());
method.addModifiers(modifier, Modifier.STATIC);
@@ -27,9 +27,9 @@ import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.aot.hint.ExecutableMode;
import org.springframework.beans.BeanInstantiationException;
import org.springframework.beans.BeansException;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.InjectionPoint;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
@@ -97,13 +97,11 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
private BeanInstanceSupplier(ExecutableLookup lookup,
@Nullable ThrowingBiFunction<RegisteredBean, AutowiredArguments, T> generator,
@Nullable String[] shortcuts) {
this.lookup = lookup;
this.generator = generator;
this.shortcuts = shortcuts;
}
/**
* Create a {@link BeanInstanceSupplier} that resolves
* arguments for the specified bean constructor.
@@ -111,7 +109,9 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
* @param parameterTypes the constructor parameter types
* @return a new {@link BeanInstanceSupplier} instance
*/
public static <T> BeanInstanceSupplier<T> forConstructor(Class<?>... parameterTypes) {
public static <T> BeanInstanceSupplier<T> forConstructor(
Class<?>... parameterTypes) {
Assert.notNull(parameterTypes, "'parameterTypes' must not be null");
Assert.noNullElements(parameterTypes, "'parameterTypes' must not contain null elements");
return new BeanInstanceSupplier<>(new ConstructorLookup(parameterTypes), null, null);
@@ -149,11 +149,11 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
* @param generator a {@link ThrowingBiFunction} that uses the
* {@link RegisteredBean} and resolved {@link AutowiredArguments} to
* instantiate the underlying bean
* @return a new {@link BeanInstanceSupplier} instance with the specified generator
* @return a new {@link BeanInstanceSupplier} instance with the specified
* generator
*/
public BeanInstanceSupplier<T> withGenerator(
ThrowingBiFunction<RegisteredBean, AutowiredArguments, T> generator) {
Assert.notNull(generator, "'generator' must not be null");
return new BeanInstanceSupplier<>(this.lookup, generator, this.shortcuts);
}
@@ -163,9 +163,11 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
* {@code generator} function to instantiate the underlying bean.
* @param generator a {@link ThrowingFunction} that uses the
* {@link RegisteredBean} to instantiate the underlying bean
* @return a new {@link BeanInstanceSupplier} instance with the specified generator
* @return a new {@link BeanInstanceSupplier} instance with the specified
* generator
*/
public BeanInstanceSupplier<T> withGenerator(ThrowingFunction<RegisteredBean, T> generator) {
public BeanInstanceSupplier<T> withGenerator(
ThrowingFunction<RegisteredBean, T> generator) {
Assert.notNull(generator, "'generator' must not be null");
return new BeanInstanceSupplier<>(this.lookup,
(registeredBean, args) -> generator.apply(registeredBean), this.shortcuts);
@@ -174,8 +176,10 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
/**
* Return a new {@link BeanInstanceSupplier} instance that uses the specified
* {@code generator} supplier to instantiate the underlying bean.
* @param generator a {@link ThrowingSupplier} to instantiate the underlying bean
* @return a new {@link BeanInstanceSupplier} instance with the specified generator
* @param generator a {@link ThrowingSupplier} to instantiate the underlying
* bean
* @return a new {@link BeanInstanceSupplier} instance with the specified
* generator
*/
public BeanInstanceSupplier<T> withGenerator(ThrowingSupplier<T> generator) {
Assert.notNull(generator, "'generator' must not be null");
@@ -278,7 +282,8 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
if (executable instanceof Method method) {
return new MethodParameter(method, index);
}
throw new IllegalStateException("Unsupported executable: " + executable.getClass().getName());
throw new IllegalStateException(
"Unsupported executable " + executable.getClass().getName());
}
private ConstructorArgumentValues resolveArgumentValues(
@@ -298,7 +303,9 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
return resolved;
}
private ValueHolder resolveArgumentValue(BeanDefinitionValueResolver resolver, ValueHolder valueHolder) {
private ValueHolder resolveArgumentValue(BeanDefinitionValueResolver resolver,
ValueHolder valueHolder) {
if (valueHolder.isConverted()) {
return valueHolder;
}
@@ -324,7 +331,8 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
}
try {
try {
return beanFactory.resolveDependency(dependencyDescriptor, beanName, autowiredBeans, typeConverter);
return beanFactory.resolveDependency(dependencyDescriptor, beanName,
autowiredBeans, typeConverter);
}
catch (NoSuchBeanDefinitionException ex) {
if (parameterType.isArray()) {
@@ -340,45 +348,47 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
}
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(parameter), ex);
throw new UnsatisfiedDependencyException(null, beanName,
new InjectionPoint(parameter), ex);
}
}
@SuppressWarnings("unchecked")
private T instantiate(ConfigurableBeanFactory beanFactory, Executable executable, Object[] args) {
if (executable instanceof Constructor<?> constructor) {
try {
return (T) instantiate(constructor, args);
private T instantiate(ConfigurableBeanFactory beanFactory, Executable executable,
Object[] arguments) {
try {
if (executable instanceof Constructor<?> constructor) {
return (T) instantiate(constructor, arguments);
}
catch (Exception ex) {
throw new BeanInstantiationException(constructor, ex.getMessage(), ex);
if (executable instanceof Method method) {
return (T) instantiate(beanFactory, method, arguments);
}
}
if (executable instanceof Method method) {
try {
return (T) instantiate(beanFactory, method, args);
}
catch (Exception ex) {
throw new BeanInstantiationException(method, ex.getMessage(), ex);
}
catch (Exception ex) {
throw new BeanCreationException(
"Unable to instantiate bean using " + executable, ex);
}
throw new IllegalStateException("Unsupported executable " + executable.getClass().getName());
throw new IllegalStateException(
"Unsupported executable " + executable.getClass().getName());
}
private Object instantiate(Constructor<?> constructor, Object[] args) throws Exception {
private Object instantiate(Constructor<?> constructor, Object[] arguments) throws Exception {
Class<?> declaringClass = constructor.getDeclaringClass();
if (ClassUtils.isInnerClass(declaringClass)) {
Object enclosingInstance = createInstance(declaringClass.getEnclosingClass());
args = ObjectUtils.addObjectToArray(args, enclosingInstance, 0);
arguments = ObjectUtils.addObjectToArray(arguments, enclosingInstance, 0);
}
ReflectionUtils.makeAccessible(constructor);
return constructor.newInstance(args);
return constructor.newInstance(arguments);
}
private Object instantiate(ConfigurableBeanFactory beanFactory, Method method, Object[] args) throws Exception {
Object target = getFactoryMethodTarget(beanFactory, method);
private Object instantiate(ConfigurableBeanFactory beanFactory, Method method,
Object[] arguments) {
ReflectionUtils.makeAccessible(method);
return method.invoke(target, args);
Object target = getFactoryMethodTarget(beanFactory, method);
return ReflectionUtils.invokeMethod(method, target, arguments);
}
@Nullable
@@ -406,13 +416,13 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
return Arrays.stream(parameterTypes).map(Class::getName).collect(Collectors.joining(", "));
}
/**
* Performs lookup of the {@link Executable}.
*/
static abstract class ExecutableLookup {
abstract Executable get(RegisteredBean registeredBean);
}
@@ -423,10 +433,12 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
private final Class<?>[] parameterTypes;
ConstructorLookup(Class<?>[] parameterTypes) {
this.parameterTypes = parameterTypes;
}
@Override
public Executable get(RegisteredBean registeredBean) {
Class<?> beanClass = registeredBean.getBeanClass();
@@ -444,8 +456,10 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
@Override
public String toString() {
return "Constructor with parameter types [%s]".formatted(toCommaSeparatedNames(this.parameterTypes));
return "Constructor with parameter types [%s]".formatted(
toCommaSeparatedNames(this.parameterTypes));
}
}
@@ -460,19 +474,23 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
private final Class<?>[] parameterTypes;
FactoryMethodLookup(Class<?> declaringClass, String methodName, Class<?>[] parameterTypes) {
FactoryMethodLookup(Class<?> declaringClass, String methodName,
Class<?>[] parameterTypes) {
this.declaringClass = declaringClass;
this.methodName = methodName;
this.parameterTypes = parameterTypes;
}
@Override
public Executable get(RegisteredBean registeredBean) {
return get();
}
Method get() {
Method method = ReflectionUtils.findMethod(this.declaringClass, this.methodName, this.parameterTypes);
Method method = ReflectionUtils.findMethod(this.declaringClass,
this.methodName, this.parameterTypes);
Assert.notNull(method, () -> "%s cannot be found".formatted(this));
return method;
}
@@ -483,6 +501,7 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
this.methodName, toCommaSeparatedNames(this.parameterTypes),
this.declaringClass);
}
}
}
@@ -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.
@@ -130,10 +130,10 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
* {@link BeanPostProcessor BeanPostProcessors}.
* <p>Note: This is intended for creating a fresh instance, populating annotated
* fields and methods as well as applying all standard bean initialization callbacks.
* Constructor resolution is based on Kotlin primary / single public / single non-public,
* with a fallback to the default constructor in ambiguous scenarios, also influenced
* by {@link SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors}
* (e.g. for annotation-driven constructor selection).
* Constructor resolution is done via {@link #AUTOWIRE_CONSTRUCTOR}, also influenced
* by {@link SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors}.
* It does <i>not</i> imply traditional by-name or by-type autowiring of properties;
* use {@link #createBean(Class, int, boolean)} for those purposes.
* @param beanClass the class of the bean to create
* @return the new bean instance
* @throws BeansException if instantiation or wiring failed
@@ -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.
@@ -188,7 +188,7 @@ public class ConstructorArgumentValues {
* rather than matched multiple times.
* @param value the argument value
*/
public void addGenericArgumentValue(@Nullable Object value) {
public void addGenericArgumentValue(Object value) {
this.genericArgumentValues.add(new ValueHolder(value));
}
@@ -53,7 +53,6 @@ import org.springframework.beans.factory.xml.XmlReaderContext;
import org.springframework.core.io.DescriptiveResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -150,10 +149,8 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
private MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(getClass());
@Nullable
private Binding binding;
@Nullable
private GroovyBeanDefinitionWrapper currentBeanDefinition;
@@ -206,7 +203,6 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
/**
* Return a specified binding for Groovy variables, if any.
*/
@Nullable
public Binding getBinding() {
return this.binding;
}
@@ -16,9 +16,9 @@
package org.springframework.beans.factory.groovy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import groovy.lang.GroovyObjectSupport;
@@ -30,8 +30,6 @@ import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
/**
@@ -53,54 +51,58 @@ class GroovyBeanDefinitionWrapper extends GroovyObjectSupport {
private static final String DESTROY_METHOD = "destroyMethod";
private static final String SINGLETON = "singleton";
private static final Set<String> dynamicProperties = Set.of(PARENT, AUTOWIRE, CONSTRUCTOR_ARGS,
FACTORY_BEAN, FACTORY_METHOD, INIT_METHOD, DESTROY_METHOD, SINGLETON);
private static final List<String> dynamicProperties = new ArrayList<>(8);
static {
dynamicProperties.add(PARENT);
dynamicProperties.add(AUTOWIRE);
dynamicProperties.add(CONSTRUCTOR_ARGS);
dynamicProperties.add(FACTORY_BEAN);
dynamicProperties.add(FACTORY_METHOD);
dynamicProperties.add(INIT_METHOD);
dynamicProperties.add(DESTROY_METHOD);
dynamicProperties.add(SINGLETON);
}
@Nullable
private String beanName;
@Nullable
private final Class<?> clazz;
private Class<?> clazz;
@Nullable
private final Collection<?> constructorArgs;
private Collection<?> constructorArgs;
@Nullable
private AbstractBeanDefinition definition;
@Nullable
private BeanWrapper definitionWrapper;
@Nullable
private String parentName;
GroovyBeanDefinitionWrapper(String beanName) {
this(beanName, null);
public GroovyBeanDefinitionWrapper(String beanName) {
this.beanName = beanName;
}
GroovyBeanDefinitionWrapper(@Nullable String beanName, @Nullable Class<?> clazz) {
this(beanName, clazz, null);
public GroovyBeanDefinitionWrapper(String beanName, Class<?> clazz) {
this.beanName = beanName;
this.clazz = clazz;
}
GroovyBeanDefinitionWrapper(@Nullable String beanName, Class<?> clazz, @Nullable Collection<?> constructorArgs) {
public GroovyBeanDefinitionWrapper(String beanName, Class<?> clazz, Collection<?> constructorArgs) {
this.beanName = beanName;
this.clazz = clazz;
this.constructorArgs = constructorArgs;
}
@Nullable
public String getBeanName() {
return this.beanName;
}
void setBeanDefinition(AbstractBeanDefinition definition) {
public void setBeanDefinition(AbstractBeanDefinition definition) {
this.definition = definition;
}
AbstractBeanDefinition getBeanDefinition() {
public AbstractBeanDefinition getBeanDefinition() {
if (this.definition == null) {
this.definition = createBeanDefinition();
}
@@ -124,17 +126,19 @@ class GroovyBeanDefinitionWrapper extends GroovyObjectSupport {
return bd;
}
void setBeanDefinitionHolder(BeanDefinitionHolder holder) {
public void setBeanDefinitionHolder(BeanDefinitionHolder holder) {
this.definition = (AbstractBeanDefinition) holder.getBeanDefinition();
this.beanName = holder.getBeanName();
}
BeanDefinitionHolder getBeanDefinitionHolder() {
public BeanDefinitionHolder getBeanDefinitionHolder() {
return new BeanDefinitionHolder(getBeanDefinition(), getBeanName());
}
void setParent(Object obj) {
Assert.notNull(obj, "Parent bean cannot be set to a null runtime bean reference.");
public void setParent(Object obj) {
if (obj == null) {
throw new IllegalArgumentException("Parent bean cannot be set to a null runtime bean reference!");
}
if (obj instanceof String name) {
this.parentName = name;
}
@@ -148,7 +152,7 @@ class GroovyBeanDefinitionWrapper extends GroovyObjectSupport {
getBeanDefinition().setAbstract(false);
}
GroovyBeanDefinitionWrapper addProperty(String propertyName, Object propertyValue) {
public GroovyBeanDefinitionWrapper addProperty(String propertyName, Object propertyValue) {
if (propertyValue instanceof GroovyBeanDefinitionWrapper wrapper) {
propertyValue = wrapper.getBeanDefinition();
}
@@ -159,7 +163,6 @@ class GroovyBeanDefinitionWrapper extends GroovyObjectSupport {
@Override
public Object getProperty(String property) {
Assert.state(this.definitionWrapper != null, "BeanDefinition wrapper not initialized");
if (this.definitionWrapper.isReadableProperty(property)) {
return this.definitionWrapper.getPropertyValue(property);
}
@@ -176,7 +179,6 @@ class GroovyBeanDefinitionWrapper extends GroovyObjectSupport {
}
else {
AbstractBeanDefinition bd = getBeanDefinition();
Assert.state(this.definitionWrapper != null, "BeanDefinition wrapper not initialized");
if (AUTOWIRE.equals(property)) {
if ("byName".equals(newValue)) {
bd.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_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.
@@ -31,7 +31,6 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
import org.springframework.lang.Nullable;
/**
* Used by GroovyBeanDefinitionReader to read a Spring XML namespace expression
@@ -69,7 +68,6 @@ class GroovyDynamicElementReader extends GroovyObjectSupport {
@Override
@Nullable
public Object invokeMethod(String name, Object obj) {
Object[] args = (Object[]) obj;
if (name.equals("doCall")) {
@@ -90,7 +88,6 @@ class GroovyDynamicElementReader extends GroovyObjectSupport {
String myNamespace = this.rootNamespace;
Map<String, String> myNamespaces = this.xmlNamespaces;
@SuppressWarnings("serial")
Closure<Object> callable = new Closure<>(this) {
@Override
public Object call(Object... arguments) {
@@ -1,9 +1,4 @@
/**
* Support package for Groovy-based bean definitions.
*/
@NonNullApi
@NonNullFields
package org.springframework.beans.factory.groovy;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
@@ -61,6 +61,7 @@ import org.springframework.beans.factory.config.AutowiredPropertyMarker;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
@@ -314,7 +315,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
@SuppressWarnings("unchecked")
public <T> T createBean(Class<T> beanClass) throws BeansException {
// Use non-singleton bean definition, to avoid registering bean as dependent bean.
RootBeanDefinition bd = new CreateFromClassBeanDefinition(beanClass);
RootBeanDefinition bd = new RootBeanDefinition(beanClass);
bd.setAutowireMode(AUTOWIRE_CONSTRUCTOR);
bd.setScope(SCOPE_PROTOTYPE);
bd.allowCaching = ClassUtils.isCacheSafe(beanClass, getBeanClassLoader());
return (T) createBean(beanClass.getName(), bd, null);
@@ -754,15 +756,13 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
if (candidate.getTypeParameters().length > 0) {
try {
// Fully resolve parameter names and argument values.
ConstructorArgumentValues cav = mbd.getConstructorArgumentValues();
Class<?>[] paramTypes = candidate.getParameterTypes();
String[] paramNames = null;
if (cav.containsNamedArgument()) {
ParameterNameDiscoverer pnd = getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
ParameterNameDiscoverer pnd = getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
ConstructorArgumentValues cav = mbd.getConstructorArgumentValues();
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length);
Object[] args = new Object[paramTypes.length];
for (int i = 0; i < args.length; i++) {
@@ -1155,7 +1155,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName, mbd);
return obtainFromSupplier(instanceSupplier, beanName);
}
if (mbd.getFactoryMethodName() != null) {
@@ -1204,20 +1204,38 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
* @param supplier the configured supplier
* @param beanName the corresponding bean name
* @return a BeanWrapper for the new instance
* @since 5.0
* @see #getObjectForBeanInstance
*/
private BeanWrapper obtainFromSupplier(Supplier<?> supplier, String beanName, RootBeanDefinition mbd) {
protected BeanWrapper obtainFromSupplier(Supplier<?> supplier, String beanName) {
Object instance = obtainInstanceFromSupplier(supplier, beanName);
if (instance == null) {
instance = new NullBean();
}
BeanWrapper bw = new BeanWrapperImpl(instance);
initBeanWrapper(bw);
return bw;
}
@Nullable
private Object obtainInstanceFromSupplier(Supplier<?> supplier, String beanName) {
String outerBean = this.currentlyCreatedBean.get();
this.currentlyCreatedBean.set(beanName);
Object instance;
try {
instance = obtainInstanceFromSupplier(supplier, beanName, mbd);
if (supplier instanceof InstanceSupplier<?> instanceSupplier) {
return instanceSupplier.get(RegisteredBean.of((ConfigurableListableBeanFactory) this, beanName));
}
if (supplier instanceof ThrowingSupplier<?> throwableSupplier) {
return throwableSupplier.getWithException();
}
return supplier.get();
}
catch (Throwable ex) {
if (ex instanceof BeansException beansException) {
throw beansException;
}
throw new BeanCreationException(beanName, "Instantiation of supplied bean failed", ex);
throw new BeanCreationException(beanName,
"Instantiation of supplied bean failed", ex);
}
finally {
if (outerBean != null) {
@@ -1227,31 +1245,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
this.currentlyCreatedBean.remove();
}
}
if (instance == null) {
instance = new NullBean();
}
BeanWrapper bw = new BeanWrapperImpl(instance);
initBeanWrapper(bw);
return bw;
}
/**
* Obtain a bean instance from the given supplier.
* @param supplier the configured supplier
* @param beanName the corresponding bean name
* @param mbd the bean definition for the bean
* @return the bean instance (possibly {@code null})
* @since 6.0.7
*/
@Nullable
protected Object obtainInstanceFromSupplier(Supplier<?> supplier, String beanName, RootBeanDefinition mbd)
throws Exception {
if (supplier instanceof ThrowingSupplier<?> throwingSupplier) {
return throwingSupplier.getWithException();
}
return supplier.get();
}
/**
@@ -1371,17 +1364,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
}
}
if (bw.getWrappedClass().isRecord()) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to a record");
}
else {
// Skip property population phase for records since they are immutable.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
@@ -1916,36 +1898,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
}
/**
* {@link RootBeanDefinition} subclass for {@code #createBean} calls with
* flexible selection of a Kotlin primary / single public / single non-public
* constructor candidate in addition to the default constructor.
* @see BeanUtils#getResolvableConstructor(Class)
*/
@SuppressWarnings("serial")
private static class CreateFromClassBeanDefinition extends RootBeanDefinition {
public CreateFromClassBeanDefinition(Class<?> beanClass) {
super(beanClass);
}
public CreateFromClassBeanDefinition(CreateFromClassBeanDefinition original) {
super(original);
}
@Override
@Nullable
public Constructor<?>[] getPreferredConstructors() {
return ConstructorResolver.determinePreferredConstructors(getBeanClass());
}
@Override
public RootBeanDefinition cloneBeanDefinition() {
return new CreateFromClassBeanDefinition(this);
}
}
/**
* Special DependencyDescriptor variant for Spring's good old autowire="byType" mode.
* Always optional; never considering the parameter name for choosing a primary candidate.
@@ -1958,7 +1910,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
}
@Override
@Nullable
public String getDependencyName() {
return null;
}
@@ -1979,7 +1930,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
}
@Override
public void doWith(Method method) throws IllegalArgumentException {
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
if (isFactoryBeanMethod(method)) {
ResolvableType returnType = ResolvableType.forMethodReturnType(method);
ResolvableType candidate = returnType.as(FactoryBean.class).getGeneric();
@@ -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.
@@ -853,12 +853,10 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
*/
@Override
public ConstructorArgumentValues getConstructorArgumentValues() {
ConstructorArgumentValues cav = this.constructorArgumentValues;
if (cav == null) {
cav = new ConstructorArgumentValues();
this.constructorArgumentValues = cav;
if (this.constructorArgumentValues == null) {
this.constructorArgumentValues = new ConstructorArgumentValues();
}
return cav;
return this.constructorArgumentValues;
}
/**
@@ -881,12 +879,10 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
*/
@Override
public MutablePropertyValues getPropertyValues() {
MutablePropertyValues pvs = this.propertyValues;
if (pvs == null) {
pvs = new MutablePropertyValues();
this.propertyValues = pvs;
if (this.propertyValues == null) {
this.propertyValues = new MutablePropertyValues();
}
return pvs;
return this.propertyValues;
}
/**
@@ -1222,54 +1222,6 @@ class ConstructorResolver {
return old;
}
/**
* See {@link BeanUtils#getResolvableConstructor(Class)} for alignment.
* This variant adds a lenient fallback to the default constructor if available, similar to
* {@link org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors}.
*/
@Nullable
static Constructor<?>[] determinePreferredConstructors(Class<?> clazz) {
Constructor<?> primaryCtor = BeanUtils.findPrimaryConstructor(clazz);
Constructor<?> defaultCtor;
try {
defaultCtor = clazz.getDeclaredConstructor();
}
catch (NoSuchMethodException ex) {
defaultCtor = null;
}
if (primaryCtor != null) {
if (defaultCtor != null && !primaryCtor.equals(defaultCtor)) {
return new Constructor<?>[] {primaryCtor, defaultCtor};
}
else {
return new Constructor<?>[] {primaryCtor};
}
}
Constructor<?>[] ctors = clazz.getConstructors();
if (ctors.length == 1) {
// A single public constructor, potentially in combination with a non-public default constructor
if (defaultCtor != null && !ctors[0].equals(defaultCtor)) {
return new Constructor<?>[] {ctors[0], defaultCtor};
}
else {
return ctors;
}
}
else if (ctors.length == 0) {
// No public constructors -> check non-public
ctors = clazz.getDeclaredConstructors();
if (ctors.length == 1) {
// A single non-public constructor, e.g. from a non-public record type
return ctors;
}
}
return null;
}
/**
* Private inner class for holding argument combinations.
@@ -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.
@@ -40,7 +40,6 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;
import jakarta.inject.Provider;
@@ -938,17 +937,6 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
return (this.configurationFrozen || super.isBeanEligibleForMetadataCaching(beanName));
}
@Override
@Nullable
protected Object obtainInstanceFromSupplier(Supplier<?> supplier, String beanName, RootBeanDefinition mbd)
throws Exception {
if (supplier instanceof InstanceSupplier<?> instanceSupplier) {
return instanceSupplier.get(RegisteredBean.of(this, beanName, mbd));
}
return super.obtainInstanceFromSupplier(supplier, beanName, mbd);
}
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
@@ -1732,7 +1720,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (beanInstance != null) {
Integer candidatePriority = getPriority(beanInstance);
if (candidatePriority != null) {
if (highestPriority != null) {
if (highestPriorityBeanName != null) {
if (candidatePriority.equals(highestPriority)) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"Multiple beans found with the same priority ('" + highestPriority +
@@ -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.
@@ -340,7 +340,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
* (within the entire factory).
* @param beanName the name of the bean
*/
public boolean isSingletonCurrentlyInCreation(@Nullable String beanName) {
public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
@@ -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.
@@ -35,7 +35,6 @@ import org.springframework.util.function.ThrowingSupplier;
* @since 6.0
* @param <T> the type of instance supplied by this supplier
* @see RegisteredBean
* @see org.springframework.beans.factory.aot.BeanInstanceSupplier
*/
@FunctionalInterface
public interface InstanceSupplier<T> extends ThrowingSupplier<T> {
@@ -75,17 +74,19 @@ public interface InstanceSupplier<T> extends ThrowingSupplier<T> {
*/
default <V> InstanceSupplier<V> andThen(
ThrowingBiFunction<RegisteredBean, ? super T, ? extends V> after) {
Assert.notNull(after, "'after' function must not be null");
return new InstanceSupplier<>() {
@Override
public V get(RegisteredBean registeredBean) throws Exception {
return after.applyWithException(registeredBean, InstanceSupplier.this.get(registeredBean));
}
@Override
public Method getFactoryMethod() {
return InstanceSupplier.this.getFactoryMethod();
}
};
}
@@ -114,21 +115,22 @@ public interface InstanceSupplier<T> extends ThrowingSupplier<T> {
*/
static <T> InstanceSupplier<T> using(@Nullable Method factoryMethod, ThrowingSupplier<T> supplier) {
Assert.notNull(supplier, "Supplier must not be null");
if (supplier instanceof InstanceSupplier<T> instanceSupplier &&
instanceSupplier.getFactoryMethod() == factoryMethod) {
if (supplier instanceof InstanceSupplier<T> instanceSupplier
&& instanceSupplier.getFactoryMethod() == factoryMethod) {
return instanceSupplier;
}
return new InstanceSupplier<>() {
@Override
public T get(RegisteredBean registeredBean) throws Exception {
return supplier.getWithException();
}
@Override
public Method getFactoryMethod() {
return factoryMethod;
}
};
}
@@ -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.
@@ -80,18 +80,6 @@ public final class RegisteredBean {
null);
}
/**
* Create a new {@link RegisteredBean} instance for a regular bean.
* @param beanFactory the source bean factory
* @param beanName the bean name
* @param mbd the pre-determined merged bean definition
* @return a new {@link RegisteredBean} instance
* @since 6.0.7
*/
static RegisteredBean of(ConfigurableListableBeanFactory beanFactory, String beanName, RootBeanDefinition mbd) {
return new RegisteredBean(beanFactory, () -> beanName, false, () -> mbd, null);
}
/**
* Create a new {@link RegisteredBean} instance for an inner-bean.
* @param parent the parent of the inner-bean
@@ -232,34 +220,45 @@ public final class RegisteredBean {
@Nullable
private volatile String resolvedBeanName;
InnerBeanResolver(RegisteredBean parent, @Nullable String innerBeanName, BeanDefinition innerBeanDefinition) {
Assert.isInstanceOf(AbstractAutowireCapableBeanFactory.class, parent.getBeanFactory());
InnerBeanResolver(RegisteredBean parent, @Nullable String innerBeanName,
BeanDefinition innerBeanDefinition) {
Assert.isInstanceOf(AbstractAutowireCapableBeanFactory.class,
parent.getBeanFactory());
this.parent = parent;
this.innerBeanName = innerBeanName;
this.innerBeanDefinition = innerBeanDefinition;
}
String resolveBeanName() {
String resolvedBeanName = this.resolvedBeanName;
if (resolvedBeanName != null) {
return resolvedBeanName;
}
resolvedBeanName = resolveInnerBean((beanName, mergedBeanDefinition) -> beanName);
resolvedBeanName = resolveInnerBean(
(beanName, mergedBeanDefinition) -> beanName);
this.resolvedBeanName = resolvedBeanName;
return resolvedBeanName;
}
RootBeanDefinition resolveMergedBeanDefinition() {
return resolveInnerBean((beanName, mergedBeanDefinition) -> mergedBeanDefinition);
return resolveInnerBean(
(beanName, mergedBeanDefinition) -> mergedBeanDefinition);
}
private <T> T resolveInnerBean(BiFunction<String, RootBeanDefinition, T> resolver) {
private <T> T resolveInnerBean(
BiFunction<String, RootBeanDefinition, T> resolver) {
// Always use a fresh BeanDefinitionValueResolver in case the parent merged bean definition has changed.
BeanDefinitionValueResolver beanDefinitionValueResolver = new BeanDefinitionValueResolver(
(AbstractAutowireCapableBeanFactory) this.parent.getBeanFactory(),
this.parent.getBeanName(), this.parent.getMergedBeanDefinition());
return beanDefinitionValueResolver.resolveInnerBean(this.innerBeanName, this.innerBeanDefinition, resolver);
return beanDefinitionValueResolver.resolveInnerBean(this.innerBeanName,
this.innerBeanDefinition, resolver);
}
}
}
@@ -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.
@@ -163,8 +163,8 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
catch (InvocationTargetException ex) {
String msg = "Factory method '" + factoryMethod.getName() + "' threw exception with message: " +
ex.getTargetException().getMessage();
if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory cbf &&
cbf.isCurrentlyInCreation(bd.getFactoryBeanName())) {
if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory &&
((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {
msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider " +
"declaring the factory method as static for independence from its containing instance. " + msg;
}
@@ -127,9 +127,9 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
throw new BeanIsNotAFactoryException(beanName, bean.getClass());
}
if (bean instanceof FactoryBean<?> factoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
if (bean instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
try {
Object exposedObject = factoryBean.getObject();
Object exposedObject = ((FactoryBean<?>) bean).getObject();
if (exposedObject == null) {
throw new BeanCreationException(beanName, "FactoryBean exposed null object");
}
@@ -205,8 +205,8 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
Object bean = getBean(name);
// In case of FactoryBean, return singleton status of created object.
if (bean instanceof FactoryBean<?> factoryBean) {
return factoryBean.isSingleton();
if (bean instanceof FactoryBean) {
return ((FactoryBean<?>) bean).isSingleton();
}
return true;
}
@@ -215,8 +215,8 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
Object bean = getBean(name);
// In case of FactoryBean, return prototype status of created object.
return ((bean instanceof SmartFactoryBean<?> smartFactoryBean && smartFactoryBean.isPrototype()) ||
(bean instanceof FactoryBean<?> factoryBean && !factoryBean.isSingleton()));
return ((bean instanceof SmartFactoryBean && ((SmartFactoryBean<?>) bean).isPrototype()) ||
(bean instanceof FactoryBean && !((FactoryBean<?>) bean).isSingleton()));
}
@Override
@@ -246,9 +246,9 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
"Defined beans are [" + StringUtils.collectionToCommaDelimitedString(this.beans.keySet()) + "]");
}
if (bean instanceof FactoryBean<?> factoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
if (bean instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
// If it's a FactoryBean, we want to look at what it creates, not the factory class.
return factoryBean.getObjectType();
return ((FactoryBean<?>) bean).getObjectType();
}
return bean.getClass();
}
@@ -408,10 +408,10 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
String beanName = entry.getKey();
Object beanInstance = entry.getValue();
// Is bean a FactoryBean?
if (beanInstance instanceof FactoryBean<?> factoryBean && !isFactoryType) {
if (beanInstance instanceof FactoryBean<?> factory && !isFactoryType) {
// Match object created by FactoryBean.
Class<?> objectType = factoryBean.getObjectType();
if ((includeNonSingletons || factoryBean.isSingleton()) &&
Class<?> objectType = factory.getObjectType();
if ((includeNonSingletons || factory.isSingleton()) &&
objectType != null && (type == null || type.isAssignableFrom(objectType))) {
matches.put(beanName, getBean(beanName, type));
}
@@ -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.
@@ -547,8 +547,7 @@ public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
* @see DefaultNamespaceHandlerResolver#DefaultNamespaceHandlerResolver(ClassLoader)
*/
protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
ResourceLoader resourceLoader = getResourceLoader();
ClassLoader cl = (resourceLoader != null ? resourceLoader.getClassLoader() : getBeanClassLoader());
ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader());
return new DefaultNamespaceHandlerResolver(cl);
}
@@ -111,7 +111,6 @@ public class ArgumentConvertingMethodInvoker extends MethodInvoker {
* @see #doFindMatchingMethod
*/
@Override
@Nullable
protected Method findMatchingMethod() {
Method matchingMethod = super.findMatchingMethod();
// Second pass: look for method where arguments can be converted to parameter types.
@@ -18,9 +18,7 @@ package org.springframework.beans.factory;
import java.io.Closeable;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.text.NumberFormat;
import java.text.ParseException;
@@ -76,9 +74,7 @@ import org.springframework.beans.testfixture.beans.NestedTestBean;
import org.springframework.beans.testfixture.beans.SideEffectBean;
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.ParameterNameDiscoverer;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.convert.support.DefaultConversionService;
@@ -115,21 +111,7 @@ import static org.mockito.Mockito.verify;
*/
class DefaultListableBeanFactoryTests {
private final DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
{
// No parameter name discovery expected unless named arguments are used
lbf.setParameterNameDiscoverer(new ParameterNameDiscoverer() {
@Override
public String[] getParameterNames(Method method) {
throw new UnsupportedOperationException();
}
@Override
public String[] getParameterNames(Constructor<?> ctor) {
throw new UnsupportedOperationException();
}
});
}
private DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
@Test
@@ -449,6 +431,7 @@ class DefaultListableBeanFactoryTests {
@Test
void empty() {
ListableBeanFactory lbf = new DefaultListableBeanFactory();
assertThat(lbf.getBeanDefinitionNames() != null).as("No beans defined --> array != null").isTrue();
assertThat(lbf.getBeanDefinitionNames().length == 0).as("No beans defined after no arg constructor").isTrue();
assertThat(lbf.getBeanDefinitionCount() == 0).as("No beans defined after no arg constructor").isTrue();
@@ -458,7 +441,6 @@ class DefaultListableBeanFactoryTests {
void emptyPropertiesPopulation() {
Properties p = new Properties();
registerBeanDefinitions(p);
assertThat(lbf.getBeanDefinitionCount() == 0).as("No beans defined after ignorable invalid").isTrue();
}
@@ -468,7 +450,6 @@ class DefaultListableBeanFactoryTests {
p.setProperty("foo", "bar");
p.setProperty("qwert", "er");
registerBeanDefinitions(p, "test");
assertThat(lbf.getBeanDefinitionCount() == 0).as("No beans defined after harmless ignorable rubbish").isTrue();
}
@@ -479,9 +460,8 @@ class DefaultListableBeanFactoryTests {
p.setProperty("test.name", "Tony");
p.setProperty("test.age", "48");
int count = registerBeanDefinitions(p);
assertThat(count == 1).as("1 beans registered, not " + count).isTrue();
testPropertiesPopulation(lbf);
singleTestBean(lbf);
}
@Test
@@ -492,22 +472,8 @@ class DefaultListableBeanFactoryTests {
p.setProperty(PREFIX + "test.name", "Tony");
p.setProperty(PREFIX + "test.age", "0x30");
int count = registerBeanDefinitions(p, PREFIX);
assertThat(count == 1).as("1 beans registered, not " + count).isTrue();
testPropertiesPopulation(lbf);
}
private void testPropertiesPopulation(ListableBeanFactory lbf) {
assertThat(lbf.getBeanDefinitionCount() == 1).as("1 beans defined").isTrue();
String[] names = lbf.getBeanDefinitionNames();
assertThat(names != lbf.getBeanDefinitionNames()).isTrue();
assertThat(names.length == 1).as("Array length == 1").isTrue();
assertThat(names[0].equals("test")).as("0th element == test").isTrue();
TestBean tb = (TestBean) lbf.getBean("test");
assertThat(tb != null).as("Test is non null").isTrue();
assertThat("Tony".equals(tb.getName())).as("Test bean name is Tony").isTrue();
assertThat(tb.getAge() == 48).as("Test bean age is 48").isTrue();
singleTestBean(lbf);
}
@Test
@@ -559,7 +525,6 @@ class DefaultListableBeanFactoryTests {
p.setProperty(PREFIX + "kerry.spouse(ref)", "rod");
registerBeanDefinitions(p, PREFIX);
assertThatExceptionOfType(BeansException.class).as("unresolved reference").isThrownBy(() ->
lbf.getBean("kerry"));
}
@@ -685,6 +650,7 @@ class DefaultListableBeanFactoryTests {
assertThat(kerry1 != null).as("Non null").isTrue();
assertThat(kerry1 == kerry2).as("Singletons equal").isTrue();
lbf = new DefaultListableBeanFactory();
p = new Properties();
p.setProperty("kerry.(class)", TestBean.class.getName());
p.setProperty("kerry.(scope)", BeanDefinition.SCOPE_PROTOTYPE);
@@ -695,6 +661,7 @@ class DefaultListableBeanFactoryTests {
assertThat(kerry1 != null).as("Non null").isTrue();
assertThat(kerry1 != kerry2).as("Prototypes NOT equal").isTrue();
lbf = new DefaultListableBeanFactory();
p = new Properties();
p.setProperty("kerry.(class)", TestBean.class.getName());
p.setProperty("kerry.(scope)", "singleton");
@@ -717,8 +684,8 @@ class DefaultListableBeanFactoryTests {
p.setProperty("rod.(singleton)", "false");
p.setProperty("rod.age", "34");
p.setProperty("rod.spouse", "*kerry");
registerBeanDefinitions(p);
registerBeanDefinitions(p);
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() ->
lbf.getBean("kerry"))
.satisfies(ex -> assertThat(ex.contains(BeanCurrentlyInCreationException.class)).isTrue());
@@ -739,6 +706,7 @@ class DefaultListableBeanFactoryTests {
assertThat(kerry1).as("Non null").isNotNull();
assertThat(kerry1 == kerry2).as("Singletons equal").isTrue();
lbf = new DefaultListableBeanFactory();
p = new Properties();
p.setProperty("wife.(class)", TestBean.class.getName());
p.setProperty("wife.name", "kerry");
@@ -753,6 +721,7 @@ class DefaultListableBeanFactoryTests {
assertThat(kerry1 != null).as("Non null").isTrue();
assertThat(kerry1 != kerry2).as("Prototypes NOT equal").isTrue();
lbf = new DefaultListableBeanFactory();
p = new Properties();
p.setProperty("kerry.(class)", TestBean.class.getName());
p.setProperty("kerry.(singleton)", "true");
@@ -827,17 +796,41 @@ class DefaultListableBeanFactoryTests {
assertThat(factory.getBean("child")).isInstanceOf(DerivedTestBean.class);
}
@Test
void nameAlreadyBound() {
Properties p = new Properties();
p.setProperty("kerry.(class)", TestBean.class.getName());
p.setProperty("kerry.age", "35");
registerBeanDefinitions(p);
try {
registerBeanDefinitions(p);
}
catch (BeanDefinitionStoreException ex) {
assertThat(ex.getBeanName()).isEqualTo("kerry");
// expected
}
}
private void singleTestBean(ListableBeanFactory lbf) {
assertThat(lbf.getBeanDefinitionCount() == 1).as("1 beans defined").isTrue();
String[] names = lbf.getBeanDefinitionNames();
assertThat(names != lbf.getBeanDefinitionNames()).isTrue();
assertThat(names.length == 1).as("Array length == 1").isTrue();
assertThat(names[0].equals("test")).as("0th element == test").isTrue();
TestBean tb = (TestBean) lbf.getBean("test");
assertThat(tb != null).as("Test is non null").isTrue();
assertThat("Tony".equals(tb.getName())).as("Test bean name is Tony").isTrue();
assertThat(tb.getAge() == 48).as("Test bean age is 48").isTrue();
}
@Test
void aliasCircle() {
lbf.registerAlias("test", "test2");
lbf.registerAlias("test2", "test3");
assertThatIllegalStateException().isThrownBy(() ->
lbf.registerAlias("test3", "test2"));
assertThatIllegalStateException().isThrownBy(() ->
lbf.registerAlias("test3", "test"));
lbf.registerAlias("test", "test3");
}
@@ -847,7 +840,6 @@ class DefaultListableBeanFactoryTests {
lbf.registerAlias("test", "testAlias");
lbf.registerAlias("testAlias", "testAlias2");
lbf.registerAlias("testAlias2", "testAlias3");
Object bean = lbf.getBean("test");
assertThat(lbf.getBean("testAlias")).isSameAs(bean);
assertThat(lbf.getBean("testAlias2")).isSameAs(bean);
@@ -862,7 +854,6 @@ class DefaultListableBeanFactoryTests {
lbf.registerAlias("test", "test2");
lbf.registerAlias("test", "testX");
lbf.registerBeanDefinition("testX", new RootBeanDefinition(TestBean.class));
assertThat(lbf.getBean("test")).isInstanceOf(NestedTestBean.class);
assertThat(lbf.getBean("test2")).isInstanceOf(NestedTestBean.class);
assertThat(lbf.getBean("testX")).isInstanceOf(TestBean.class);
@@ -875,15 +866,13 @@ class DefaultListableBeanFactoryTests {
BeanDefinition newDef = new RootBeanDefinition(NestedTestBean.class);
lbf.registerBeanDefinition("test", oldDef);
lbf.registerAlias("test", "testX");
assertThatExceptionOfType(BeanDefinitionOverrideException.class).isThrownBy(() ->
lbf.registerBeanDefinition("test", newDef))
lbf.registerBeanDefinition("test", newDef))
.satisfies(ex -> {
assertThat(ex.getBeanName()).isEqualTo("test");
assertThat(ex.getBeanDefinition()).isEqualTo(newDef);
assertThat(ex.getExistingDefinition()).isEqualTo(oldDef);
});
assertThatExceptionOfType(BeanDefinitionOverrideException.class).isThrownBy(() ->
lbf.registerBeanDefinition("testX", newDef))
.satisfies(ex -> {
@@ -899,7 +888,6 @@ class DefaultListableBeanFactoryTests {
lbf.registerAlias("test", "testAlias");
lbf.registerBeanDefinition("test", new RootBeanDefinition(NestedTestBean.class));
lbf.registerAlias("test", "testAlias");
assertThat(lbf.getBean("test")).isInstanceOf(NestedTestBean.class);
assertThat(lbf.getBean("testAlias")).isInstanceOf(NestedTestBean.class);
}
@@ -912,7 +900,6 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition bd2 = new RootBeanDefinition(NestedTestBean.class);
bd2.getConstructorArgumentValues().addIndexedArgumentValue(0, "value0");
lbf.registerBeanDefinition("test", bd2);
assertThat(lbf.getBean("test")).isInstanceOf(NestedTestBean.class);
assertThat(lbf.getBean("test", NestedTestBean.class).getCompany()).isEqualTo("value0");
}
@@ -929,7 +916,6 @@ class DefaultListableBeanFactoryTests {
lbf.removeAlias("test2");
lbf.registerBeanDefinition("test", new RootBeanDefinition(NestedTestBean.class));
lbf.registerAlias("test", "test2");
assertThat(lbf.getBean("test")).isInstanceOf(NestedTestBean.class);
assertThat(lbf.getBean("test2")).isInstanceOf(NestedTestBean.class);
}
@@ -969,7 +955,6 @@ class DefaultListableBeanFactoryTests {
p.setProperty("k.name", "kerry");
p.setProperty("k.spouse", "*r");
registerBeanDefinitions(p);
TestBean k = (TestBean) lbf.getBean("k");
TestBean r = (TestBean) lbf.getBean("r");
assertThat(k.getSpouse() == r).isTrue();
@@ -982,7 +967,6 @@ class DefaultListableBeanFactoryTests {
p.setProperty("r.(class)", TestBean.class.getName());
p.setProperty("r.name", "*" + name);
registerBeanDefinitions(p);
TestBean r = (TestBean) lbf.getBean("r");
assertThat(r.getName().equals(name)).isTrue();
}
@@ -998,7 +982,6 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
bd.setPropertyValues(pvs);
lbf.registerBeanDefinition("testBean", bd);
TestBean testBean = (TestBean) lbf.getBean("testBean");
assertThat(testBean.getMyFloat() == 1.1f).isTrue();
}
@@ -1016,13 +999,11 @@ class DefaultListableBeanFactoryTests {
}
});
lbf.setConversionService(conversionService);
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.add("myFloat", "1,1");
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
bd.setPropertyValues(pvs);
lbf.registerBeanDefinition("testBean", bd);
TestBean testBean = (TestBean) lbf.getBean("testBean");
assertThat(testBean.getMyFloat() == 1.1f).isTrue();
}
@@ -1039,7 +1020,6 @@ class DefaultListableBeanFactoryTests {
bd.setPropertyValues(pvs);
lbf.registerBeanDefinition("testBean", bd);
lbf.registerSingleton("myFloat", "1,1");
TestBean testBean = (TestBean) lbf.getBean("testBean");
assertThat(testBean.getMyFloat() == 1.1f).isTrue();
}
@@ -1054,7 +1034,6 @@ class DefaultListableBeanFactoryTests {
cav.addIndexedArgumentValue(0, "myName");
cav.addIndexedArgumentValue(1, "myAge");
lbf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class, cav, pvs));
TestBean testBean = (TestBean) lbf.getBean("testBean");
assertThat(testBean.getName()).isEqualTo("myName");
assertThat(testBean.getAge()).isEqualTo(5);
@@ -1072,7 +1051,6 @@ class DefaultListableBeanFactoryTests {
cav.addIndexedArgumentValue(1, "myAge");
lbf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class, cav, pvs));
lbf.registerSingleton("myFloat", "1,1");
TestBean testBean = (TestBean) lbf.getBean("testBean");
assertThat(testBean.getName()).isEqualTo("myName");
assertThat(testBean.getAge()).isEqualTo(5);
@@ -1189,7 +1167,6 @@ class DefaultListableBeanFactoryTests {
bd1.setScope(BeanDefinition.SCOPE_PROTOTYPE);
lbf.registerBeanDefinition("testBean", bd1);
assertThat(lbf.getBean("testBean")).isInstanceOf(TestBean.class);
RootBeanDefinition bd2 = new RootBeanDefinition(NestedTestBean.class);
bd2.setScope(BeanDefinition.SCOPE_PROTOTYPE);
lbf.registerBeanDefinition("testBean", bd2);
@@ -1204,8 +1181,8 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition rbd = new RootBeanDefinition(ArrayBean.class);
rbd.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE);
lbf.registerBeanDefinition("arrayBean", rbd);
ArrayBean ab = (ArrayBean) lbf.getBean("arrayBean");
assertThat(ab.getResourceArray()[0]).isEqualTo(new UrlResource("http://localhost:8080"));
assertThat(ab.getResourceArray()[1]).isEqualTo(new UrlResource("http://localhost:9090"));
}
@@ -1215,8 +1192,8 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition rbd = new RootBeanDefinition(ArrayBean.class);
rbd.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE);
lbf.registerBeanDefinition("arrayBean", rbd);
ArrayBean ab = (ArrayBean) lbf.getBean("arrayBean");
assertThat(ab.getResourceArray()).isNull();
}
@@ -1228,8 +1205,8 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition rbd = new RootBeanDefinition(ArrayBean.class);
rbd.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
lbf.registerBeanDefinition("arrayBean", rbd);
ArrayBean ab = (ArrayBean) lbf.getBean("arrayBean");
assertThat(ab.getIntegerArray()[0]).isEqualTo(4);
assertThat(ab.getIntegerArray()[1]).isEqualTo(5);
}
@@ -1239,8 +1216,8 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition rbd = new RootBeanDefinition(ArrayBean.class);
rbd.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
lbf.registerBeanDefinition("arrayBean", rbd);
ArrayBean ab = (ArrayBean) lbf.getBean("arrayBean");
assertThat(ab.getIntegerArray()).isNull();
}
@@ -1254,8 +1231,8 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition rbd = new RootBeanDefinition(ArrayBean.class);
rbd.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
lbf.registerBeanDefinition("arrayBean", rbd);
ArrayBean ab = (ArrayBean) lbf.getBean("arrayBean");
assertThat(ab.getIntegerArray()[0]).isEqualTo(4);
assertThat(ab.getIntegerArray()[1]).isEqualTo(5);
assertThat(ab.getResourceArray()[0]).isEqualTo(new UrlResource("http://localhost:8080"));
@@ -1270,8 +1247,8 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition rbd = new RootBeanDefinition(ArrayBean.class);
rbd.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
lbf.registerBeanDefinition("arrayBean", rbd);
ArrayBean ab = (ArrayBean) lbf.getBean("arrayBean");
assertThat(ab.getIntegerArray()).isNull();
assertThat(ab.getResourceArray()).isNull();
}
@@ -1288,7 +1265,6 @@ class DefaultListableBeanFactoryTests {
pvs.add("locations", new String[]{"#{foo}"});
rbd.setPropertyValues(pvs);
lbf.registerBeanDefinition("myProperties", rbd);
Properties properties = (Properties) lbf.getBean("myProperties");
assertThat(properties.getProperty("foo")).isEqualTo("bar");
}
@@ -1311,7 +1287,6 @@ class DefaultListableBeanFactoryTests {
bd.setPropertyValues(pvs);
lbf.registerBeanDefinition("rod", bd);
assertThat(lbf.getBeanDefinitionCount()).isEqualTo(1);
// Depends on age, name and spouse (TestBean)
Object registered = lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
assertThat(lbf.getBeanDefinitionCount()).isEqualTo(1);
@@ -1328,7 +1303,6 @@ class DefaultListableBeanFactoryTests {
bd.setPropertyValues(pvs);
lbf.registerBeanDefinition("rod", bd);
assertThat(lbf.getBeanDefinitionCount()).isEqualTo(1);
Object registered = lbf.autowire(ConstructorDependency.class, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false);
assertThat(lbf.getBeanDefinitionCount()).isEqualTo(1);
ConstructorDependency kerry = (ConstructorDependency) registered;
@@ -1342,8 +1316,6 @@ class DefaultListableBeanFactoryTests {
lbf.registerBeanDefinition("rod", bd);
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
lbf.registerBeanDefinition("rod2", bd2);
lbf.setParameterNameDiscoverer(new DefaultParameterNameDiscoverer());
assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(() ->
lbf.autowire(ConstructorDependency.class, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false))
.withMessageContaining("rod")
@@ -1357,7 +1329,6 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
bd.setPropertyValues(pvs);
lbf.registerBeanDefinition("rod", bd);
assertThat(lbf.getBeanDefinitionCount()).isEqualTo(1);
assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(() ->
lbf.autowire(UnsatisfiedConstructorDependency.class, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, true));
@@ -1369,7 +1340,6 @@ class DefaultListableBeanFactoryTests {
lbf.registerBeanDefinition("spouse", bd);
ConstructorDependenciesBean bean = (ConstructorDependenciesBean)
lbf.autowire(ConstructorDependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, true);
Object spouse = lbf.getBean("spouse");
assertThat(bean.getSpouse1() == spouse).isTrue();
assertThat(BeanFactoryUtils.beanOfType(lbf, TestBean.class) == spouse).isTrue();
@@ -1381,7 +1351,6 @@ class DefaultListableBeanFactoryTests {
lbf.registerBeanDefinition("spouse", bd);
DependenciesBean bean = (DependenciesBean)
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true);
TestBean spouse = (TestBean) lbf.getBean("spouse");
assertThat(bean.getSpouse()).isEqualTo(spouse);
assertThat(BeanFactoryUtils.beanOfType(lbf, TestBean.class) == spouse).isTrue();
@@ -1391,7 +1360,6 @@ class DefaultListableBeanFactoryTests {
void autowireBeanByNameWithDependencyCheck() {
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
lbf.registerBeanDefinition("spous", bd);
assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(() ->
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true));
}
@@ -1402,7 +1370,6 @@ class DefaultListableBeanFactoryTests {
lbf.registerBeanDefinition("spous", bd);
DependenciesBean bean = (DependenciesBean)
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false);
assertThat(bean.getSpouse()).isNull();
}
@@ -1414,7 +1381,6 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
bd2.setDependsOn("tb1");
lbf.registerBeanDefinition("tb2", bd2);
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() ->
lbf.preInstantiateSingletons())
.withMessageContaining("Circular")
@@ -1433,7 +1399,6 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition bd3 = new RootBeanDefinition(TestBean.class);
bd3.setDependsOn("tb1");
lbf.registerBeanDefinition("tb3", bd3);
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(
lbf::preInstantiateSingletons)
.withMessageContaining("Circular")
@@ -1443,31 +1408,30 @@ class DefaultListableBeanFactoryTests {
@Test
void getBeanByTypeWithNoneFound() {
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
assertThatExceptionOfType(NoSuchBeanDefinitionException.class).isThrownBy(() ->
lbf.getBean(TestBean.class));
}
@Test
void getBeanByTypeWithLateRegistration() {
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
assertThatExceptionOfType(NoSuchBeanDefinitionException.class).isThrownBy(() ->
lbf.getBean(TestBean.class));
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
lbf.registerBeanDefinition("bd1", bd1);
TestBean bean = lbf.getBean(TestBean.class);
assertThat(bean.getBeanName()).isEqualTo("bd1");
}
@Test
void getBeanByTypeWithLateRegistrationAgainstFrozen() {
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
lbf.freezeConfiguration();
assertThatExceptionOfType(NoSuchBeanDefinitionException.class).isThrownBy(() ->
lbf.getBean(TestBean.class));
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
lbf.registerBeanDefinition("bd1", bd1);
TestBean bean = lbf.getBean(TestBean.class);
assertThat(bean.getBeanName()).isEqualTo("bd1");
}
@@ -1477,8 +1441,7 @@ class DefaultListableBeanFactoryTests {
DefaultListableBeanFactory parent = new DefaultListableBeanFactory();
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
parent.registerBeanDefinition("bd1", bd1);
lbf.setParentBeanFactory(parent);
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(parent);
TestBean bean = lbf.getBean(TestBean.class);
assertThat(bean.getBeanName()).isEqualTo("bd1");
}
@@ -1489,7 +1452,6 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
lbf.registerBeanDefinition("bd1", bd1);
lbf.registerBeanDefinition("bd2", bd2);
assertThatExceptionOfType(NoUniqueBeanDefinitionException.class).isThrownBy(() ->
lbf.getBean(TestBean.class));
}
@@ -1502,7 +1464,6 @@ class DefaultListableBeanFactoryTests {
bd2.setPrimary(true);
lbf.registerBeanDefinition("bd1", bd1);
lbf.registerBeanDefinition("bd2", bd2);
TestBean bean = lbf.getBean(TestBean.class);
assertThat(bean.getBeanName()).isEqualTo("bd2");
assertThat(lbf.containsSingleton("bd1")).isFalse();
@@ -1511,12 +1472,12 @@ class DefaultListableBeanFactoryTests {
@Test
@SuppressWarnings("rawtypes")
void getFactoryBeanByTypeWithPrimary() {
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
RootBeanDefinition bd1 = new RootBeanDefinition(NullTestBeanFactoryBean.class);
RootBeanDefinition bd2 = new RootBeanDefinition(NullTestBeanFactoryBean.class);
bd2.setPrimary(true);
lbf.registerBeanDefinition("bd1", bd1);
lbf.registerBeanDefinition("bd2", bd2);
NullTestBeanFactoryBean factoryBeanByType = lbf.getBean(NullTestBeanFactoryBean.class);
NullTestBeanFactoryBean bd1FactoryBean = (NullTestBeanFactoryBean)lbf.getBean("&bd1");
NullTestBeanFactoryBean bd2FactoryBean = (NullTestBeanFactoryBean)lbf.getBean("&bd2");
@@ -1535,7 +1496,6 @@ class DefaultListableBeanFactoryTests {
bd2.setPrimary(true);
lbf.registerBeanDefinition("bd1", bd1);
lbf.registerBeanDefinition("bd2", bd2);
assertThatExceptionOfType(NoUniqueBeanDefinitionException.class).isThrownBy(() ->
lbf.getBean(TestBean.class))
.withMessageContaining("more than one 'primary'");
@@ -1551,7 +1511,6 @@ class DefaultListableBeanFactoryTests {
lbf.registerBeanDefinition("bd2", bd2);
lbf.registerBeanDefinition("bd3", bd3);
lbf.preInstantiateSingletons();
TestBean bean = lbf.getBean(TestBean.class);
assertThat(bean.getBeanName()).isEqualTo("bd1");
}
@@ -1568,7 +1527,6 @@ class DefaultListableBeanFactoryTests {
lbf.registerBeanDefinition("bd3", bd3);
lbf.registerBeanDefinition("bd4", bd4);
lbf.preInstantiateSingletons();
TestBean bean = lbf.getBean(TestBeanRecipient.class).testBean;
assertThat(bean.getBeanName()).isEqualTo("bd1");
}
@@ -1580,7 +1538,6 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition bd2 = new RootBeanDefinition(HighPriorityTestBean.class);
lbf.registerBeanDefinition("bd1", bd1);
lbf.registerBeanDefinition("bd2", bd2);
assertThatExceptionOfType(NoUniqueBeanDefinitionException.class).isThrownBy(() ->
lbf.getBean(TestBean.class))
.withMessageContaining("Multiple beans found with the same priority")
@@ -1594,7 +1551,6 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition bd2 = new RootBeanDefinition(NullTestBeanFactoryBean.class);
lbf.registerBeanDefinition("bd1", bd1);
lbf.registerBeanDefinition("bd2", bd2);
TestBean bean = lbf.getBean(TestBean.class);
assertThat(bean.getBeanName()).isEqualTo("bd1");
}
@@ -1607,7 +1563,6 @@ class DefaultListableBeanFactoryTests {
bd2.setPrimary(true);
lbf.registerBeanDefinition("bd1", bd1);
lbf.registerBeanDefinition("bd2", bd2);
TestBean bean = lbf.getBean(TestBean.class);
assertThat(bean.getBeanName()).isEqualTo("bd2");
}
@@ -1665,7 +1620,7 @@ class DefaultListableBeanFactoryTests {
DefaultListableBeanFactory parent = new DefaultListableBeanFactory();
RootBeanDefinition bd1 = createConstructorDependencyBeanDefinition(99);
parent.registerBeanDefinition("bd1", bd1);
lbf.setParentBeanFactory(parent);
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(parent);
ConstructorDependency bean = lbf.getBean(ConstructorDependency.class);
assertThat(bean.beanName).isEqualTo("bd1");
@@ -1697,7 +1652,6 @@ class DefaultListableBeanFactoryTests {
bd2.getConstructorArgumentValues().addGenericArgumentValue("43");
lbf.registerBeanDefinition("bd1", bd1);
lbf.registerBeanDefinition("bd2", bd2);
assertThatExceptionOfType(NoUniqueBeanDefinitionException.class).isThrownBy(() ->
lbf.getBean(ConstructorDependency.class));
assertThatExceptionOfType(NoUniqueBeanDefinitionException.class).isThrownBy(() ->
@@ -1815,9 +1769,9 @@ class DefaultListableBeanFactoryTests {
@SuppressWarnings("rawtypes")
void beanProviderSerialization() throws Exception {
lbf.setSerializationId("test");
ObjectProvider<ConstructorDependency> provider = lbf.getBeanProvider(ConstructorDependency.class);
ObjectProvider deserialized = SerializationTestUtils.serializeAndDeserialize(provider);
assertThatExceptionOfType(NoSuchBeanDefinitionException.class).isThrownBy(
deserialized::getObject);
assertThatExceptionOfType(NoSuchBeanDefinitionException.class).isThrownBy(() ->
@@ -1860,7 +1814,6 @@ class DefaultListableBeanFactoryTests {
lbf.registerBeanDefinition("test", bd);
DependenciesBean bean = (DependenciesBean)
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
TestBean test = (TestBean) lbf.getBean("test");
assertThat(bean.getSpouse()).isEqualTo(test);
}
@@ -1875,10 +1828,8 @@ class DefaultListableBeanFactoryTests {
void autowireBeanWithFactoryBeanByType() {
RootBeanDefinition bd = new RootBeanDefinition(LazyInitFactory.class);
lbf.registerBeanDefinition("factoryBean", bd);
LazyInitFactory factoryBean = (LazyInitFactory) lbf.getBean("&factoryBean");
assertThat(factoryBean).as("The FactoryBean should have been registered.").isNotNull();
FactoryBeanDependentBean bean = (FactoryBeanDependentBean) lbf.autowire(FactoryBeanDependentBean.class,
AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
assertThat(bean.getFactoryBean()).as("The FactoryBeanDependentBean should have been autowired 'by type' with the LazyInitFactory.").isEqualTo(factoryBean);
@@ -1886,17 +1837,16 @@ class DefaultListableBeanFactoryTests {
@Test
void autowireBeanWithFactoryBeanByTypeWithPrimary() {
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
RootBeanDefinition bd1 = new RootBeanDefinition(LazyInitFactory.class);
RootBeanDefinition bd2 = new RootBeanDefinition(LazyInitFactory.class);
bd2.setPrimary(true);
lbf.registerBeanDefinition("bd1", bd1);
lbf.registerBeanDefinition("bd2", bd2);
LazyInitFactory bd1FactoryBean = (LazyInitFactory) lbf.getBean("&bd1");
LazyInitFactory bd2FactoryBean = (LazyInitFactory) lbf.getBean("&bd2");
assertThat(bd1FactoryBean).isNotNull();
assertThat(bd2FactoryBean).isNotNull();
FactoryBeanDependentBean bean = (FactoryBeanDependentBean) lbf.autowire(FactoryBeanDependentBean.class,
AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
assertThat(bean.getFactoryBean()).isNotEqualTo(bd1FactoryBean);
@@ -1965,7 +1915,6 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition bd = new RootBeanDefinition(LazyInitFactory.class);
lbf.registerBeanDefinition("factoryBean", bd);
LazyInitFactory factoryBean = (LazyInitFactory) lbf.getBean("&factoryBean");
assertThat(factoryBean).as("The FactoryBean should have been registered.").isNotNull();
assertThatExceptionOfType(TypeMismatchException.class).isThrownBy(() ->
lbf.autowire(FactoryBeanDependentBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true));
@@ -1977,7 +1926,6 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
lbf.registerBeanDefinition("test", bd);
lbf.registerBeanDefinition("spouse", bd2);
assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(() ->
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true))
.withMessageContaining("test")
@@ -2018,7 +1966,6 @@ class DefaultListableBeanFactoryTests {
bd2.setPrimary(true);
lbf.registerBeanDefinition("test", bd);
lbf.registerBeanDefinition("spouse", bd2);
assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(() ->
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true))
.withCauseExactlyInstanceOf(NoUniqueBeanDefinitionException.class);
@@ -2044,7 +1991,6 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition bd2 = new RootBeanDefinition(HighPriorityTestBean.class);
lbf.registerBeanDefinition("test", bd);
lbf.registerBeanDefinition("spouse", bd2);
assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(() ->
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true))
.withCauseExactlyInstanceOf(NoUniqueBeanDefinitionException.class)
@@ -2084,7 +2030,6 @@ class DefaultListableBeanFactoryTests {
lbf.registerBeanDefinition("spouse", bd);
DependenciesBean existingBean = new DependenciesBean();
lbf.autowireBeanProperties(existingBean, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true);
TestBean spouse = (TestBean) lbf.getBean("spouse");
assertThat(spouse).isEqualTo(existingBean.getSpouse());
assertThat(BeanFactoryUtils.beanOfType(lbf, TestBean.class)).isSameAs(spouse);
@@ -2095,7 +2040,6 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
lbf.registerBeanDefinition("spous", bd);
DependenciesBean existingBean = new DependenciesBean();
assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(() ->
lbf.autowireBeanProperties(existingBean, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true));
}
@@ -2106,7 +2050,6 @@ class DefaultListableBeanFactoryTests {
lbf.registerBeanDefinition("spous", bd);
DependenciesBean existingBean = new DependenciesBean();
lbf.autowireBeanProperties(existingBean, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false);
assertThat(existingBean.getSpouse()).isNull();
}
@@ -2116,7 +2059,6 @@ class DefaultListableBeanFactoryTests {
lbf.registerBeanDefinition("test", bd);
DependenciesBean existingBean = new DependenciesBean();
lbf.autowireBeanProperties(existingBean, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
TestBean test = (TestBean) lbf.getBean("test");
assertThat(test).isEqualTo(existingBean.getSpouse());
}
@@ -2184,23 +2126,6 @@ class DefaultListableBeanFactoryTests {
assertThat(tb.wasDestroyed()).isTrue();
}
@Test
void createBeanWithNonDefaultConstructor() {
lbf.registerBeanDefinition("otherTestBean", new RootBeanDefinition(TestBean.class));
TestBeanRecipient tb = lbf.createBean(TestBeanRecipient.class);
assertThat(lbf.containsSingleton("otherTestBean")).isTrue();
assertThat(tb.testBean).isEqualTo(lbf.getBean("otherTestBean"));
lbf.destroyBean(tb);
}
@Test
void createBeanWithPreferredDefaultConstructor() {
lbf.registerBeanDefinition("otherTestBean", new RootBeanDefinition(TestBean.class));
TestBean tb = lbf.createBean(TestBean.class);
assertThat(lbf.containsSingleton("otherTestBean")).isFalse();
lbf.destroyBean(tb);
}
@Test
void configureBean() {
MutablePropertyValues pvs = new MutablePropertyValues();
@@ -2208,7 +2133,6 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
bd.setPropertyValues(pvs);
lbf.registerBeanDefinition("test", bd);
TestBean tb = new TestBean();
assertThat(tb.getAge()).isEqualTo(0);
lbf.configureBean(tb, "test");
@@ -2226,7 +2150,6 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition tbd = new RootBeanDefinition(TestBean.class);
tbd.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_NAME);
lbf.registerBeanDefinition("test", tbd);
TestBean tb = new TestBean();
lbf.configureBean(tb, "test");
assertThat(tb.getBeanFactory()).isSameAs(lbf);
@@ -2244,7 +2167,6 @@ class DefaultListableBeanFactoryTests {
lbf.registerBeanDefinition("bean" + i, bd);
}
lbf.preInstantiateSingletons();
for (int i = 0; i < 1000; i++) {
TestBean bean = (TestBean) lbf.getBean("bean" + i);
TestBean otherBean = (TestBean) lbf.getBean("bean" + (i < 99 ? i + 1 : 0));
@@ -2257,7 +2179,6 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition bd = new RootBeanDefinition(ConstructorDependencyBean.class);
bd.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
lbf.registerBeanDefinition("test", bd);
assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(lbf::preInstantiateSingletons);
}
@@ -2266,7 +2187,6 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition bd = new RootBeanDefinition(ConstructorDependencyFactoryBean.class);
bd.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
lbf.registerBeanDefinition("test", bd);
assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(lbf::preInstantiateSingletons);
}
@@ -2275,7 +2195,6 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition bd = new RootBeanDefinition(ConstructorDependencyFactoryBean.class);
bd.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
lbf.registerBeanDefinition("test", bd);
assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(() -> lbf.getBeansOfType(String.class));
}
@@ -2303,14 +2222,12 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition bd = new RootBeanDefinition(ConstructorDependencyWithClassResolution.class);
bd.getConstructorArgumentValues().addGenericArgumentValue("java.lang.Strin");
lbf.registerBeanDefinition("test", bd);
assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(lbf::preInstantiateSingletons);
}
@Test
void beanDefinitionWithInterface() {
lbf.registerBeanDefinition("test", new RootBeanDefinition(ITestBean.class));
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() ->
lbf.getBean("test"))
.withMessageContaining("interface")
@@ -2320,7 +2237,6 @@ class DefaultListableBeanFactoryTests {
@Test
void beanDefinitionWithAbstractClass() {
lbf.registerBeanDefinition("test", new RootBeanDefinition(AbstractBeanFactory.class));
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() ->
lbf.getBean("test"))
.withMessageContaining("abstract")
@@ -2364,7 +2280,6 @@ class DefaultListableBeanFactoryTests {
void lazyInitFactory() {
lbf.registerBeanDefinition("test", new RootBeanDefinition(LazyInitFactory.class));
lbf.preInstantiateSingletons();
LazyInitFactory factory = (LazyInitFactory) lbf.getBean("&test");
assertThat(factory.initialized).isFalse();
}
@@ -2373,7 +2288,6 @@ class DefaultListableBeanFactoryTests {
void smartInitFactory() {
lbf.registerBeanDefinition("test", new RootBeanDefinition(EagerInitFactory.class));
lbf.preInstantiateSingletons();
EagerInitFactory factory = (EagerInitFactory) lbf.getBean("&test");
assertThat(factory.initialized).isTrue();
}
@@ -2384,7 +2298,6 @@ class DefaultListableBeanFactoryTests {
stringDef.setScope(BeanDefinition.SCOPE_PROTOTYPE);
stringDef.getConstructorArgumentValues().addGenericArgumentValue(new TypedStringValue("value"));
lbf.registerBeanDefinition("string", stringDef);
String val1 = lbf.getBean("string", String.class);
String val2 = lbf.getBean("string", String.class);
assertThat(val1).isEqualTo("value");
@@ -2399,11 +2312,9 @@ class DefaultListableBeanFactoryTests {
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
bd.getConstructorArgumentValues().addGenericArgumentValue(list);
lbf.registerBeanDefinition("test", bd);
DerivedTestBean tb = (DerivedTestBean) lbf.getBean("test");
assertThat(tb.getName()).isEqualTo("myName");
assertThat(tb.getBeanName()).isEqualTo("myBeanName");
DerivedTestBean tb2 = (DerivedTestBean) lbf.getBean("test");
assertThat(tb != tb2).isTrue();
assertThat(tb2.getName()).isEqualTo("myName");
@@ -2418,11 +2329,9 @@ class DefaultListableBeanFactoryTests {
bd.setFactoryMethodName("create");
bd.getConstructorArgumentValues().addGenericArgumentValue(list);
lbf.registerBeanDefinition("test", bd);
DerivedTestBean tb = (DerivedTestBean) lbf.getBean("test");
assertThat(tb.getName()).isEqualTo("myName");
assertThat(tb.getBeanName()).isEqualTo("myBeanName");
DerivedTestBean tb2 = (DerivedTestBean) lbf.getBean("test");
assertThat(tb != tb2).isTrue();
assertThat(tb2.getName()).isEqualTo("myName");
@@ -2435,7 +2344,6 @@ class DefaultListableBeanFactoryTests {
bd.setInitMethodNames("init1", "init2");
bd.setDestroyMethodNames("destroy2", "destroy1");
lbf.registerBeanDefinition("test", bd);
BeanWithInitAndDestroyMethods bean = lbf.getBean("test", BeanWithInitAndDestroyMethods.class);
assertThat(bean.initMethods).containsExactly("init", "init1", "init2");
assertThat(bean.destroyMethods).isEmpty();
@@ -2453,7 +2361,6 @@ class DefaultListableBeanFactoryTests {
return new TestBean();
}
});
BeanWithDisposableBean.closed = false;
lbf.preInstantiateSingletons();
lbf.destroySingletons();
@@ -2470,7 +2377,6 @@ class DefaultListableBeanFactoryTests {
return new TestBean();
}
});
BeanWithDisposableBean.closed = false;
lbf.preInstantiateSingletons();
lbf.destroySingletons();
@@ -2488,7 +2394,6 @@ class DefaultListableBeanFactoryTests {
return new TestBean();
}
});
BeanWithDestroyMethod.closeCount = 0;
lbf.preInstantiateSingletons();
lbf.destroySingletons();
@@ -2693,7 +2598,6 @@ class DefaultListableBeanFactoryTests {
}
});
lbf.preInstantiateSingletons();
TestBean tb = (TestBean) lbf.getBean("test");
assertThat(tb.getName()).as("Name was set on field by IAPP").isEqualTo(nameSetOnField);
if (!skipPropertyPopulation) {
@@ -2737,7 +2641,6 @@ class DefaultListableBeanFactoryTests {
bd.setFactoryMethodName("of");
bd.getConstructorArgumentValues().addGenericArgumentValue("CONTENT");
lbf.registerBeanDefinition("optionalBean", bd);
assertThat((Optional<?>) lbf.getBean(Optional.class)).isEqualTo(Optional.of("CONTENT"));
}
@@ -2746,7 +2649,6 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition bd = new RootBeanDefinition(Optional.class);
bd.setFactoryMethodName("empty");
lbf.registerBeanDefinition("optionalBean", bd);
assertThat((Optional<?>) lbf.getBean(Optional.class)).isSameAs(Optional.empty());
}
@@ -2755,21 +2657,18 @@ class DefaultListableBeanFactoryTests {
RootBeanDefinition bd = new RootBeanDefinition(NonPublicEnumHolder.class);
bd.getConstructorArgumentValues().addGenericArgumentValue("VALUE_1");
lbf.registerBeanDefinition("holderBean", bd);
NonPublicEnumHolder holder = (NonPublicEnumHolder) lbf.getBean("holderBean");
assertThat(holder.getNonPublicEnum()).isEqualTo(NonPublicEnum.VALUE_1);
}
@SuppressWarnings("deprecation")
private int registerBeanDefinitions(Properties p) {
return registerBeanDefinitions(p, null);
return (new org.springframework.beans.factory.support.PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
}
@SuppressWarnings("deprecation")
private int registerBeanDefinitions(Properties p, @Nullable String prefix) {
for (String beanName : lbf.getBeanDefinitionNames()) {
lbf.removeBeanDefinition(beanName);
}
private int registerBeanDefinitions(Properties p, String prefix) {
return (new org.springframework.beans.factory.support.PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p, prefix);
}
@@ -2821,7 +2720,7 @@ class DefaultListableBeanFactoryTests {
}
@Override
public boolean equals(@Nullable Object o) {
public boolean equals(Object o) {
if (this == o) {
return true;
}
@@ -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.
@@ -27,10 +27,10 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* Tests for {@link AbstractAutowireCapableBeanFactory} instance supplier support.
* Tests for {@link AbstractAutowireCapableBeanFactory} instance supplier
* support.
*
* @author Phillip Webb
* @author Juergen Hoeller
*/
public class BeanFactorySupplierTests {
@@ -43,39 +43,14 @@ public class BeanFactorySupplierTests {
assertThat(beanFactory.getBean("test")).isEqualTo("I am supplied");
}
@Test
void getBeanWithInnerBeanUsingRegularSupplier() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setInstanceSupplier(() -> "I am supplied");
RootBeanDefinition outerBean = new RootBeanDefinition(String.class);
outerBean.getConstructorArgumentValues().addGenericArgumentValue(beanDefinition);
beanFactory.registerBeanDefinition("test", outerBean);
assertThat(beanFactory.getBean("test")).asString().startsWith("I am supplied");
}
@Test
void getBeanWhenUsingInstanceSupplier() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
RootBeanDefinition beanDefinition = new RootBeanDefinition(String.class);
beanDefinition.setInstanceSupplier(InstanceSupplier.of(registeredBean ->
"I am bean " + registeredBean.getBeanName() + " of " + registeredBean.getBeanClass()));
RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setInstanceSupplier(InstanceSupplier
.of(registeredBean -> "I am bean " + registeredBean.getBeanName()));
beanFactory.registerBeanDefinition("test", beanDefinition);
assertThat(beanFactory.getBean("test")).isEqualTo("I am bean test of class java.lang.String");
}
@Test
void getBeanWithInnerBeanUsingInstanceSupplier() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
RootBeanDefinition beanDefinition = new RootBeanDefinition(String.class);
beanDefinition.setInstanceSupplier(InstanceSupplier.of(registeredBean ->
"I am bean " + registeredBean.getBeanName() + " of " + registeredBean.getBeanClass()));
RootBeanDefinition outerBean = new RootBeanDefinition(String.class);
outerBean.getConstructorArgumentValues().addGenericArgumentValue(beanDefinition);
beanFactory.registerBeanDefinition("test", outerBean);
assertThat(beanFactory.getBean("test")).asString()
.startsWith("I am bean (inner bean)")
.endsWith(" of class java.lang.String");
assertThat(beanFactory.getBean("test")).isEqualTo("I am bean test");
}
@Test
@@ -87,17 +62,6 @@ public class BeanFactorySupplierTests {
assertThat(beanFactory.getBean("test")).isEqualTo("I am supplied");
}
@Test
void getBeanWithInnerBeanUsingThrowableSupplier() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setInstanceSupplier(ThrowingSupplier.of(() -> "I am supplied"));
RootBeanDefinition outerBean = new RootBeanDefinition(String.class);
outerBean.getConstructorArgumentValues().addGenericArgumentValue(beanDefinition);
beanFactory.registerBeanDefinition("test", outerBean);
assertThat(beanFactory.getBean("test")).asString().startsWith("I am supplied");
}
@Test
void getBeanWhenUsingThrowableSupplierThatThrowsCheckedException() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
@@ -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.
@@ -22,7 +22,6 @@ import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.testfixture.beans.TestBean;
import org.springframework.lang.Nullable;
import static org.assertj.core.api.Assertions.assertThat;
@@ -195,7 +194,7 @@ public class PagedListHolderTests {
}
@Override
public boolean equals(@Nullable Object o) {
public boolean equals(Object o) {
if (this == o) {
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.
@@ -16,8 +16,6 @@
package org.springframework.beans.testfixture.beans;
import org.springframework.lang.Nullable;
/**
* Simple nested test bean used for testing bean factories, AOP framework etc.
*
@@ -45,7 +43,7 @@ public class NestedTestBean implements INestedTestBean {
}
@Override
public boolean equals(@Nullable Object obj) {
public boolean equals(Object obj) {
if (!(obj instanceof NestedTestBean ntb)) {
return false;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,8 +16,6 @@
package org.springframework.beans.testfixture.beans;
import org.springframework.lang.Nullable;
/**
* @author Rob Harrop
* @since 2.0
@@ -40,7 +38,7 @@ public class Pet {
}
@Override
public boolean equals(@Nullable Object o) {
public boolean equals(Object o) {
if (this == o) {
return true;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2016 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.
@@ -18,7 +18,6 @@ package org.springframework.beans.testfixture.beans;
import java.io.Serializable;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
/**
@@ -64,7 +63,7 @@ public class SerializablePerson implements Person, Serializable {
@Override
public boolean equals(@Nullable Object other) {
public boolean equals(Object other) {
if (!(other instanceof SerializablePerson p)) {
return false;
}
@@ -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.
@@ -30,7 +30,6 @@ import java.util.Set;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
/**
@@ -465,7 +464,7 @@ public class TestBean implements BeanNameAware, BeanFactoryAware, ITestBean, IOt
@Override
public boolean equals(@Nullable Object other) {
public boolean equals(Object other) {
if (this == other) {
return true;
}
@@ -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.
@@ -133,8 +133,8 @@ public class CandidateComponentsIndexer implements Processor {
List<TypeElement> list = new ArrayList<>();
for (Element element : elements) {
if ((element.getKind().isClass() || element.getKind() == ElementKind.INTERFACE) &&
element.getModifiers().contains(Modifier.STATIC) && element instanceof TypeElement te) {
list.add(te);
element.getModifiers().contains(Modifier.STATIC) && element instanceof TypeElement) {
list.add((TypeElement) element);
}
}
return list;
@@ -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,8 +73,8 @@ class TypeHelper {
}
private String getQualifiedName(Element element) {
if (element instanceof QualifiedNameable qualifiedNameable) {
return qualifiedNameable.getQualifiedName().toString();
if (element instanceof QualifiedNameable) {
return ((QualifiedNameable) element).getQualifiedName().toString();
}
return element.toString();
}
@@ -1,4 +0,0 @@
/**
* Core package for Spring Framework's scanned component index.
*/
package org.springframework.context.index.processor;
@@ -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.
@@ -93,8 +93,8 @@ public class CaffeineCache extends AbstractValueAdaptingCache {
@Override
@Nullable
protected Object lookup(Object key) {
if (this.cache instanceof LoadingCache<Object, Object> loadingCache) {
return loadingCache.get(key);
if (this.cache instanceof LoadingCache) {
return ((LoadingCache<Object, Object>) this.cache).get(key);
}
return this.cache.getIfPresent(key);
}
@@ -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.
@@ -51,7 +51,6 @@ import org.springframework.util.ObjectUtils;
* @author Juergen Hoeller
* @author Stephane Nicoll
* @author Sam Brannen
* @author Brian Clozel
* @since 4.3
* @see CaffeineCache
*/
@@ -189,13 +188,8 @@ public class CaffeineCacheManager implements CacheManager {
@Override
@Nullable
public Cache getCache(String name) {
if (this.dynamic) {
Cache cache = this.cacheMap.get(name);
return (cache != null) ? cache : this.cacheMap.computeIfAbsent(name, this::createCaffeineCache);
}
else {
return this.cacheMap.get(name);
}
return this.cacheMap.computeIfAbsent(name, cacheName ->
this.dynamic ? createCaffeineCache(cacheName) : null);
}
@@ -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.
@@ -48,8 +48,8 @@ public abstract class AbstractJCacheConfiguration extends AbstractCachingConfigu
protected void useCachingConfigurer(CachingConfigurerSupplier cachingConfigurerSupplier) {
super.useCachingConfigurer(cachingConfigurerSupplier);
this.exceptionCacheResolver = cachingConfigurerSupplier.adapt(config -> {
if (config instanceof JCacheConfigurer jcacheConfigurer) {
return jcacheConfigurer.exceptionCacheResolver();
if (config instanceof JCacheConfigurer) {
return ((JCacheConfigurer) config).exceptionCacheResolver();
}
return null;
});
@@ -1,10 +1,10 @@
/**
* Support package for declarative JSR-107 caching configuration. Used by Spring's
* caching configuration when it detects the JSR-107 API and Spring's JCache
* implementation.
* Support package for declarative JSR-107 caching configuration. Used
* by the regular Spring's caching configuration when it detects the
* JSR-107 API and Spring's JCache implementation.
*
* <p>Provides an extension of the {@code CachingConfigurer} that exposes
* the exception cache resolver to use (see {@code JCacheConfigurer}).
* <p>Provide an extension of the {@code CachingConfigurer} that exposes
* the exception cache resolver to use, see {@code JCacheConfigurer}.
*/
@NonNullApi
@NonNullFields
@@ -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.
@@ -42,8 +42,8 @@ class DefaultCacheKeyInvocationContext<A extends Annotation> extends DefaultCach
public DefaultCacheKeyInvocationContext(AbstractJCacheKeyOperation<A> operation, Object target, Object[] args) {
super(operation, target, args);
this.keyParameters = operation.getKeyParameters(args);
if (operation instanceof CachePutOperation cachePutOperation) {
this.valueParameter = cachePutOperation.getValueParameter(args);
if (operation instanceof CachePutOperation) {
this.valueParameter = ((CachePutOperation) operation).getValueParameter(args);
}
else {
this.valueParameter = null;
@@ -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.
@@ -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.
@@ -71,11 +71,11 @@ public class AdaptableJobFactory implements JobFactory {
* @see DelegatingJob
*/
protected Job adaptJob(Object jobObject) throws Exception {
if (jobObject instanceof Job job) {
return job;
if (jobObject instanceof Job) {
return (Job) jobObject;
}
else if (jobObject instanceof Runnable runnable) {
return new DelegatingJob(runnable);
else if (jobObject instanceof Runnable) {
return new DelegatingJob((Runnable) jobObject);
}
else {
throw new IllegalArgumentException(
@@ -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.
@@ -267,9 +267,9 @@ public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethod
context.setResult(this.methodInvoker.invoke());
}
catch (InvocationTargetException ex) {
if (ex.getTargetException() instanceof JobExecutionException jobExecutionException) {
if (ex.getTargetException() instanceof JobExecutionException) {
// -> JobExecutionException, to be logged at info level by Quartz
throw jobExecutionException;
throw (JobExecutionException) ex.getTargetException();
}
else {
// -> "unhandled exception", to be logged at error level by Quartz

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