mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d5da602bc2 |
@@ -15,7 +15,7 @@ runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Generate Changelog
|
||||
uses: spring-io/github-changelog-generator@86958813a62af8fb223b3fd3b5152035504bcb83 #v0.0.12
|
||||
uses: spring-io/github-changelog-generator@185319ad7eaa75b0e8e72e4b6db19c8b2cb8c4c1 #v0.0.11
|
||||
with:
|
||||
config-file: .github/actions/create-github-release/changelog-generator.yml
|
||||
milestone: ${{ inputs.milestone }}
|
||||
|
||||
@@ -24,14 +24,14 @@ runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Set Up Java
|
||||
uses: actions/setup-java@v5
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: ${{ inputs.java-early-access == 'true' && 'temurin' || (inputs.java-distribution || 'liberica') }}
|
||||
java-version: |
|
||||
${{ inputs.java-early-access == 'true' && format('{0}-ea', inputs.java-version) || inputs.java-version }}
|
||||
${{ inputs.java-toolchain == 'true' && '17' || '' }}
|
||||
- name: Set Up Gradle
|
||||
uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # v5.0.0
|
||||
uses: gradle/actions/setup-gradle@cc4fc85e6b35bafd578d5ffbc76a5518407e1af0 # v4.2.1
|
||||
with:
|
||||
cache-read-only: false
|
||||
develocity-access-key: ${{ inputs.develocity-access-key }}
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
name: Sync to Maven Central
|
||||
description: 'Syncs a release to Maven Central and waits for it to be available for use'
|
||||
inputs:
|
||||
central-token-password:
|
||||
description: 'Password for authentication with central.sonatype.com'
|
||||
required: true
|
||||
central-token-username:
|
||||
description: 'Username for authentication with central.sonatype.com'
|
||||
required: true
|
||||
jfrog-cli-config-token:
|
||||
description: 'Config token for the JFrog CLI'
|
||||
required: true
|
||||
ossrh-s01-staging-profile:
|
||||
description: 'Staging profile to use when syncing to Central'
|
||||
required: true
|
||||
ossrh-s01-token-password:
|
||||
description: 'Password for authentication with s01.oss.sonatype.org'
|
||||
required: true
|
||||
ossrh-s01-token-username:
|
||||
description: 'Username for authentication with s01.oss.sonatype.org'
|
||||
required: true
|
||||
spring-framework-version:
|
||||
description: 'Version of Spring Framework that is being synced to Central'
|
||||
required: true
|
||||
@@ -17,17 +20,23 @@ runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Set Up JFrog CLI
|
||||
uses: jfrog/setup-jfrog-cli@5b06f730cc5a6f55d78b30753f8583454b08c0aa # v4.8.1
|
||||
uses: jfrog/setup-jfrog-cli@dff217c085c17666e8849ebdbf29c8fe5e3995e6 # v4.5.2
|
||||
env:
|
||||
JF_ENV_SPRING: ${{ inputs.jfrog-cli-config-token }}
|
||||
- name: Download Release Artifacts
|
||||
shell: bash
|
||||
run: jf rt download --spec ${{ format('{0}/artifacts.spec', github.action_path) }} --spec-vars 'buildName=${{ format('spring-framework-{0}', inputs.spring-framework-version) }};buildNumber=${{ github.run_number }}'
|
||||
- name: Sync
|
||||
uses: spring-io/central-publish-action@0c03960e9b16fdfe70e2443e1d5393cbc3a35622 # v0.3.0
|
||||
uses: spring-io/nexus-sync-action@42477a2230a2f694f9eaa4643fa9e76b99b7ab84 # v0.0.1
|
||||
with:
|
||||
token: ${{ inputs.central-token-password }}
|
||||
token-name: ${{ inputs.central-token-username }}
|
||||
close: true
|
||||
create: true
|
||||
generate-checksums: true
|
||||
password: ${{ inputs.ossrh-s01-token-password }}
|
||||
release: true
|
||||
staging-profile-name: ${{ inputs.ossrh-s01-staging-profile }}
|
||||
upload: true
|
||||
username: ${{ inputs.ossrh-s01-token-username }}
|
||||
- name: Await
|
||||
uses: ./.github/actions/await-http-resource
|
||||
with:
|
||||
|
||||
@@ -18,9 +18,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v5
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'liberica'
|
||||
java-version: 17
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Check Out Code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
- name: Build and Publish
|
||||
id: build-and-publish
|
||||
uses: ./.github/actions/build
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
publish: true
|
||||
- name: Deploy
|
||||
uses: spring-io/artifactory-deploy-action@926d7f7cc810569395346bf3a4d91b380b3e355b # v0.0.4
|
||||
uses: spring-io/artifactory-deploy-action@dc1913008c0599f0c4b1fdafb6ff3c502b3565ea # v0.0.2
|
||||
with:
|
||||
artifact-properties: |
|
||||
/**/framework-api-*.zip::zip.name=spring-framework,zip.deployed=false
|
||||
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Check Out Code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
- name: Build
|
||||
id: build
|
||||
uses: ./.github/actions/build
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
uses: ./.github/actions/print-jvm-thread-dumps
|
||||
- name: Upload Build Reports
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-reports
|
||||
path: '**/build/reports/'
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
toolchain: false
|
||||
- version: 21
|
||||
toolchain: true
|
||||
- version: 25
|
||||
- version: 23
|
||||
toolchain: true
|
||||
exclude:
|
||||
- os:
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
git config --global core.longPaths true
|
||||
Stop-Service -name Docker
|
||||
- name: Check Out Code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
- name: Build
|
||||
id: build
|
||||
uses: ./.github/actions/build
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
ref: docs-build
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check Out Code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
- name: Build and Publish
|
||||
id: build-and-publish
|
||||
uses: ./.github/actions/build
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
publish: true
|
||||
- name: Stage Release
|
||||
uses: spring-io/artifactory-deploy-action@926d7f7cc810569395346bf3a4d91b380b3e355b # v0.0.4
|
||||
uses: spring-io/artifactory-deploy-action@26bbe925a75f4f863e1e529e85be2d0093cac116 # v0.0.1
|
||||
with:
|
||||
artifact-properties: |
|
||||
/**/framework-api-*.zip::zip.name=spring-framework,zip.deployed=false
|
||||
@@ -56,13 +56,14 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check Out Code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- name: Sync to Maven Central
|
||||
uses: ./.github/actions/sync-to-maven-central
|
||||
with:
|
||||
central-token-password: ${{ secrets.CENTRAL_TOKEN_PASSWORD }}
|
||||
central-token-username: ${{ secrets.CENTRAL_TOKEN_USERNAME }}
|
||||
jfrog-cli-config-token: ${{ secrets.JF_ARTIFACTORY_SPRING }}
|
||||
ossrh-s01-staging-profile: ${{ secrets.OSSRH_S01_STAGING_PROFILE }}
|
||||
ossrh-s01-token-password: ${{ secrets.OSSRH_S01_TOKEN_PASSWORD }}
|
||||
ossrh-s01-token-username: ${{ secrets.OSSRH_S01_TOKEN_USERNAME }}
|
||||
spring-framework-version: ${{ needs.build-and-stage-release.outputs.version }}
|
||||
promote-release:
|
||||
name: Promote Release
|
||||
@@ -72,7 +73,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up JFrog CLI
|
||||
uses: jfrog/setup-jfrog-cli@5b06f730cc5a6f55d78b30753f8583454b08c0aa # v4.8.1
|
||||
uses: jfrog/setup-jfrog-cli@dff217c085c17666e8849ebdbf29c8fe5e3995e6 # v4.5.2
|
||||
env:
|
||||
JF_ENV_SPRING: ${{ secrets.JF_ARTIFACTORY_SPRING }}
|
||||
- name: Promote build
|
||||
@@ -85,7 +86,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check Out Code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- name: Create GitHub Release
|
||||
uses: ./.github/actions/create-github-release
|
||||
with:
|
||||
|
||||
@@ -30,23 +30,23 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check Out Release Verification Tests
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: 'v0.0.2'
|
||||
repository: spring-projects/spring-framework-release-verification
|
||||
token: ${{ secrets.token }}
|
||||
- name: Check Out Send Notification Action
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: send-notification
|
||||
sparse-checkout: .github/actions/send-notification
|
||||
- name: Set Up Java
|
||||
uses: actions/setup-java@v5
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'liberica'
|
||||
java-version: 17
|
||||
- name: Set Up Gradle
|
||||
uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # v5.0.0
|
||||
uses: gradle/actions/setup-gradle@cc4fc85e6b35bafd578d5ffbc76a5518407e1af0 # v4.2.1
|
||||
with:
|
||||
cache-read-only: false
|
||||
- name: Configure Gradle Properties
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
run: ./gradlew spring-framework-release-verification-tests:test
|
||||
- name: Upload Build Reports on Failure
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-reports
|
||||
path: '**/build/reports/'
|
||||
|
||||
+1
-3
@@ -9,7 +9,6 @@ ivy-cache
|
||||
argfile*
|
||||
activemq-data/
|
||||
classes/
|
||||
.cursor/
|
||||
|
||||
# Log files
|
||||
jxl.log
|
||||
@@ -43,8 +42,7 @@ spring-*/src/main/java/META-INF/MANIFEST.MF
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/*
|
||||
!.idea/icon.svg
|
||||
.idea
|
||||
out
|
||||
test-output
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
Generated
-52
@@ -1,52 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 510 510" style="enable-background:new 0 0 510 510;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#6DB33F;}
|
||||
</style>
|
||||
<title>icon-framework</title>
|
||||
<g id="Layer_2_1_">
|
||||
<g id="Layer_1-2">
|
||||
<path class="st0" d="M479.2,162.5c-5.6-34.3-20.5-64.4-43.9-87.8S382,36.5,347.6,30.9C320.1,11.2,288.5,0,255,0
|
||||
s-65.1,11.2-92.6,30.9C128,36.5,98,51.3,74.7,74.7C50.9,98.4,36.5,128.7,31,162.2C11.2,189.8,0,221.4,0,255s11.2,65.2,31,92.8
|
||||
c5.5,33.5,19.9,63.8,43.7,87.5c23.3,23.3,53.3,38.2,87.7,43.8C190,498.8,221.5,510,255,510s65-11.2,92.6-30.9
|
||||
c34.4-5.6,64.4-20.5,87.7-43.8c23.8-23.8,38.1-54.1,43.7-87.5c19.8-27.6,31-59.2,31-92.8S498.8,190,479.2,162.5z M473,224.2
|
||||
c-0.8,6-1.9,11.9-3.2,17.9c-7.2-22.4-17.1-43.8-29.4-63.8c-5.5-22.8-13.6-44.9-24.4-65.8c22.9,14.8,42.2,32.6,56.7,52.6
|
||||
C475.7,184.6,475.8,204.6,473,224.2z M444.7,199.6c9.3,17.7,16.6,36.3,21.9,55.6c-5.3,19.3-12.7,37.9-22,55.6
|
||||
C450.9,274,451,236.4,444.7,199.6L444.7,199.6z M175.4,341.1c6.5-4.5,13.7-7.8,21.3-9.8c32.2-7.5,46.7-9.9,66.3-18.4
|
||||
c36.8-15.9,74.8-53.3,84.6-94c-16.1,38.8-59.5,70.2-97.9,81.6c-26.2,7.8-79.8,13.6-80.1,13.6l-1.4-1.2
|
||||
c-30.6-17.4-27-85.8,31.8-104.1c25.7-8,55.9-0.7,83.5-5.4c29.4-5,64.4-24.5,79.9-52c12.3,46.4,26.1,118.5-9.7,160.2
|
||||
C309.4,363,211.8,318,175.4,341.1z M310.8,444.6c-17.7,9.4-36.5,16.8-55.8,22.1c-19.4-5.3-38.1-12.7-55.8-22.1
|
||||
C236.1,450.9,273.9,450.9,310.8,444.6z M117.6,392.4c13.1,13.1,27.3,25.1,42.3,35.8c-19-5.9-37.2-13.8-54.5-23.7
|
||||
c-9.9-17.3-17.8-35.7-23.7-54.7C92.4,365.1,104.5,379.3,117.6,392.4z M81.7,160.1c5.9-19,13.9-37.4,23.7-54.7
|
||||
c17.3-9.8,35.5-17.8,54.5-23.7c-15.1,10.8-29.2,22.7-42.3,35.8C104.5,130.7,92.4,144.9,81.7,160.1z M149.1,346.4
|
||||
c-8.5,0.2-15.5-6.5-15.7-15c-0.2-8.5,6.5-15.5,15-15.7c8.5-0.2,15.5,6.5,15.7,15c0,0,0,0.1,0,0.1
|
||||
C164.2,339.3,157.5,346.2,149.1,346.4L149.1,346.4z M199.2,65.4c17.7-9.4,36.5-16.8,55.8-22.1c19.4,5.3,38.1,12.7,55.8,22.1
|
||||
C273.9,59.1,236.1,59.1,199.2,65.4L199.2,65.4z M392.4,392.4c13.1-13.1,25.1-27.3,35.9-42.4c-5.9,19-13.9,37.3-23.7,54.5
|
||||
c-17.3,9.8-35.5,17.7-54.5,23.7C365.2,417.5,379.3,405.5,392.4,392.4L392.4,392.4z M392.4,117.6c-13.1-13.1-27.2-25.1-42.3-35.8
|
||||
c19,5.9,37.2,13.9,54.5,23.7c9.8,17.3,17.8,35.6,23.7,54.7C417.6,144.9,405.5,130.7,392.4,117.6L392.4,117.6z M430.5,79.5
|
||||
c19.4,19.3,32.6,43.6,39.3,71.1c-16.2-19.2-36.6-36.2-60.4-50c-13.8-23.8-30.8-44.2-50-60.4C387.1,46.9,411.2,60.1,430.5,79.5
|
||||
L430.5,79.5z M397.6,94c-20.8-10.7-42.8-18.8-65.6-24.2c-20-12.4-41.5-22.4-63.9-29.6c15.5-3.4,31.3-5.1,47.2-5.2
|
||||
c10,0,19.9,0.8,29.7,2.3C365.1,51.8,382.8,71.1,397.6,94z M255,6.8c27.6,0,53.8,8,77.4,22.2c-5.6-0.5-11.3-0.7-17.1-0.7
|
||||
c-20.4,0.1-40.6,2.8-60.3,8.1c-19.7-5.3-39.9-8-60.3-8.1c-5.8,0-11.5,0.2-17.1,0.7C201.2,14.7,227.4,6.8,255,6.8z M165,37.3
|
||||
c9.8-1.5,19.8-2.3,29.7-2.3c15.9,0.1,31.7,1.8,47.2,5.2C219.5,47.4,198,57.3,178,69.8c-22.7,5.4-44.8,13.6-65.6,24.2
|
||||
C127.2,71.1,144.9,51.8,165,37.3z M79.5,79.5c19.3-19.3,43.5-32.6,71.1-39.3c-19.2,16.2-36.2,36.6-50,60.4
|
||||
c-23.7,13.8-44,30.6-60.2,49.8C47,123.4,59.8,99.1,79.5,79.5z M37.4,164.9c14.6-20,33.8-37.7,56.6-52.4
|
||||
c-10.7,20.9-18.8,43-24.3,65.8c-12.3,20-22.2,41.4-29.4,63.8C34.6,215.4,33.5,189.3,37.4,164.9z M65.4,310.4
|
||||
c-9.3-17.6-16.6-36.2-21.9-55.4c5.3-19.2,12.6-37.8,21.9-55.4C59.1,236.3,59.1,273.7,65.4,310.4L65.4,310.4z M29.2,332.8
|
||||
c-14.4-23.7-22.4-50-22.4-77.8s8.1-54.1,22.4-77.8c-2.1,25,0.4,51.3,7.4,77.8C29.5,281.5,27,307.8,29.2,332.8z M40.3,268
|
||||
c7.2,22.3,17.1,43.7,29.4,63.7c5.5,22.8,13.6,44.9,24.3,65.8c-22.8-14.7-42-32.5-56.6-52.4C33.5,320.7,34.6,294.6,40.3,268z
|
||||
M79.5,430.5c-19.6-19.6-32.5-43.9-39.1-70.9c16.1,19.1,36.5,36,60.2,49.8c13.8,23.7,30.8,44.2,50,60.4
|
||||
C122.9,463.1,98.8,449.9,79.5,430.5z M112.5,416c20.8,10.7,42.8,18.8,65.5,24.2c20,12.4,41.5,22.4,63.9,29.6
|
||||
c-15.5,3.4-31.3,5.1-47.2,5.1c-10,0-19.9-0.8-29.7-2.3C144.9,458.1,127.2,438.9,112.5,416L112.5,416z M255,503.2
|
||||
c-27.6,0-53.8-8-77.4-22.2c5.6,0.5,11.3,0.7,17.1,0.7c20.4-0.1,40.6-2.8,60.3-8.1c19.7,5.3,39.9,8,60.3,8.1
|
||||
c5.8,0,11.5-0.2,17.1-0.7C308.8,495.3,282.6,503.2,255,503.2z M345,472.7c-9.8,1.5-19.8,2.3-29.7,2.3c-15.9-0.1-31.7-1.8-47.2-5.1
|
||||
c22.4-7.2,43.9-17.2,63.9-29.6c22.7-5.4,44.8-13.6,65.6-24.2C382.8,438.9,365.1,458.1,345,472.7z M430.5,430.5
|
||||
c-19.3,19.3-43.5,32.6-71.1,39.3c19.2-16.2,36.2-36.6,50-60.4c23.7-13.8,44-30.6,60.2-49.8C463.1,386.6,450.1,410.9,430.5,430.5
|
||||
L430.5,430.5z M472.6,345.1c-14.6,20-33.8,37.7-56.6,52.4c10.7-20.8,18.8-42.8,24.3-65.6c12.3-20,22.2-41.3,29.5-63.7
|
||||
C475.4,294.7,476.5,320.8,472.6,345.1L472.6,345.1z M473.5,255.3c2.6-9.9,4.7-20,6.1-30.1c2.2-15.7,2.7-31.7,1.4-47.5
|
||||
c14.2,23.6,22.2,49.8,22.2,77.4s-8.1,54.1-22.4,77.8C482.9,307.9,480.5,281.6,473.5,255.3L473.5,255.3z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 4.8 KiB |
@@ -27,7 +27,7 @@ See the [Build from Source](https://github.com/spring-projects/spring-framework/
|
||||
|
||||
## Continuous Integration Builds
|
||||
|
||||
CI builds are defined with [GitHub Actions workflows](.github/workflows).
|
||||
Information regarding CI builds can be found in the [Spring Framework Concourse pipeline](ci/README.adoc) documentation.
|
||||
|
||||
## Stay in Touch
|
||||
|
||||
|
||||
+15
-6
@@ -9,7 +9,7 @@ plugins {
|
||||
id 'io.github.goooler.shadow' version '8.1.8' apply false
|
||||
id 'me.champeau.jmh' version '0.7.2' apply false
|
||||
id 'me.champeau.mrjar' version '0.1.1'
|
||||
id "net.ltgt.errorprone" version "4.1.0" apply false
|
||||
id "net.ltgt.errorprone" version "3.1.0" apply false
|
||||
}
|
||||
|
||||
ext {
|
||||
@@ -68,13 +68,17 @@ configure([rootProject] + javaProjects) { project ->
|
||||
apply from: "${rootDir}/gradle/ide.gradle"
|
||||
|
||||
dependencies {
|
||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||
testImplementation("org.junit.platform:junit-platform-suite")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-api")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-params")
|
||||
testImplementation("org.junit.platform:junit-platform-suite-api")
|
||||
testImplementation("org.mockito:mockito-core")
|
||||
testImplementation("org.mockito:mockito-junit-jupiter")
|
||||
testImplementation("io.mockk:mockk")
|
||||
testImplementation("org.assertj:assertj-core")
|
||||
// Pull in the latest JUnit 5 Launcher API to ensure proper support in IDEs.
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-suite-engine")
|
||||
testRuntimeOnly("org.apache.logging.log4j:log4j-core")
|
||||
testRuntimeOnly("org.apache.logging.log4j:log4j-jul")
|
||||
testRuntimeOnly("org.apache.logging.log4j:log4j-slf4j2-impl")
|
||||
@@ -86,15 +90,20 @@ configure([rootProject] + javaProjects) { project ->
|
||||
ext.javadocLinks = [
|
||||
"https://docs.oracle.com/en/java/javase/17/docs/api/",
|
||||
"https://jakarta.ee/specifications/platform/9/apidocs/",
|
||||
"https://docs.hibernate.org/orm/5.6/javadocs/",
|
||||
"https://docs.jboss.org/hibernate/orm/5.6/javadocs/",
|
||||
"https://eclipse.dev/aspectj/doc/released/aspectj5rt-api",
|
||||
"https://www.quartz-scheduler.org/api/2.3.0/",
|
||||
"https://fasterxml.github.io/jackson-core/javadoc/2.14/",
|
||||
"https://fasterxml.github.io/jackson-databind/javadoc/2.14/",
|
||||
"https://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.14/",
|
||||
//"https://hc.apache.org/httpcomponents-client-5.5.x/current/httpclient5/apidocs/",
|
||||
"https://hc.apache.org/httpcomponents-client-5.4.x/current/httpclient5/apidocs/",
|
||||
"https://projectreactor.io/docs/test/release/api/",
|
||||
"https://junit.org/junit4/javadoc/4.13.2/",
|
||||
"https://www.reactive-streams.org/reactive-streams-1.0.4-javadoc/",
|
||||
// TODO Uncomment link to JUnit 5 docs once we execute Gradle with Java 18+.
|
||||
// See https://github.com/spring-projects/spring-framework/issues/27497
|
||||
//
|
||||
// "https://junit.org/junit5/docs/5.11.4/api/",
|
||||
"https://www.reactive-streams.org/reactive-streams-1.0.3-javadoc/",
|
||||
//"https://javadoc.io/static/io.rsocket/rsocket-core/1.1.1/",
|
||||
"https://r2dbc.io/spec/1.0.0.RELEASE/api/",
|
||||
// Previously there could be a split-package issue between JSR250 and JSR305 javax.annotation packages,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<module name="io.spring.javaformat.checkstyle.check.SpringHeaderCheck">
|
||||
<property name="fileExtensions" value="java"/>
|
||||
<property name="headerType" value="apache2"/>
|
||||
<property name="headerCopyrightPattern" value="20\d\d-present"/>
|
||||
<property name="headerCopyrightPattern" value="20\d\d-20\d\d"/>
|
||||
<property name="packageInfoHeaderType" value="none"/>
|
||||
</module>
|
||||
<module name="com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheck"/>
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
org.gradle.caching=true
|
||||
javaFormatVersion=0.0.43
|
||||
javaFormatVersion=0.0.42
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-present the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -50,7 +50,7 @@ public class CheckstyleConventions {
|
||||
project.getPlugins().apply(CheckstylePlugin.class);
|
||||
project.getTasks().withType(Checkstyle.class).forEach(checkstyle -> checkstyle.getMaxHeapSize().set("1g"));
|
||||
CheckstyleExtension checkstyle = project.getExtensions().getByType(CheckstyleExtension.class);
|
||||
checkstyle.setToolVersion("10.26.1");
|
||||
checkstyle.setToolVersion("10.21.1");
|
||||
checkstyle.getConfigDirectory().set(project.getRootProject().file("src/checkstyle"));
|
||||
String version = SpringJavaFormatPlugin.class.getPackage().getImplementationVersion();
|
||||
DependencySet checkstyleDependencies = project.getConfigurations().getByName("checkstyle").getDependencies();
|
||||
@@ -64,7 +64,7 @@ public class CheckstyleConventions {
|
||||
NoHttpExtension noHttp = project.getExtensions().getByType(NoHttpExtension.class);
|
||||
noHttp.setAllowlistFile(project.file("src/nohttp/allowlist.lines"));
|
||||
noHttp.getSource().exclude("**/test-output/**", "**/.settings/**",
|
||||
"**/.classpath", "**/.project", "**/.gradle/**", "**/node_modules/**", "buildSrc/build/**");
|
||||
"**/.classpath", "**/.project", "**/.gradle/**", "**/node_modules/**");
|
||||
List<String> buildFolders = List.of("bin", "build", "out");
|
||||
project.allprojects(subproject -> {
|
||||
Path rootPath = project.getRootDir().toPath();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-present the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-present the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-present the original author or authors.
|
||||
* Copyright 2002-2024 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.util.Map;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.plugins.JavaBasePlugin;
|
||||
import org.gradle.api.tasks.testing.Test;
|
||||
import org.gradle.api.tasks.testing.TestFrameworkOptions;
|
||||
import org.gradle.api.tasks.testing.junitplatform.JUnitPlatformOptions;
|
||||
import org.gradle.testretry.TestRetryPlugin;
|
||||
import org.gradle.testretry.TestRetryTaskExtension;
|
||||
|
||||
@@ -36,7 +34,6 @@ import org.gradle.testretry.TestRetryTaskExtension;
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @author Andy Wilkinson
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
class TestConventions {
|
||||
|
||||
@@ -53,12 +50,7 @@ class TestConventions {
|
||||
}
|
||||
|
||||
private void configureTests(Project project, Test test) {
|
||||
TestFrameworkOptions existingOptions = test.getOptions();
|
||||
test.useJUnitPlatform(options -> {
|
||||
if (existingOptions instanceof JUnitPlatformOptions junitPlatformOptions) {
|
||||
options.copyFrom(junitPlatformOptions);
|
||||
}
|
||||
});
|
||||
test.useJUnitPlatform();
|
||||
test.include("**/*Tests.class", "**/*Test.class");
|
||||
test.setSystemProperties(Map.of(
|
||||
"java.awt.headless", "true",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-present the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-present the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-present the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-present the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,7 +27,6 @@ import org.gradle.api.attributes.Usage;
|
||||
import org.gradle.api.attributes.java.TargetJvmVersion;
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.gradle.api.plugins.jvm.JvmTestSuite;
|
||||
import org.gradle.api.tasks.TaskProvider;
|
||||
import org.gradle.api.tasks.testing.Test;
|
||||
import org.gradle.testing.base.TestingExtension;
|
||||
|
||||
@@ -53,7 +52,7 @@ public class RuntimeHintsAgentPlugin implements Plugin<Project> {
|
||||
TestingExtension testing = project.getExtensions().getByType(TestingExtension.class);
|
||||
JvmTestSuite jvmTestSuite = (JvmTestSuite) testing.getSuites().getByName("test");
|
||||
RuntimeHintsAgentExtension agentExtension = createRuntimeHintsAgentExtension(project);
|
||||
TaskProvider<Test> agentTest = project.getTasks().register(RUNTIMEHINTS_TEST_TASK, Test.class, test -> {
|
||||
Test agentTest = project.getTasks().create(RUNTIMEHINTS_TEST_TASK, Test.class, test -> {
|
||||
test.useJUnitPlatform(options -> {
|
||||
options.includeTags("RuntimeHintsTests");
|
||||
});
|
||||
@@ -64,7 +63,7 @@ public class RuntimeHintsAgentPlugin implements Plugin<Project> {
|
||||
test.setClasspath(jvmTestSuite.getSources().getRuntimeClasspath());
|
||||
test.getJvmArgumentProviders().add(createRuntimeHintsAgentArgumentProvider(project, agentExtension));
|
||||
});
|
||||
project.getTasks().named("check", task -> task.dependsOn(agentTest));
|
||||
project.getTasks().getByName("check", task -> task.dependsOn(agentTest));
|
||||
project.getDependencies().add(CONFIGURATION_NAME, project.project(":spring-core-test"));
|
||||
});
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-present the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-present the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
plugins {
|
||||
id 'java-platform'
|
||||
id 'io.freefair.aggregate-javadoc' version '8.13.1'
|
||||
id 'io.freefair.aggregate-javadoc' version '8.3'
|
||||
}
|
||||
|
||||
description = "Spring Framework API Docs"
|
||||
@@ -21,7 +21,6 @@ dependencies {
|
||||
|
||||
javadoc {
|
||||
title = "${rootProject.description} ${version} API"
|
||||
failOnError = true
|
||||
options {
|
||||
encoding = "UTF-8"
|
||||
memberLevel = JavadocMemberLevel.PROTECTED
|
||||
@@ -32,9 +31,8 @@ javadoc {
|
||||
destinationDir = project.java.docsDir.dir("javadoc-api").get().asFile
|
||||
splitIndex = true
|
||||
links(rootProject.ext.javadocLinks)
|
||||
// Check for 'syntax' and 'reference' during linting.
|
||||
addBooleanOption('Xdoclint:syntax,reference', true)
|
||||
addBooleanOption('Werror', true) // fail build on Javadoc warnings
|
||||
addBooleanOption('Xdoclint:syntax,reference', true) // only check syntax and reference with doclint
|
||||
addBooleanOption('Werror', true) // fail build on Javadoc warnings
|
||||
}
|
||||
maxMemory = "1024m"
|
||||
doFirst {
|
||||
|
||||
@@ -13,10 +13,8 @@ content:
|
||||
- url: https://github.com/spring-projects/spring-framework
|
||||
# Refname matching:
|
||||
# https://docs.antora.org/antora/latest/playbook/content-refname-matching/
|
||||
# branches: We include snapshots for main, 6.2.x, and 7.0.x to 9.*.x.
|
||||
branches: ['main', '6.2.x', '{7..9}.+({0..9}).x']
|
||||
# tags: include all releases from 6.2.0 to 9.*.*.
|
||||
tags: ['v6.2.+({0..9})', 'v{7..9}.+({0..9}).+({0..9})?(-{RC,M}*)']
|
||||
branches: ['main', '{6..9}.+({1..9}).x']
|
||||
tags: ['v{6..9}.+({0..9}).+({0..9})?(-{RC,M}*)', '!(v6.0.{0..8})', '!(v6.0.0-{RC,M}{0..9})']
|
||||
start_path: framework-docs
|
||||
asciidoc:
|
||||
extensions:
|
||||
@@ -38,4 +36,4 @@ runtime:
|
||||
failure_level: warn
|
||||
ui:
|
||||
bundle:
|
||||
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.26/ui-bundle.zip
|
||||
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.18/ui-bundle.zip
|
||||
|
||||
@@ -6,7 +6,7 @@ nav:
|
||||
ext:
|
||||
collector:
|
||||
run:
|
||||
command: gradlew -q -PbuildSrc.skipTests=true "-Dorg.gradle.jvmargs=-Xmx3g" :framework-docs:generateAntoraResources
|
||||
command: gradlew -q -PbuildSrc.skipTests=true "-Dorg.gradle.jvmargs=-Xmx3g -XX:+HeapDumpOnOutOfMemoryError" :framework-docs:generateAntoraResources
|
||||
local: true
|
||||
scan:
|
||||
dir: ./build/generated-antora-resources
|
||||
|
||||
@@ -17,10 +17,6 @@ antora {
|
||||
]
|
||||
}
|
||||
|
||||
node {
|
||||
version = '24.15.0'
|
||||
}
|
||||
|
||||
tasks.named("generateAntoraYml") {
|
||||
asciidocAttributes = project.provider( {
|
||||
return ["spring-version": project.version ]
|
||||
@@ -46,34 +42,33 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":spring-aspects"))
|
||||
implementation(project(":spring-context"))
|
||||
implementation(project(":spring-context-support"))
|
||||
implementation(project(":spring-core-test"))
|
||||
implementation(project(":spring-jdbc"))
|
||||
implementation(project(":spring-jms"))
|
||||
implementation(project(":spring-test"))
|
||||
implementation(project(":spring-web"))
|
||||
implementation(project(":spring-webflux"))
|
||||
implementation(project(":spring-webmvc"))
|
||||
implementation(project(":spring-websocket"))
|
||||
api(project(":spring-aspects"))
|
||||
api(project(":spring-context"))
|
||||
api(project(":spring-context-support"))
|
||||
api(project(":spring-jdbc"))
|
||||
api(project(":spring-jms"))
|
||||
api(project(":spring-test"))
|
||||
api(project(":spring-web"))
|
||||
api(project(":spring-webflux"))
|
||||
api(project(":spring-webmvc"))
|
||||
api(project(":spring-websocket"))
|
||||
|
||||
implementation("com.fasterxml.jackson.core:jackson-databind")
|
||||
implementation("com.fasterxml.jackson.module:jackson-module-parameter-names")
|
||||
implementation("com.mchange:c3p0:0.9.5.5")
|
||||
implementation("com.oracle.database.jdbc:ojdbc11")
|
||||
implementation("io.projectreactor.netty:reactor-netty-http")
|
||||
implementation("jakarta.jms:jakarta.jms-api")
|
||||
implementation("jakarta.servlet:jakarta.servlet-api")
|
||||
implementation("jakarta.resource:jakarta.resource-api")
|
||||
implementation("jakarta.validation:jakarta.validation-api")
|
||||
implementation("jakarta.websocket:jakarta.websocket-client-api")
|
||||
implementation("javax.cache:cache-api")
|
||||
implementation("org.apache.activemq:activemq-ra:6.1.2")
|
||||
implementation("org.apache.commons:commons-dbcp2:2.11.0")
|
||||
implementation("org.aspectj:aspectjweaver")
|
||||
api("com.fasterxml.jackson.core:jackson-databind")
|
||||
api("com.fasterxml.jackson.module:jackson-module-parameter-names")
|
||||
api("com.mchange:c3p0:0.9.5.5")
|
||||
api("com.oracle.database.jdbc:ojdbc11")
|
||||
api("io.projectreactor.netty:reactor-netty-http")
|
||||
api("jakarta.jms:jakarta.jms-api")
|
||||
api("jakarta.servlet:jakarta.servlet-api")
|
||||
api("jakarta.resource:jakarta.resource-api")
|
||||
api("jakarta.validation:jakarta.validation-api")
|
||||
api("javax.cache:cache-api")
|
||||
api("org.apache.activemq:activemq-ra:6.1.2")
|
||||
api("org.apache.commons:commons-dbcp2:2.11.0")
|
||||
api("org.aspectj:aspectjweaver")
|
||||
api("org.eclipse.jetty.websocket:jetty-websocket-jetty-api")
|
||||
api("org.jetbrains.kotlin:kotlin-stdlib")
|
||||
|
||||
implementation(project(":spring-core-test"))
|
||||
implementation("org.assertj:assertj-core")
|
||||
implementation("org.eclipse.jetty.websocket:jetty-websocket-jetty-api")
|
||||
implementation("org.jetbrains.kotlin:kotlin-stdlib")
|
||||
implementation("org.junit.jupiter:junit-jupiter-api")
|
||||
}
|
||||
|
||||
@@ -326,9 +326,9 @@
|
||||
*** xref:testing/testcontext-framework/application-events.adoc[]
|
||||
*** xref:testing/testcontext-framework/test-execution-events.adoc[]
|
||||
*** xref:testing/testcontext-framework/ctx-management.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/javaconfig.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/xml.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/groovy.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/javaconfig.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/mixed-config.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/context-customizers.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/initializers.adoc[]
|
||||
|
||||
@@ -74,11 +74,6 @@ expressions used in XML bean definitions, `@Value`, etc.
|
||||
| The mode to use when compiling expressions for the
|
||||
xref:core/expressions/evaluation.adoc#expressions-compiler-configuration[Spring Expression Language].
|
||||
|
||||
| `spring.expression.maxOperations`
|
||||
| The default maximum number of operations permitted during
|
||||
xref:core/expressions/evaluation.adoc#expressions-parser-configuration[Spring Expression Language]
|
||||
expression evaluation.
|
||||
|
||||
| `spring.getenv.ignore`
|
||||
| Instructs Spring to ignore operating system environment variables if a Spring
|
||||
`Environment` property -- for example, a placeholder in a configuration String -- isn't
|
||||
@@ -97,25 +92,11 @@ the repeated JNDI lookup overhead. See
|
||||
{spring-framework-api}++/jndi/JndiLocatorDelegate.html#IGNORE_JNDI_PROPERTY_NAME++[`JndiLocatorDelegate`]
|
||||
for details.
|
||||
|
||||
| `spring.locking.strict`
|
||||
| Instructs Spring to enforce strict locking during bean creation, rather than the mix of
|
||||
strict and lenient locking that 6.2 applies by default. See
|
||||
{spring-framework-api}++/beans/factory/support/DefaultListableBeanFactory.html#STRICT_LOCKING_PROPERTY_NAME++[`DefaultListableBeanFactory`]
|
||||
for details.
|
||||
|
||||
| `spring.objenesis.ignore`
|
||||
| Instructs Spring to ignore Objenesis, not even attempting to use it. See
|
||||
{spring-framework-api}++/objenesis/SpringObjenesis.html#IGNORE_OBJENESIS_PROPERTY_NAME++[`SpringObjenesis`]
|
||||
for details.
|
||||
|
||||
| `spring.placeholder.escapeCharacter.default`
|
||||
| The default escape character for property placeholder support. If not set, `'\'` will
|
||||
be used. Can be set to a custom escape character or an empty string to disable support
|
||||
for an escape character. The default escape character be explicitly overridden in
|
||||
`PropertySourcesPlaceholderConfigurer` and subclasses of `AbstractPropertyResolver`. See
|
||||
{spring-framework-api}++/core/env/AbstractPropertyResolver.html#DEFAULT_PLACEHOLDER_ESCAPE_CHARACTER_PROPERTY_NAME++[`AbstractPropertyResolver`]
|
||||
for details.
|
||||
|
||||
| `spring.test.aot.processing.failOnError`
|
||||
| A boolean flag that controls whether errors encountered during AOT processing in the
|
||||
_Spring TestContext Framework_ should result in an exception that fails the overall process.
|
||||
|
||||
@@ -17,3 +17,14 @@ is also provided.
|
||||
|
||||
AOT processing can be used to optimize your application ahead-of-time. It is typically
|
||||
used for native image deployment using GraalVM.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,3 +6,7 @@ The previous chapter described the Spring's support for AOP with @AspectJ and sc
|
||||
aspect definitions. In this chapter, we discuss the lower-level Spring AOP APIs. For common
|
||||
applications, we recommend the use of Spring AOP with AspectJ pointcuts as described in the
|
||||
previous chapter.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
Now we can examine how Spring AOP handles advice.
|
||||
|
||||
|
||||
|
||||
[[aop-api-advice-lifecycle]]
|
||||
== Advice Lifecycles
|
||||
|
||||
@@ -21,12 +22,14 @@ the advice adds state to the proxied object.
|
||||
You can use a mix of shared and per-instance advice in the same AOP proxy.
|
||||
|
||||
|
||||
|
||||
[[aop-api-advice-types]]
|
||||
== Advice Types in Spring
|
||||
|
||||
Spring provides several advice types and is extensible to support
|
||||
arbitrary advice types. This section describes the basic concepts and standard advice types.
|
||||
|
||||
|
||||
[[aop-api-advice-around]]
|
||||
=== Interception Around Advice
|
||||
|
||||
@@ -98,6 +101,7 @@ you are likely to want to run the aspect in another AOP framework. Note that poi
|
||||
are not currently interoperable between frameworks, and the AOP Alliance does not
|
||||
currently define pointcut interfaces.
|
||||
|
||||
|
||||
[[aop-api-advice-before]]
|
||||
=== Before Advice
|
||||
|
||||
@@ -164,6 +168,7 @@ Kotlin::
|
||||
|
||||
TIP: Before advice can be used with any pointcut.
|
||||
|
||||
|
||||
[[aop-api-advice-throws]]
|
||||
=== Throws Advice
|
||||
|
||||
@@ -292,6 +297,7 @@ exception that is incompatible with the target method's signature!_
|
||||
|
||||
TIP: Throws advice can be used with any pointcut.
|
||||
|
||||
|
||||
[[aop-api-advice-after-returning]]
|
||||
=== After Returning Advice
|
||||
|
||||
@@ -355,6 +361,7 @@ thrown up the interceptor chain instead of the return value.
|
||||
|
||||
TIP: After returning advice can be used with any pointcut.
|
||||
|
||||
|
||||
[[aop-api-advice-introduction]]
|
||||
=== Introduction Advice
|
||||
|
||||
@@ -494,6 +501,7 @@ Java::
|
||||
}
|
||||
return super.invoke(invocation);
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -523,6 +531,7 @@ Kotlin::
|
||||
}
|
||||
return super.invoke(invocation)
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
======
|
||||
@@ -573,3 +582,8 @@ We can apply this advisor programmatically by using the `Advised.addAdvisor()` m
|
||||
(the recommended way) in XML configuration, as any other advisor. All proxy creation
|
||||
choices discussed below, including "`auto proxy creators,`" correctly handle introductions
|
||||
and stateful mixins.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -142,3 +142,7 @@ case, the `Advised` `isFrozen()` method returns `true`, and any attempts to modi
|
||||
advice through addition or removal results in an `AopConfigException`. The ability
|
||||
to freeze the state of an advised object is useful in some cases (for example, to
|
||||
prevent calling code removing a security interceptor).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -14,3 +14,7 @@ It is possible to mix advisor and advice types in Spring in the same AOP proxy.
|
||||
example, you could use an interception around advice, throws advice, and before advice in
|
||||
one proxy configuration. Spring automatically creates the necessary interceptor
|
||||
chain.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -19,12 +19,14 @@ There are two ways to do this:
|
||||
auto-proxy creation driven by source-level metadata attributes.
|
||||
|
||||
|
||||
|
||||
[[aop-autoproxy-choices]]
|
||||
== Auto-proxy Bean Definitions
|
||||
|
||||
This section covers the auto-proxy creators provided by the
|
||||
`org.springframework.aop.framework.autoproxy` package.
|
||||
|
||||
|
||||
[[aop-api-autoproxy]]
|
||||
=== `BeanNameAutoProxyCreator`
|
||||
|
||||
@@ -59,6 +61,7 @@ automatically created by the `BeanNameAutoProxyCreator`. The same advice is appl
|
||||
to all matching beans. Note that, if advisors are used (rather than the interceptor in
|
||||
the preceding example), the pointcuts may apply differently to different beans.
|
||||
|
||||
|
||||
[[aop-api-autoproxy-default]]
|
||||
=== `DefaultAdvisorAutoProxyCreator`
|
||||
|
||||
@@ -122,3 +125,7 @@ differently configured, AdvisorAutoProxyCreators in the same factory) and orderi
|
||||
Advisors can implement the `org.springframework.core.Ordered` interface to ensure
|
||||
correct ordering if this is an issue. The `TransactionAttributeSourceAdvisor` used in the
|
||||
preceding example has a configurable order value. The default setting is unordered.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -65,3 +65,7 @@ that, if you have a (parent) bean definition that you intend to use only as a te
|
||||
and this definition specifies a class, you must make sure to set the `abstract`
|
||||
attribute to `true`. Otherwise, the application context actually tries to
|
||||
pre-instantiate it.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ the pointcuts, any advice that applies, and their ordering. However, there are s
|
||||
options that are preferable if you do not need such control.
|
||||
|
||||
|
||||
|
||||
[[aop-pfb-1]]
|
||||
== Basics
|
||||
|
||||
@@ -31,6 +32,7 @@ application objects (besides the target, which should be available in any AOP
|
||||
framework), benefiting from all the pluggability provided by Dependency Injection.
|
||||
|
||||
|
||||
|
||||
[[aop-pfb-2]]
|
||||
== JavaBean Properties
|
||||
|
||||
@@ -85,6 +87,7 @@ to be applied. You can find an example of using this feature in xref:core/aop-ap
|
||||
`false`.
|
||||
|
||||
|
||||
|
||||
[[aop-pfb-proxy-types]]
|
||||
== JDK- and CGLIB-based proxies
|
||||
|
||||
@@ -134,6 +137,7 @@ interface that the target class implements to the `proxyInterfaces` property. Ho
|
||||
it is significantly less work and less prone to typographical errors.
|
||||
|
||||
|
||||
|
||||
[[aop-api-proxying-intf]]
|
||||
== Proxying Interfaces
|
||||
|
||||
@@ -259,6 +263,7 @@ However, there are times when being able to obtain the un-advised target from th
|
||||
factory might actually be an advantage (for example, in certain test scenarios).
|
||||
|
||||
|
||||
|
||||
[[aop-api-proxying-class]]
|
||||
== Proxying Classes
|
||||
|
||||
@@ -297,6 +302,7 @@ There is little performance difference between CGLIB proxies and dynamic proxies
|
||||
Performance should not be a decisive consideration in this case.
|
||||
|
||||
|
||||
|
||||
[[aop-global-advisors]]
|
||||
== Using "`Global`" Advisors
|
||||
|
||||
@@ -319,3 +325,7 @@ two global advisors:
|
||||
<bean id="global_debug" class="org.springframework.aop.interceptor.DebugInterceptor"/>
|
||||
<bean id="global_performance" class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor"/>
|
||||
----
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
This section describes how Spring handles the crucial pointcut concept.
|
||||
|
||||
|
||||
|
||||
[[aop-api-concepts]]
|
||||
== Concepts
|
||||
|
||||
@@ -68,6 +69,7 @@ TIP: If possible, try to make pointcuts static, allowing the AOP framework to ca
|
||||
results of pointcut evaluation when an AOP proxy is created.
|
||||
|
||||
|
||||
|
||||
[[aop-api-pointcut-ops]]
|
||||
== Operations on Pointcuts
|
||||
|
||||
@@ -82,6 +84,7 @@ You can compose pointcuts by using the static methods in the
|
||||
expressions is usually a simpler approach.
|
||||
|
||||
|
||||
|
||||
[[aop-api-pointcuts-aspectj]]
|
||||
== AspectJ Expression Pointcuts
|
||||
|
||||
@@ -92,12 +95,14 @@ uses an AspectJ-supplied library to parse an AspectJ pointcut expression string.
|
||||
See the xref:core/aop.adoc[previous chapter] for a discussion of supported AspectJ pointcut primitives.
|
||||
|
||||
|
||||
|
||||
[[aop-api-pointcuts-impls]]
|
||||
== Convenience Pointcut Implementations
|
||||
|
||||
Spring provides several convenient pointcut implementations. You can use some of them
|
||||
directly; others are intended to be subclassed in application-specific pointcuts.
|
||||
|
||||
|
||||
[[aop-api-pointcuts-static]]
|
||||
=== Static Pointcuts
|
||||
|
||||
@@ -141,6 +146,7 @@ You can use `RegexpMethodPointcutAdvisor` with any `Advice` type.
|
||||
An important type of static pointcut is a metadata-driven pointcut. This uses the
|
||||
values of metadata attributes (typically, source-level metadata).
|
||||
|
||||
|
||||
[[aop-api-pointcuts-dynamic]]
|
||||
=== Dynamic pointcuts
|
||||
|
||||
@@ -166,6 +172,7 @@ other dynamic pointcuts. In Java 1.4, the cost is about five times that of other
|
||||
pointcuts.
|
||||
|
||||
|
||||
|
||||
[[aop-api-pointcuts-superclasses]]
|
||||
== Pointcut Superclasses
|
||||
|
||||
@@ -207,6 +214,7 @@ There are also superclasses for dynamic pointcuts.
|
||||
You can use custom pointcuts with any advice type.
|
||||
|
||||
|
||||
|
||||
[[aop-api-pointcuts-custom]]
|
||||
== Custom Pointcuts
|
||||
|
||||
@@ -217,3 +225,7 @@ expression language, if you can.
|
||||
|
||||
NOTE: Later versions of Spring may offer support for "`semantic pointcuts`" as offered by JAC --
|
||||
for example, "`all methods that change instance variables in the target object.`"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ rather than a singleton bean definition. This allows Spring to create a new targ
|
||||
instance when required.
|
||||
|
||||
|
||||
|
||||
[[aop-ts-swap]]
|
||||
== Hot-swappable Target Sources
|
||||
|
||||
@@ -76,6 +77,7 @@ use a `TargetSource`), any `TargetSource` can be used in conjunction with
|
||||
arbitrary advice.
|
||||
|
||||
|
||||
|
||||
[[aop-ts-pool]]
|
||||
== Pooling Target Sources
|
||||
|
||||
@@ -173,6 +175,7 @@ Simpler pooling is available by using auto-proxying. You can set the `TargetSour
|
||||
used by any auto-proxy creator.
|
||||
|
||||
|
||||
|
||||
[[aop-ts-prototype]]
|
||||
== Prototype Target Sources
|
||||
|
||||
@@ -197,6 +200,7 @@ The only property is the name of the target bean. Inheritance is used in the
|
||||
source, the target bean must be a prototype bean definition.
|
||||
|
||||
|
||||
|
||||
[[aop-ts-threadlocal]]
|
||||
== `ThreadLocal` Target Sources
|
||||
|
||||
@@ -222,3 +226,7 @@ always remember to correctly set and unset (where the latter involves a call to
|
||||
any case, since not unsetting it might result in problematic behavior. Spring's
|
||||
`ThreadLocal` support does this for you and should always be considered in favor of using
|
||||
`ThreadLocal` instances without other proper handling code.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -32,3 +32,7 @@ AOP is used in the Spring Framework to:
|
||||
NOTE: If you are interested only in generic declarative services or other pre-packaged
|
||||
declarative middleware services such as pooling, you do not need to work directly with
|
||||
Spring AOP, and can skip most of this chapter.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -53,3 +53,7 @@ Kotlin::
|
||||
======
|
||||
|
||||
See the {spring-framework-api}/aop/aspectj/annotation/AspectJProxyFactory.html[javadoc] for more information.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -11,3 +11,6 @@ there is no dependency on the AspectJ compiler or weaver.
|
||||
|
||||
NOTE: Using the AspectJ compiler and weaver enables use of the full AspectJ language and
|
||||
is discussed in xref:core/aop/using-aspectj.adoc[Using AspectJ with Spring Applications].
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -937,3 +937,5 @@ reflection for javac-compiled classes). Consider collapsing such advice methods
|
||||
advice method per join point in each `@Aspect` class or refactor the pieces of advice into
|
||||
separate `@Aspect` classes that you can order at the aspect level via `Ordered` or `@Order`.
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -32,3 +32,6 @@ stereotype annotation that qualifies, as per the rules of Spring's component sca
|
||||
NOTE: In Spring AOP, aspects themselves cannot be the targets of advice from other
|
||||
aspects. The `@Aspect` annotation on a class marks it as an aspect and, hence, excludes
|
||||
it from auto-proxying.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -18,8 +18,7 @@ call `proceed` multiple times. The following listing shows the basic aspect impl
|
||||
|
||||
include-code::./ConcurrentOperationExecutor[tag=snippet,indent=0]
|
||||
|
||||
`@Around("com.xyz.CommonPointcuts.businessService()")` references the `businessService` named pointcut defined in
|
||||
xref:core/aop/ataspectj/pointcuts.adoc#aop-common-pointcuts[Sharing Named Pointcut Definitions].
|
||||
`@Around("com.xyz.CommonPointcuts.businessService()")` references the `businessService` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-common-pointcuts[Sharing Named Pointcut Definitions].
|
||||
|
||||
Note that the aspect implements the `Ordered` interface so that we can set the precedence of
|
||||
the aspect higher than the transaction advice (we want a fresh transaction each time we
|
||||
|
||||
@@ -60,3 +60,6 @@ Programming Guide for more information on `per` clauses.
|
||||
|
||||
The `pertarget` instantiation model works in exactly the same way as `perthis`, but it
|
||||
creates one aspect instance for each unique target object at matched join points.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -75,3 +75,5 @@ Kotlin::
|
||||
val usageTracked = context.getBean<UsageTracked>("myService")
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ Note that pointcut definitions are generally matched against any intercepted met
|
||||
If a pointcut is strictly meant to be public-only, even in a CGLIB proxy scenario with
|
||||
potential non-public interactions through proxies, it needs to be defined accordingly.
|
||||
|
||||
If your interception needs to include method calls or even constructors within the target
|
||||
If your interception needs include method calls or even constructors within the target
|
||||
class, consider the use of Spring-driven xref:core/aop/using-aspectj.adoc#aop-aj-ltw[native AspectJ weaving] instead
|
||||
of Spring's proxy-based AOP framework. This constitutes a different mode of AOP usage
|
||||
with different characteristics, so be sure to make yourself familiar with weaving
|
||||
@@ -581,3 +581,6 @@ performance (time and memory used), due to extra processing and analysis. Scopin
|
||||
designators are very fast to match, and using them means AspectJ can very quickly
|
||||
dismiss groups of join points that should not be further processed. A good
|
||||
pointcut should always include one if possible.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ decisions are influenced by a number of factors including application requiremen
|
||||
development tools, and team familiarity with AOP.
|
||||
|
||||
|
||||
|
||||
[[aop-spring-or-aspectj]]
|
||||
== Spring AOP or Full AspectJ?
|
||||
|
||||
@@ -30,6 +31,7 @@ the @AspectJ style, sticking with regular Java compilation in your IDE, and addi
|
||||
an aspect weaving phase to your build script.
|
||||
|
||||
|
||||
|
||||
[[aop-ataspectj-or-xml]]
|
||||
== @AspectJ or XML for Spring AOP?
|
||||
|
||||
@@ -105,3 +107,7 @@ Spring AOP and by AspectJ. So, if you later decide you need the capabilities of
|
||||
to implement additional requirements, you can easily migrate to a classic AspectJ setup.
|
||||
In general, the Spring team prefers the @AspectJ style for custom aspects beyond simple
|
||||
configuration of enterprise services.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -73,3 +73,7 @@ it from older technologies offering only interception. Pointcuts enable advice t
|
||||
targeted independently of the object-oriented hierarchy. For example, you can apply an
|
||||
around advice providing declarative transaction management to a set of methods that span
|
||||
multiple objects (such as all business operations in the service layer).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -14,5 +14,9 @@ need to advise a method that is not declared on an interface or where you need t
|
||||
pass a proxied object to a method as a concrete type.
|
||||
|
||||
It is important to grasp the fact that Spring AOP is proxy-based. See
|
||||
xref:core/aop/proxying.adoc#aop-understanding-aop-proxies[Understanding AOP Proxies]
|
||||
for a thorough examination of exactly what this implementation detail actually means.
|
||||
xref:core/aop/proxying.adoc#aop-understanding-aop-proxies[Understanding AOP Proxies] for a thorough examination of exactly what this
|
||||
implementation detail actually means.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -52,6 +52,10 @@ configuration-style approach. The fact that this chapter chooses to introduce th
|
||||
@AspectJ-style approach first should not be taken as an indication that the Spring team
|
||||
favors the @AspectJ annotation-style approach over the Spring XML configuration-style.
|
||||
|
||||
See xref:core/aop/choosing.adoc[Choosing which AOP Declaration Style to Use] for a more
|
||||
complete discussion of the advantages and disadvantages of each style.
|
||||
See xref:core/aop/choosing.adoc[Choosing which AOP Declaration Style to Use] for a more complete discussion of the advantages and disadvantages of
|
||||
each style.
|
||||
====
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,3 +6,7 @@ It is perfectly possible to mix @AspectJ style aspects by using the auto-proxyin
|
||||
schema-defined `<aop:aspect>` aspects, `<aop:advisor>` declared advisors, and even proxies
|
||||
and interceptors in other styles in the same configuration. All of these are implemented
|
||||
by using the same underlying support mechanism and can co-exist without any difficulty.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ proxies _for all three of them_.
|
||||
====
|
||||
|
||||
|
||||
|
||||
[[aop-understanding-aop-proxies]]
|
||||
== Understanding AOP Proxies
|
||||
|
||||
@@ -290,3 +291,4 @@ Kotlin::
|
||||
|
||||
NOTE: AspectJ compile-time weaving and load-time weaving do not have this self-invocation
|
||||
issue because they apply advice within the bytecode instead of via a proxy.
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ use either only the `<aop:config>` style or only the `AutoProxyCreator` style an
|
||||
never mix them.
|
||||
|
||||
|
||||
|
||||
[[aop-schema-declaring-an-aspect]]
|
||||
== Declaring an Aspect
|
||||
|
||||
@@ -53,6 +54,7 @@ The bean that backs the aspect (`aBean` in this case) can of course be configure
|
||||
dependency injected just like any other Spring bean.
|
||||
|
||||
|
||||
|
||||
[[aop-schema-pointcuts]]
|
||||
== Declaring a Pointcut
|
||||
|
||||
@@ -175,7 +177,9 @@ follows:
|
||||
|
||||
Note that pointcuts defined in this way are referred to by their XML `id` and cannot be
|
||||
used as named pointcuts to form composite pointcuts. The named pointcut support in the
|
||||
schema-based definition style is thus more limited than that offered by the @AspectJ style.
|
||||
schema-based definition style is thus more limited than that offered by the @AspectJ
|
||||
style.
|
||||
|
||||
|
||||
|
||||
[[aop-schema-advice]]
|
||||
@@ -184,6 +188,7 @@ schema-based definition style is thus more limited than that offered by the @Asp
|
||||
The schema-based AOP support uses the same five kinds of advice as the @AspectJ style, and they have
|
||||
exactly the same semantics.
|
||||
|
||||
|
||||
[[aop-schema-advice-before]]
|
||||
=== Before Advice
|
||||
|
||||
@@ -232,6 +237,7 @@ that contains the advice. Before a data access operation is performed (a method
|
||||
join point matched by the pointcut expression), the `doAccessCheck` method on the aspect
|
||||
bean is invoked.
|
||||
|
||||
|
||||
[[aop-schema-advice-after-returning]]
|
||||
=== After Returning Advice
|
||||
|
||||
@@ -289,6 +295,7 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
[[aop-schema-advice-after-throwing]]
|
||||
=== After Throwing Advice
|
||||
|
||||
@@ -346,6 +353,7 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
[[aop-schema-advice-after-finally]]
|
||||
=== After (Finally) Advice
|
||||
|
||||
@@ -364,6 +372,7 @@ You can declare it by using the `after` element, as the following example shows:
|
||||
</aop:aspect>
|
||||
----
|
||||
|
||||
|
||||
[[aop-schema-advice-around]]
|
||||
=== Around Advice
|
||||
|
||||
@@ -435,18 +444,17 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
[[aop-schema-params]]
|
||||
=== Advice Parameters
|
||||
|
||||
The schema-based declaration style supports fully typed advice in the same way as
|
||||
described for the @AspectJ support -- by matching pointcut parameters by name against
|
||||
advice method parameters. See
|
||||
xref:core/aop/ataspectj/advice.adoc#aop-ataspectj-advice-params[Advice Parameters] for details.
|
||||
If you wish to explicitly specify argument names for the advice methods (not relying on the
|
||||
advice method parameters. See xref:core/aop/ataspectj/advice.adoc#aop-ataspectj-advice-params[Advice Parameters] for details. If you wish
|
||||
to explicitly specify argument names for the advice methods (not relying on the
|
||||
detection strategies previously described), you can do so by using the `arg-names`
|
||||
attribute of the advice element, which is treated in the same manner as the `argNames`
|
||||
attribute in an advice annotation (as described in
|
||||
xref:core/aop/ataspectj/advice.adoc#aop-ataspectj-advice-params-names[Determining Argument Names]).
|
||||
attribute in an advice annotation (as described in xref:core/aop/ataspectj/advice.adoc#aop-ataspectj-advice-params-names[Determining Argument Names]).
|
||||
The following example shows how to specify an argument name in XML:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
@@ -456,8 +464,7 @@ The following example shows how to specify an argument name in XML:
|
||||
method="audit"
|
||||
arg-names="auditable" />
|
||||
----
|
||||
<1> References the `publicMethod` named pointcut defined in
|
||||
xref:core/aop/ataspectj/pointcuts.adoc#aop-pointcuts-combining[Combining Pointcut Expressions].
|
||||
<1> References the `publicMethod` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-pointcuts-combining[Combining Pointcut Expressions].
|
||||
|
||||
The `arg-names` attribute accepts a comma-delimited list of parameter names.
|
||||
|
||||
@@ -638,15 +645,15 @@ ms % Task name
|
||||
00000 ? execution(getFoo)
|
||||
----
|
||||
|
||||
|
||||
[[aop-ordering]]
|
||||
=== Advice Ordering
|
||||
|
||||
When multiple pieces of advice need to run at the same join point (executing method)
|
||||
the ordering rules are as described in
|
||||
xref:core/aop/ataspectj/advice.adoc#aop-ataspectj-advice-ordering[Advice Ordering]. The
|
||||
precedence between aspects is determined via the `order` attribute in the `<aop:aspect>`
|
||||
element or by either adding the `@Order` annotation to the bean that backs the aspect
|
||||
or by having the bean implement the `Ordered` interface.
|
||||
the ordering rules are as described in xref:core/aop/ataspectj/advice.adoc#aop-ataspectj-advice-ordering[Advice Ordering]. The precedence
|
||||
between aspects is determined via the `order` attribute in the `<aop:aspect>` element or
|
||||
by either adding the `@Order` annotation to the bean that backs the aspect or by having
|
||||
the bean implement the `Ordered` interface.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
@@ -669,6 +676,7 @@ at the aspect level.
|
||||
====
|
||||
|
||||
|
||||
|
||||
[[aop-schema-introductions]]
|
||||
== Introductions
|
||||
|
||||
@@ -748,6 +756,7 @@ Kotlin::
|
||||
======
|
||||
|
||||
|
||||
|
||||
[[aop-schema-instantiation-models]]
|
||||
== Aspect Instantiation Models
|
||||
|
||||
@@ -755,6 +764,7 @@ The only supported instantiation model for schema-defined aspects is the singlet
|
||||
model. Other instantiation models may be supported in future releases.
|
||||
|
||||
|
||||
|
||||
[[aop-schema-advisors]]
|
||||
== Advisors
|
||||
|
||||
@@ -762,8 +772,7 @@ The concept of "advisors" comes from the AOP support defined in Spring
|
||||
and does not have a direct equivalent in AspectJ. An advisor is like a small
|
||||
self-contained aspect that has a single piece of advice. The advice itself is
|
||||
represented by a bean and must implement one of the advice interfaces described in
|
||||
xref:core/aop-api/advice.adoc#aop-api-advice-types[Advice Types in Spring].
|
||||
Advisors can take advantage of AspectJ pointcut expressions.
|
||||
xref:core/aop-api/advice.adoc#aop-api-advice-types[Advice Types in Spring]. Advisors can take advantage of AspectJ pointcut expressions.
|
||||
|
||||
Spring supports the advisor concept with the `<aop:advisor>` element. You most
|
||||
commonly see it used in conjunction with transactional advice, which also has its own
|
||||
@@ -796,6 +805,7 @@ To define the precedence of an advisor so that the advice can participate in ord
|
||||
use the `order` attribute to define the `Ordered` value of the advisor.
|
||||
|
||||
|
||||
|
||||
[[aop-schema-example]]
|
||||
== An AOP Schema Example
|
||||
|
||||
@@ -971,3 +981,7 @@ pointcut expression so that only `@Idempotent` operations match, as follows:
|
||||
expression="execution(* com.xyz.service.*.*(..)) and
|
||||
@annotation(com.xyz.service.Idempotent)"/>
|
||||
----
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,14 +8,12 @@ alone.
|
||||
|
||||
Spring ships with a small AspectJ aspect library, which is available stand-alone in your
|
||||
distribution as `spring-aspects.jar`. You need to add this to your classpath in order
|
||||
to use the aspects in it.
|
||||
xref:core/aop/using-aspectj.adoc#aop-atconfigurable[Using AspectJ to Dependency Inject Domain Objects with Spring]
|
||||
and xref:core/aop/using-aspectj.adoc#aop-ajlib-other[Other Spring aspects for AspectJ]
|
||||
discuss the content of this library and how you can use it.
|
||||
xref:core/aop/using-aspectj.adoc#aop-aj-configure[Configuring AspectJ Aspects by Using Spring IoC]
|
||||
discusses how to dependency inject AspectJ aspects that are woven using the AspectJ compiler. Finally,
|
||||
xref:core/aop/using-aspectj.adoc#aop-aj-ltw[Load-time Weaving with AspectJ in the Spring Framework]
|
||||
provides an introduction to load-time weaving for Spring applications that use AspectJ.
|
||||
to use the aspects in it. xref:core/aop/using-aspectj.adoc#aop-atconfigurable[Using AspectJ to Dependency Inject Domain Objects with Spring] and xref:core/aop/using-aspectj.adoc#aop-ajlib-other[Other Spring aspects for AspectJ] discuss the
|
||||
content of this library and how you can use it. xref:core/aop/using-aspectj.adoc#aop-aj-configure[Configuring AspectJ Aspects by Using Spring IoC] discusses how to
|
||||
dependency inject AspectJ aspects that are woven using the AspectJ compiler. Finally,
|
||||
xref:core/aop/using-aspectj.adoc#aop-aj-ltw[Load-time Weaving with AspectJ in the Spring Framework] provides an introduction to load-time weaving for Spring applications
|
||||
that use AspectJ.
|
||||
|
||||
|
||||
|
||||
[[aop-atconfigurable]]
|
||||
@@ -208,6 +206,7 @@ not use `@Configurable` on bean classes that are registered as regular Spring be
|
||||
with the container. Doing so results in double initialization, once through the
|
||||
container and once through the aspect.
|
||||
|
||||
|
||||
[[aop-configurable-testing]]
|
||||
=== Unit Testing `@Configurable` Objects
|
||||
|
||||
@@ -220,6 +219,7 @@ you can still unit test outside of the container as normal, but you see a warnin
|
||||
message each time that you construct a `@Configurable` object indicating that it has
|
||||
not been configured by Spring.
|
||||
|
||||
|
||||
[[aop-configurable-container]]
|
||||
=== Working with Multiple Application Contexts
|
||||
|
||||
@@ -249,6 +249,7 @@ is added only to the container-wide classpath (and hence loaded by the shared pa
|
||||
not what you want).
|
||||
|
||||
|
||||
|
||||
[[aop-ajlib-other]]
|
||||
== Other Spring aspects for AspectJ
|
||||
|
||||
@@ -301,6 +302,7 @@ fully qualified class names:
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[aop-aj-configure]]
|
||||
== Configuring AspectJ Aspects by Using Spring IoC
|
||||
|
||||
@@ -355,6 +357,7 @@ results in the creation of Spring AOP proxies. The @AspectJ style of aspect
|
||||
declaration is being used here, but the AspectJ runtime is not involved.
|
||||
|
||||
|
||||
|
||||
[[aop-aj-ltw]]
|
||||
== Load-time Weaving with AspectJ in the Spring Framework
|
||||
|
||||
@@ -388,6 +391,7 @@ LTW that uses Spring, followed by detailed specifics about elements introduced i
|
||||
example. For a complete example, see the
|
||||
{petclinic-github-org}/spring-framework-petclinic[Petclinic sample application based on Spring Framework].
|
||||
|
||||
|
||||
[[aop-aj-ltw-first-example]]
|
||||
=== A First Example
|
||||
|
||||
@@ -673,6 +677,7 @@ nice example of a development-time aspect that developers can use during develop
|
||||
and then easily exclude from builds of the application being deployed
|
||||
into UAT or production.
|
||||
|
||||
|
||||
[[aop-aj-ltw-the-aspects]]
|
||||
=== Aspects
|
||||
|
||||
@@ -681,6 +686,7 @@ either the AspectJ language itself, or you can write your aspects in the @Aspect
|
||||
Your aspects are then both valid AspectJ and Spring AOP aspects.
|
||||
Furthermore, the compiled aspect classes need to be available on the classpath.
|
||||
|
||||
|
||||
[[aop-aj-ltw-aop_dot_xml]]
|
||||
=== `META-INF/aop.xml`
|
||||
|
||||
@@ -710,6 +716,7 @@ The structure and contents of this file is detailed in the LTW part of the
|
||||
{aspectj-docs-devguide}/ltw-configuration.html[AspectJ reference
|
||||
documentation]. Because the `aop.xml` file is 100% AspectJ, we do not describe it further here.
|
||||
|
||||
|
||||
[[aop-aj-ltw-libraries]]
|
||||
=== Required libraries (JARS)
|
||||
|
||||
@@ -724,6 +731,7 @@ If you use the xref:core/aop/using-aspectj.adoc#aop-aj-ltw-environments-generic[
|
||||
|
||||
* `spring-instrument.jar`
|
||||
|
||||
|
||||
[[aop-aj-ltw-spring]]
|
||||
=== Spring Configuration
|
||||
|
||||
@@ -823,6 +831,7 @@ possible values:
|
||||
then AspectJ weaving is on. Otherwise, it is off. This is the default value.
|
||||
|===
|
||||
|
||||
|
||||
[[aop-aj-ltw-environments]]
|
||||
=== Environment-specific Configuration
|
||||
|
||||
@@ -871,3 +880,7 @@ Note that this requires modification of the JVM launch script, which may prevent
|
||||
from using this in application server environments (depending on your server and your
|
||||
operation policies). That said, for one-app-per-JVM deployments such as standalone
|
||||
Spring Boot applications, you typically control the entire JVM setup in any case.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ This chapter covers Spring's Ahead of Time (AOT) optimizations.
|
||||
|
||||
For AOT support specific to integration tests, see xref:testing/testcontext-framework/aot.adoc[Ahead of Time Support for Tests].
|
||||
|
||||
|
||||
[[aot.introduction]]
|
||||
== Introduction to Ahead of Time Optimizations
|
||||
|
||||
@@ -18,9 +17,9 @@ Applying such optimizations early implies the following restrictions:
|
||||
* The beans defined in your application cannot change at runtime, meaning:
|
||||
** `@Profile`, in particular profile-specific configuration, needs to be chosen at build time and is automatically enabled at runtime when AOT is enabled.
|
||||
** `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.
|
||||
* Bean definitions with instance suppliers (lambdas or method references) cannot be transformed ahead-of-time.
|
||||
* Beans registered as singletons (using `registerSingleton`, typically from
|
||||
`ConfigurableListableBeanFactory`) cannot be transformed ahead of time either.
|
||||
`ConfigurableListableBeanFactory`) cannot be transformed ahead-of-time either.
|
||||
* As we cannot rely on the instance, make sure that the bean type is as precise as
|
||||
possible.
|
||||
|
||||
@@ -36,7 +35,6 @@ A Spring AOT processed application typically generates:
|
||||
NOTE: At the moment, AOT is focused on allowing Spring applications to be deployed as native images using GraalVM.
|
||||
We intend to support more JVM-based use cases in future generations.
|
||||
|
||||
|
||||
[[aot.basics]]
|
||||
== AOT Engine Overview
|
||||
|
||||
@@ -53,7 +51,6 @@ The `RuntimeHints` instance can also be used to generate the relevant GraalVM na
|
||||
|
||||
Those steps are covered in greater detail in the sections below.
|
||||
|
||||
|
||||
[[aot.refresh]]
|
||||
== Refresh for AOT Processing
|
||||
|
||||
@@ -91,7 +88,6 @@ This makes sure to create any proxy that will be required at runtime.
|
||||
|
||||
Once this part completes, the `BeanFactory` contains the bean definitions that are necessary for the application to run. It does not trigger bean instantiation but allows the AOT engine to inspect the beans that will be created at runtime.
|
||||
|
||||
|
||||
[[aot.bean-factory-initialization-contributions]]
|
||||
== Bean Factory Initialization AOT Contributions
|
||||
|
||||
@@ -110,10 +106,11 @@ Consequently, such a bean is automatically excluded from the AOT-optimized conte
|
||||
[NOTE]
|
||||
====
|
||||
If a bean implements the `BeanFactoryInitializationAotProcessor` interface, the bean and **all** of its dependencies will be initialized during AOT processing.
|
||||
We generally recommend that this interface is only implemented by infrastructure beans, such as a `BeanFactoryPostProcessor`, which have limited dependencies and are already initialized early in the bean factory lifecycle.
|
||||
We generally recommend that this interface is only implemented by infrastructure beans such as `BeanFactoryPostProcessor` which have limited dependencies and are already initialized early in the bean factory lifecycle.
|
||||
If such a bean is registered using an `@Bean` factory method, ensure the method is `static` so that its enclosing `@Configuration` class does not have to be initialized.
|
||||
====
|
||||
|
||||
|
||||
[[aot.bean-registration-contributions]]
|
||||
=== Bean Registration AOT Contributions
|
||||
|
||||
@@ -130,7 +127,7 @@ Typically used when the bean definition needs to be tuned for specific features
|
||||
[NOTE]
|
||||
====
|
||||
If a bean implements the `BeanRegistrationAotProcessor` interface, the bean and **all** of its dependencies will be initialized during AOT processing.
|
||||
We generally recommend that this interface is only implemented by infrastructure beans, such as a `BeanFactoryPostProcessor`, which have limited dependencies and are already initialized early in the bean factory lifecycle.
|
||||
We generally recommend that this interface is only implemented by infrastructure beans such as `BeanFactoryPostProcessor` which have limited dependencies and are already initialized early in the bean factory lifecycle.
|
||||
If such a bean is registered using an `@Bean` factory method, ensure the method is `static` so that its enclosing `@Configuration` class does not have to be initialized.
|
||||
====
|
||||
|
||||
@@ -222,23 +219,21 @@ NOTE: The exact code generated may differ depending on the exact nature of your
|
||||
TIP: Each generated class is annotated with `org.springframework.aot.generate.Generated` to
|
||||
identify them if they need to be excluded, for instance by static analysis tools.
|
||||
|
||||
The generated code above creates bean definitions equivalent to the `@Configuration` class, but in a direct way and without the use of reflection at all if possible.
|
||||
The generated code above creates bean definitions equivalent to the `@Configuration` class, but in a direct way and without the use of reflection if at all possible.
|
||||
There is a bean definition for `dataSourceConfiguration` and one for `dataSourceBean`.
|
||||
When a `datasource` instance is required, a `BeanInstanceSupplier` is called.
|
||||
This supplier invokes the `dataSource()` method on the `dataSourceConfiguration` bean.
|
||||
|
||||
|
||||
[[aot.running]]
|
||||
== Running with AOT Optimizations
|
||||
|
||||
AOT is a mandatory step to transform a Spring application to a native executable, so it
|
||||
is automatically enabled when running within a native image. However it is also possible to use AOT optimizations
|
||||
is automatically enabled when running in this mode. It is possible to use those optimizations
|
||||
on the JVM by setting the `spring.aot.enabled` System property to `true`.
|
||||
|
||||
NOTE: When AOT optimizations are included, some decisions that have been made at build time
|
||||
are hard coded in the application setup. For instance, profiles that have been enabled at
|
||||
build time are automatically enabled at runtime as well.
|
||||
|
||||
NOTE: When AOT optimizations are included, some decisions that have been taken at build-time
|
||||
are hard-coded in the application setup. For instance, profiles that have been enabled at
|
||||
build-time are automatically enabled at runtime as well.
|
||||
|
||||
[[aot.bestpractices]]
|
||||
== Best Practices
|
||||
@@ -276,7 +271,7 @@ build time.
|
||||
While your application may interact with an interface that a bean implements, it is still very important to declare the most precise type.
|
||||
The AOT engine performs additional checks on the bean type, such as detecting the presence of `@Autowired` members or lifecycle callback methods.
|
||||
|
||||
For `@Configuration` classes, make sure that the return type of an `@Bean` factory method is as precise as possible.
|
||||
For `@Configuration` classes, make sure that the return type of the factory `@Bean` method is as precise as possible.
|
||||
Consider the following example:
|
||||
|
||||
[tabs]
|
||||
@@ -310,11 +305,11 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
In the example above, the declared type for the `myInterface` bean is `MyInterface`.
|
||||
During AOT processing, none of the usual post-processing will take `MyImplementation` into account.
|
||||
For instance, if there is an annotated handler method on `MyImplementation` that the context should register, it will not be detected during AOT processing.
|
||||
In the example above, the declared type for the `myInterface` bean is `MyInterface`.
|
||||
None of the usual post-processing will take `MyImplementation` into account.
|
||||
For instance, if there is an annotated handler method on `MyImplementation` that the context should register, it won’t be detected upfront.
|
||||
|
||||
The example above should therefore be rewritten as follows:
|
||||
The example above should be rewritten as follows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
@@ -353,7 +348,7 @@ If you are registering bean definitions programmatically, consider using `RootBe
|
||||
=== Avoid Multiple Constructors
|
||||
|
||||
The container is able to choose the most appropriate constructor to use based on several candidates.
|
||||
However, relying on that is not a best practice, and flagging the preferred constructor with `@Autowired` if necessary is preferred.
|
||||
However, this is not a best practice and flagging the preferred constructor with `@Autowired` if necessary is preferred.
|
||||
|
||||
In case you are working on a code base that you cannot modify, you can set the {spring-framework-api}/beans/factory/support/AbstractBeanDefinition.html#PREFERRED_CONSTRUCTORS_ATTRIBUTE[`preferredConstructors` attribute] on the related bean definition to indicate which constructor should be used.
|
||||
|
||||
@@ -368,17 +363,17 @@ A good rule of thumb is to keep in mind that bean definitions are an abstraction
|
||||
Rather than using such structures, decomposing to simple types or referring to a bean that is built as such is recommended.
|
||||
|
||||
As a last resort, you can implement your own `org.springframework.aot.generate.ValueCodeGenerator$Delegate`.
|
||||
To use it, register its fully-qualified name in `META-INF/spring/aot.factories` using `org.springframework.aot.generate.ValueCodeGenerator$Delegate` as the key.
|
||||
To use it, register its fully qualified name in `META-INF/spring/aot.factories` using the `Delegate` as the key.
|
||||
|
||||
[[aot.bestpractices.custom-arguments]]
|
||||
=== Avoid Creating Beans with Custom Arguments
|
||||
|
||||
Spring AOT detects what needs to be done to create a bean and translates that into generated code that uses an instance supplier.
|
||||
The container also supports creating a bean with {spring-framework-api}++/beans/factory/BeanFactory.html#getBean(java.lang.String,java.lang.Object...)++[custom arguments] which can lead to several issues with AOT:
|
||||
Spring AOT detects what needs to be done to create a bean and translates that in generated code using an instance supplier.
|
||||
The container also supports creating a bean with {spring-framework-api}++/beans/factory/BeanFactory.html#getBean(java.lang.String,java.lang.Object...)++[custom arguments] that leads to several issues with AOT:
|
||||
|
||||
. The custom arguments require dynamic introspection of a matching constructor or factory method.
|
||||
Those arguments cannot be detected by AOT, so the necessary reflection hints will have to be provided manually.
|
||||
. Bypassing the instance supplier means that all other optimizations after creation are skipped as well.
|
||||
. By-passing the instance supplier means that all other optimizations after creation are skipped as well.
|
||||
For instance, autowiring on fields and methods will be skipped as they are handled in the instance supplier.
|
||||
|
||||
Rather than having prototype-scoped beans created with custom arguments, we recommend a manual factory pattern where a bean is responsible for the creation of the instance.
|
||||
@@ -401,7 +396,7 @@ for further information.
|
||||
=== FactoryBean
|
||||
|
||||
`FactoryBean` should be used with care as it introduces an intermediate layer in terms of bean type resolution that may not be conceptually necessary.
|
||||
As a rule of thumb, if a `FactoryBean` instance does not hold long-term state and is not needed at a later point at runtime, it should be replaced by a regular `@Bean` factory method, possibly with a `FactoryBean` adapter layer on top (for declarative configuration purposes).
|
||||
As a rule of thumb, if the `FactoryBean` instance does not hold long-term state and is not needed at a later point in time at runtime, it should be replaced by a regular factory method, possibly with a `FactoryBean` adapter layer on top (for declarative configuration purposes).
|
||||
|
||||
If your `FactoryBean` implementation does not resolve the object type (i.e. `T`), extra care is necessary.
|
||||
Consider the following example:
|
||||
@@ -460,7 +455,7 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
If a `FactoryBean` bean definition is registered programmatically, make sure to follow these steps:
|
||||
If the `FactoryBean` bean definition is registered programmatically, make sure to follow these steps:
|
||||
|
||||
1. Use `RootBeanDefinition`.
|
||||
2. Set the `beanClass` to the `FactoryBean` class so that AOT knows that it is an intermediate layer.
|
||||
@@ -474,20 +469,20 @@ Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(ClientFactoryBean.class);
|
||||
beanDefinition.setTargetType(ResolvableType.forClassWithGenerics(ClientFactoryBean.class, MyClient.class));
|
||||
// ...
|
||||
registry.registerBeanDefinition("myClient", beanDefinition);
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(ClientFactoryBean.class);
|
||||
beanDefinition.setTargetType(ResolvableType.forClassWithGenerics(ClientFactoryBean.class, MyClient.class));
|
||||
// ...
|
||||
registry.registerBeanDefinition("myClient", beanDefinition);
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
val beanDefinition = RootBeanDefinition(ClientFactoryBean::class.java)
|
||||
beanDefinition.setTargetType(ResolvableType.forClassWithGenerics(ClientFactoryBean::class.java, MyClient::class.java));
|
||||
// ...
|
||||
registry.registerBeanDefinition("myClient", beanDefinition)
|
||||
val beanDefinition = RootBeanDefinition(ClientFactoryBean::class.java)
|
||||
beanDefinition.setTargetType(ResolvableType.forClassWithGenerics(ClientFactoryBean::class.java, MyClient::class.java));
|
||||
// ...
|
||||
registry.registerBeanDefinition("myClient", beanDefinition)
|
||||
----
|
||||
======
|
||||
|
||||
@@ -525,7 +520,7 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
To ensure that entity scanning occurs ahead of time, a `PersistenceManagedTypes` bean must be declared and used by the
|
||||
To make sure the scanning occurs ahead of time, a `PersistenceManagedTypes` bean must be declared and used by the
|
||||
factory bean definition, as shown by the following example:
|
||||
|
||||
[tabs]
|
||||
@@ -569,7 +564,6 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
[[aot.hints]]
|
||||
== Runtime Hints
|
||||
|
||||
@@ -604,38 +598,35 @@ For instance, the return type of a `@Controller` method is inspected, and releva
|
||||
For cases that the core container cannot infer, you can register such hints programmatically.
|
||||
A number of convenient annotations are also provided for common use cases.
|
||||
|
||||
|
||||
[[aot.hints.import-runtime-hints]]
|
||||
=== `@ImportRuntimeHints`
|
||||
|
||||
{spring-framework-api}/aot/hint/RuntimeHintsRegistrar.html[`RuntimeHintsRegistrar`]
|
||||
implementations allow you to get a callback to the `RuntimeHints` instance managed by the
|
||||
AOT engine. Implementations of this interface can be registered using
|
||||
{spring-framework-api}/context/annotation/ImportRuntimeHints.html[`@ImportRuntimeHints`]
|
||||
on any Spring bean or `@Bean` factory method. `RuntimeHintsRegistrar` implementations are
|
||||
detected and invoked at build time.
|
||||
`RuntimeHintsRegistrar` implementations allow you to get a callback to the `RuntimeHints` instance managed by the AOT engine.
|
||||
Implementations of this interface can be registered using `@ImportRuntimeHints` on any Spring bean or `@Bean` factory method.
|
||||
`RuntimeHintsRegistrar` implementations are detected and invoked at build time.
|
||||
|
||||
include-code::./SpellCheckService[]
|
||||
|
||||
If at all possible, `@ImportRuntimeHints` should be used as close as possible to the component that requires the hints.
|
||||
This way, if the component is not contributed to the `BeanFactory`, the hints will not be contributed either.
|
||||
This way, if the component is not contributed to the `BeanFactory`, the hints won't be contributed either.
|
||||
|
||||
It is also possible to register an implementation statically by adding an entry in `META-INF/spring/aot.factories` with a key equal to the fully-qualified name of the `RuntimeHintsRegistrar` interface.
|
||||
|
||||
|
||||
[[aot.hints.reflective]]
|
||||
=== `@Reflective`
|
||||
|
||||
{spring-framework-api}/aot/hint/annotation/Reflective.html[`@Reflective`] provides an idiomatic way to flag the need for reflection on an annotated element.
|
||||
For instance, `@EventListener` is meta-annotated with `@Reflective` since the underlying implementation invokes the annotated method using reflection.
|
||||
|
||||
Out-of-the-box, only Spring beans are considered, but you can opt-in for scanning using
|
||||
{spring-framework-api}/context/annotation/ReflectiveScan.html[`@ReflectiveScan`]. In the
|
||||
example below, all types in the `com.example.app` package and its subpackages are
|
||||
considered:
|
||||
Out-of-the-box, only Spring beans are considered but you can opt-in for scanning using `@ReflectiveScan`.
|
||||
In the example below, all types of the package `com.example.app` and their subpackages are considered:
|
||||
|
||||
include-code::./MyConfiguration[]
|
||||
|
||||
Scanning happens during AOT processing, and the types in the target packages do not need to have a class-level annotation to be considered.
|
||||
This performs a _deep scan_, and the presence of `@Reflective`, either directly or as a meta-annotation, is checked on types, fields, constructors, methods, and enclosed elements.
|
||||
Scanning happens during AOT processing and the types in the target packages do not need to have a class-level annotation to be considered.
|
||||
This performs a "deep scan" and the presence of `@Reflective`, either directly or as a meta-annotation, is checked on types, fields, constructors, methods, and enclosed elements.
|
||||
|
||||
By default, `@Reflective` registers an invocation hint for the annotated element.
|
||||
This can be tuned by specifying a custom `ReflectiveProcessor` implementation via the `@Reflective` annotation.
|
||||
@@ -643,12 +634,13 @@ This can be tuned by specifying a custom `ReflectiveProcessor` implementation vi
|
||||
Library authors can reuse this annotation for their own purposes.
|
||||
An example of such customization is covered in the next section.
|
||||
|
||||
|
||||
[[aot.hints.register-reflection]]
|
||||
=== `@RegisterReflection`
|
||||
|
||||
{spring-framework-api}/aot/hint/annotation/RegisterReflection.html[`@RegisterReflection`] is a specialization of `@Reflective` that provides a declarative way to register reflection for arbitrary types.
|
||||
{spring-framework-api}/aot/hint/annotation/RegisterReflection.html[`@RegisterReflection`] is a specialization of `@Reflective` that provides a declarative way of registering reflection for arbitrary types.
|
||||
|
||||
NOTE: As a specialization of `@Reflective`, `@RegisterReflection` is also detected if you are using `@ReflectiveScan`.
|
||||
NOTE: As a specialization of `@Reflective`, this is also detected if you're using `@ReflectiveScan`.
|
||||
|
||||
In the following example, public constructors and public methods can be invoked via reflection on `AccountService`:
|
||||
|
||||
@@ -656,8 +648,8 @@ include-code::./MyConfiguration[tag=snippet,indent=0]
|
||||
|
||||
`@RegisterReflection` can be applied to any target type at the class level, but it can also be applied directly to a method to better indicate where the hints are actually required.
|
||||
|
||||
`@RegisterReflection` can be used as a meta-annotation to support more specific needs.
|
||||
{spring-framework-api}/aot/hint/annotation/RegisterReflectionForBinding.html[`@RegisterReflectionForBinding`] is a composed annotation that is meta-annotated with `@RegisterReflection` and registers the need for serializing arbitrary types.
|
||||
`@RegisterReflection` can be used as a meta-annotation to provide more specific needs.
|
||||
{spring-framework-api}/aot/hint/annotation/RegisterReflectionForBinding.html[`@RegisterReflectionForBinding`] is such composed annotation and registers the need for serializing arbitrary types.
|
||||
A typical use case is the use of DTOs that the container cannot infer, such as using a web client within a method body.
|
||||
|
||||
The following example registers `Order` for serialization.
|
||||
@@ -668,66 +660,11 @@ This registers hints for constructors, fields, properties, and record components
|
||||
Hints are also registered for types transitively used on properties and record components.
|
||||
In other words, if `Order` exposes others types, hints are registered for those as well.
|
||||
|
||||
[[aot.hints.convention-based-conversion]]
|
||||
=== Runtime Hints for Convention-based Conversion
|
||||
|
||||
Although the core container provides built-in support for automatic conversion of many
|
||||
common types (see xref:core/validation/convert.adoc[Spring Type Conversion]), some
|
||||
conversions are supported via a convention-based algorithm that relies on reflection.
|
||||
|
||||
Specifically, if there is no explicit `Converter` registered with the `ConversionService`
|
||||
for a particular source → target type pair, the internal `ObjectToObjectConverter`
|
||||
will attempt to use conventions to convert a source object to a target type by delegating
|
||||
to a method on the source object or to a static factory method or constructor on the
|
||||
target type. Since this convention-based algorithm can be applied to arbitrary types at
|
||||
runtime, the core container is not able to infer the runtime hints necessary to support
|
||||
such reflection.
|
||||
|
||||
If you encounter convention-based conversion issues within a native image resulting from
|
||||
lacking runtime hints, you can register the necessary hints programmatically. For
|
||||
example, if your application requires a conversion from `java.time.Instant` to
|
||||
`java.sql.Timestamp` and relies on `ObjectToObjectConverter` to invoke
|
||||
`java.sql.Timestamp.from(Instant)` using reflection, you could implement a custom
|
||||
`RuntimeHintsRegitrar` to support this use case within a native image, as demonstrated in
|
||||
the following example.
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
public class TimestampConversionRuntimeHints implements RuntimeHintsRegistrar {
|
||||
|
||||
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||
ReflectionHints reflectionHints = hints.reflection();
|
||||
|
||||
reflectionHints.registerTypeIfPresent(classLoader, "java.sql.Timestamp", hint -> hint
|
||||
.withMethod("from", List.of(TypeReference.of(Instant.class)), ExecutableMode.INVOKE)
|
||||
.onReachableType(TypeReference.of("java.sql.Timestamp")));
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
`TimestampConversionRuntimeHints` can then be registered declaratively via
|
||||
<<aot.hints.import-runtime-hints>> or statically via a `META-INF/spring/aot.factories`
|
||||
configuration file.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
The above `TimestampConversionRuntimeHints` class is a simplified version of the
|
||||
`ObjectToObjectConverterRuntimeHints` class that is included in the framework and
|
||||
registered by default.
|
||||
|
||||
Thus, this specific `Instant`-to-`Timestamp` use case is already handled by the framework.
|
||||
====
|
||||
|
||||
[[aot.hints.testing]]
|
||||
=== Testing Runtime Hints
|
||||
|
||||
Spring Core also ships `RuntimeHintsPredicates`, a utility for checking that existing hints match a particular use case.
|
||||
This can be used in your own tests to validate that a `RuntimeHintsRegistrar` produces the expected results.
|
||||
This can be used in your own tests to validate that a `RuntimeHintsRegistrar` contains the expected results.
|
||||
We can write a test for our `SpellCheckService` and ensure that we will be able to load a dictionary at runtime:
|
||||
|
||||
include-code::./SpellCheckServiceTests[tag=hintspredicates]
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
[[appendix]]
|
||||
= Appendix
|
||||
:page-section-summary-toc: 1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ Spring's extensible XML configuration mechanism is based on XML Schema. If you a
|
||||
familiar with Spring's current XML configuration extensions that come with the standard
|
||||
Spring distribution, you should first read the previous section on xref:core/appendix/xsd-schemas.adoc[XML Schemas].
|
||||
|
||||
|
||||
To create new XML configuration extensions:
|
||||
|
||||
. xref:core/appendix/xml-custom.adoc#core.appendix.xsd-custom-schema[Author] an XML schema to describe your custom element(s).
|
||||
@@ -37,6 +38,7 @@ examples follow later in this appendix. The intent of this first simple example
|
||||
through the basic steps of making a custom extension.)
|
||||
|
||||
|
||||
|
||||
[[xsd-custom-schema]]
|
||||
== Authoring the Schema
|
||||
|
||||
@@ -108,6 +110,7 @@ can use autocompletion to let a user choose between several configuration option
|
||||
defined in the enumeration.
|
||||
|
||||
|
||||
|
||||
[[xsd-custom-namespacehandler]]
|
||||
== Coding a `NamespaceHandler`
|
||||
|
||||
@@ -184,6 +187,7 @@ means that each `BeanDefinitionParser` contains only the logic for parsing a sin
|
||||
custom element, as we can see in the next step.
|
||||
|
||||
|
||||
|
||||
[[xsd-custom-parser]]
|
||||
== Using `BeanDefinitionParser`
|
||||
|
||||
@@ -272,11 +276,13 @@ the basic grunt work of creating a single `BeanDefinition`.
|
||||
single `BeanDefinition` represents.
|
||||
======
|
||||
|
||||
|
||||
In this simple case, this is all that we need to do. The creation of our single
|
||||
`BeanDefinition` is handled by the `AbstractSingleBeanDefinitionParser` superclass, as
|
||||
is the extraction and setting of the bean definition's unique identifier.
|
||||
|
||||
|
||||
|
||||
[[xsd-custom-registration]]
|
||||
== Registering the Handler and the Schema
|
||||
|
||||
@@ -288,6 +294,7 @@ can, for example, be distributed alongside your binary classes in a JAR file. Th
|
||||
XML parsing infrastructure automatically picks up your new extension by consuming
|
||||
these special properties files, the formats of which are detailed in the next two sections.
|
||||
|
||||
|
||||
[[xsd-custom-registration-spring-handlers]]
|
||||
=== Writing `META-INF/spring.handlers`
|
||||
|
||||
@@ -306,6 +313,7 @@ The first part (the key) of the key-value pair is the URI associated with your c
|
||||
namespace extension and needs to exactly match exactly the value of the `targetNamespace`
|
||||
attribute, as specified in your custom XSD schema.
|
||||
|
||||
|
||||
[[xsd-custom-registration-spring-schemas]]
|
||||
=== Writing 'META-INF/spring.schemas'
|
||||
|
||||
@@ -329,6 +337,7 @@ You are encouraged to deploy your XSD file (or files) right alongside
|
||||
the `NamespaceHandler` and `BeanDefinitionParser` classes on the classpath.
|
||||
|
||||
|
||||
|
||||
[[xsd-custom-using]]
|
||||
== Using a Custom Extension in Your Spring XML Configuration
|
||||
|
||||
@@ -362,11 +371,13 @@ in a Spring XML configuration file:
|
||||
<1> Our custom bean.
|
||||
|
||||
|
||||
|
||||
[[xsd-custom-meat]]
|
||||
== More Detailed Examples
|
||||
|
||||
This section presents some more detailed examples of custom XML extensions.
|
||||
|
||||
|
||||
[[xsd-custom-custom-nested]]
|
||||
=== Nesting Custom Elements within Custom Elements
|
||||
|
||||
@@ -742,6 +753,7 @@ http\://www.foo.example/schema/component=com.foo.ComponentNamespaceHandler
|
||||
http\://www.foo.example/schema/component/component.xsd=com/foo/component.xsd
|
||||
----
|
||||
|
||||
|
||||
[[xsd-custom-custom-just-attributes]]
|
||||
=== Custom Attributes on "`Normal`" Elements
|
||||
|
||||
@@ -995,3 +1007,5 @@ http\://www.foo.example/schema/jcache=com.foo.JCacheNamespaceHandler
|
||||
# in 'META-INF/spring.schemas'
|
||||
http\://www.foo.example/schema/jcache/jcache.xsd=com/foo/jcache.xsd
|
||||
----
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
This part of the appendix lists XML schemas related to the core container.
|
||||
|
||||
|
||||
|
||||
[[xsd-schemas-util]]
|
||||
== The `util` Schema
|
||||
|
||||
@@ -28,6 +29,7 @@ correct schema so that the tags in the `util` namespace are available to you):
|
||||
</beans>
|
||||
----
|
||||
|
||||
|
||||
[[xsd-schemas-util-constant]]
|
||||
=== Using `<util:constant/>`
|
||||
|
||||
@@ -184,6 +186,7 @@ Kotlin::
|
||||
</bean>
|
||||
----
|
||||
|
||||
|
||||
[[xsd-schemas-util-property-path]]
|
||||
=== Using `<util:property-path/>`
|
||||
|
||||
@@ -305,6 +308,7 @@ You can specifically set the result type in the actual definition. This is not n
|
||||
for most use cases, but it can sometimes be useful. See the javadoc for more info on
|
||||
this feature.
|
||||
|
||||
|
||||
[[xsd-schemas-util-properties]]
|
||||
=== Using `<util:properties/>`
|
||||
|
||||
@@ -330,6 +334,7 @@ The following example uses a `util:properties` element to make a more concise re
|
||||
<util:properties id="jdbcConfiguration" location="classpath:com/foo/jdbc-production.properties"/>
|
||||
----
|
||||
|
||||
|
||||
[[xsd-schemas-util-list]]
|
||||
=== Using `<util:list/>`
|
||||
|
||||
@@ -384,6 +389,7 @@ following configuration:
|
||||
|
||||
If no `list-class` attribute is supplied, the container chooses a `List` implementation.
|
||||
|
||||
|
||||
[[xsd-schemas-util-map]]
|
||||
=== Using `<util:map/>`
|
||||
|
||||
@@ -438,6 +444,7 @@ following configuration:
|
||||
|
||||
If no `'map-class'` attribute is supplied, the container chooses a `Map` implementation.
|
||||
|
||||
|
||||
[[xsd-schemas-util-set]]
|
||||
=== Using `<util:set/>`
|
||||
|
||||
@@ -493,6 +500,7 @@ following configuration:
|
||||
If no `set-class` attribute is supplied, the container chooses a `Set` implementation.
|
||||
|
||||
|
||||
|
||||
[[xsd-schemas-aop]]
|
||||
== The `aop` Schema
|
||||
|
||||
@@ -522,6 +530,7 @@ are available to you):
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[xsd-schemas-context]]
|
||||
== The `context` Schema
|
||||
|
||||
@@ -546,6 +555,7 @@ available to you:
|
||||
</beans>
|
||||
----
|
||||
|
||||
|
||||
[[xsd-schemas-context-pphc]]
|
||||
=== Using `<property-placeholder/>`
|
||||
|
||||
@@ -589,25 +599,34 @@ element for that purpose. Similarly, Spring's
|
||||
xref:integration/cache/annotations.adoc[caching annotations] need to be explicitly
|
||||
xref:integration/cache/annotations.adoc#cache-annotation-enable[enabled] as well.
|
||||
|
||||
|
||||
[[xsd-schemas-context-component-scan]]
|
||||
=== Using `<component-scan/>`
|
||||
|
||||
This element is detailed in the section on xref:core/beans/annotation-config.adoc[annotation-based container configuration].
|
||||
This element is detailed in the section on xref:core/beans/annotation-config.adoc[annotation-based container configuration]
|
||||
.
|
||||
|
||||
|
||||
[[xsd-schemas-context-ltw]]
|
||||
=== Using `<load-time-weaver/>`
|
||||
|
||||
This element is detailed in the section on xref:core/aop/using-aspectj.adoc#aop-aj-ltw[load-time weaving with AspectJ in the Spring Framework].
|
||||
This element is detailed in the section on xref:core/aop/using-aspectj.adoc#aop-aj-ltw[load-time weaving with AspectJ in the Spring Framework]
|
||||
.
|
||||
|
||||
|
||||
[[xsd-schemas-context-sc]]
|
||||
=== Using `<spring-configured/>`
|
||||
|
||||
This element is detailed in the section on xref:core/aop/using-aspectj.adoc#aop-atconfigurable[using AspectJ to dependency inject domain objects with Spring].
|
||||
This element is detailed in the section on xref:core/aop/using-aspectj.adoc#aop-atconfigurable[using AspectJ to dependency inject domain objects with Spring]
|
||||
.
|
||||
|
||||
|
||||
[[xsd-schemas-context-mbe]]
|
||||
=== Using `<mbean-export/>`
|
||||
|
||||
This element is detailed in the section on xref:integration/jmx/naming.adoc#jmx-context-mbeanexport[configuring annotation-based MBean export].
|
||||
This element is detailed in the section on xref:integration/jmx/naming.adoc#jmx-context-mbeanexport[configuring annotation-based MBean export]
|
||||
.
|
||||
|
||||
|
||||
|
||||
[[xsd-schemas-beans]]
|
||||
@@ -647,3 +666,7 @@ as it stands).
|
||||
|
||||
In the case of the preceding example, you could assume that there is some logic that consumes
|
||||
the bean definition and sets up some caching infrastructure that uses the supplied metadata.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,3 +3,7 @@
|
||||
:page-section-summary-toc: 1
|
||||
|
||||
This chapter covers Spring's Inversion of Control (IoC) container.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -62,3 +62,6 @@ application context in which it is defined. This means that, if you put
|
||||
it only checks for `@Autowired` beans in your controllers, and not your services. See
|
||||
xref:web/webmvc/mvc-servlet.adoc[The DispatcherServlet] for more information.
|
||||
====
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -152,3 +152,6 @@ The corresponding bean definitions follow:
|
||||
|
||||
</beans>
|
||||
----
|
||||
|
||||
|
||||
|
||||
|
||||
+14
-11
@@ -151,17 +151,17 @@ injected into a `Set<MovieCatalog>` annotated with `@Qualifier("action")`.
|
||||
[TIP]
|
||||
====
|
||||
Letting qualifier values select against target bean names, within the type-matching
|
||||
candidates, does not require a `@Qualifier` annotation at the injection point. If there
|
||||
is no other resolution indicator (such as a qualifier, a primary marker, or a fallback
|
||||
marker), for a non-unique dependency situation, Spring matches the injection point name
|
||||
(that is, the field name or parameter name) against the target bean names and chooses the
|
||||
same-named candidate, if any (either by bean name or by associated alias).
|
||||
candidates, does not require a `@Qualifier` annotation at the injection point.
|
||||
If there is no other resolution indicator (such as a qualifier or a primary marker),
|
||||
for a non-unique dependency situation, Spring matches the injection point name
|
||||
(that is, the field name or parameter name) against the target bean names and chooses
|
||||
the same-named candidate, if any (either by bean name or by associated alias).
|
||||
|
||||
Since version 6.1, this requires the `-parameters` Java compiler flag to be present. As
|
||||
of 6.2, the container applies fast shortcut resolution for bean name matches, bypassing
|
||||
the full type matching algorithm when the parameter name matches the bean name and no
|
||||
type, qualifier, primary, or fallback conditions override the match. It is therefore
|
||||
recommendable for your parameter names to match the target bean names.
|
||||
Since version 6.1, this requires the `-parameters` Java compiler flag to be present.
|
||||
As of 6.2, the container applies fast shortcut resolution for bean name matches,
|
||||
bypassing the full type matching algorithm when the parameter name matches the
|
||||
bean name and no type, qualifier or primary conditions override the match. It is
|
||||
therefore recommendable for your parameter names to match the target bean names.
|
||||
====
|
||||
|
||||
As an alternative for injection by name, consider the JSR-250 `@Resource` annotation
|
||||
@@ -274,7 +274,7 @@ Kotlin::
|
||||
Next, you can provide the information for the candidate bean definitions. You can add
|
||||
`<qualifier/>` tags as sub-elements of the `<bean/>` tag and then specify the `type` and
|
||||
`value` to match your custom qualifier annotations. The type is matched against the
|
||||
fully-qualified class name of the annotation. Alternatively, as a convenience if no risk of
|
||||
fully-qualified class name of the annotation. Alternately, as a convenience if no risk of
|
||||
conflicting names exists, you can use the short class name. The following example
|
||||
demonstrates both approaches:
|
||||
|
||||
@@ -568,3 +568,6 @@ the following example:
|
||||
</beans>
|
||||
----
|
||||
--
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -308,8 +308,7 @@ set of multiple matches for the specific bean type (as returned by the factory m
|
||||
|
||||
Note that the standard `jakarta.annotation.Priority` annotation is not available at the
|
||||
`@Bean` level, since it cannot be declared on methods. Its semantics can be modeled
|
||||
through `@Order` values in combination with `@Primary` or `@Fallback` on a single bean
|
||||
for each type.
|
||||
through `@Order` values in combination with `@Primary` on a single bean for each type.
|
||||
====
|
||||
|
||||
Even typed `Map` instances can be autowired as long as the expected key type is `String`.
|
||||
@@ -445,9 +444,9 @@ through Java 8's `java.util.Optional`, as the following example shows:
|
||||
}
|
||||
----
|
||||
|
||||
You can also use a parameter-level `@Nullable` annotation (of any kind in any package --
|
||||
for example, `javax.annotation.Nullable` from JSR-305) or just leverage Kotlin built-in
|
||||
null-safety support:
|
||||
You can also use a `@Nullable` annotation (of any kind in any package -- for example,
|
||||
`javax.annotation.Nullable` from JSR-305) or just leverage Kotlin built-in null-safety
|
||||
support:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
@@ -478,13 +477,6 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
A type-level `@Nullable` annotation such as from JSpecify is not supported in Spring
|
||||
Framework 6.2 yet. You need to upgrade to Spring Framework 7.0 where the framework
|
||||
detects type-level annotations and consistently declares JSpecify in its own codebase.
|
||||
====
|
||||
|
||||
You can also use `@Autowired` for interfaces that are well-known resolvable
|
||||
dependencies: `BeanFactory`, `ApplicationContext`, `Environment`, `ResourceLoader`,
|
||||
`ApplicationEventPublisher`, and `MessageSource`. These interfaces and their extended
|
||||
@@ -531,3 +523,6 @@ The `@Autowired`, `@Inject`, `@Value`, and `@Resource` annotations are handled b
|
||||
within your own `BeanPostProcessor` or `BeanFactoryPostProcessor` types (if any).
|
||||
These types must be 'wired up' explicitly by using XML or a Spring `@Bean` method.
|
||||
====
|
||||
|
||||
|
||||
|
||||
|
||||
+4
-2
@@ -27,5 +27,7 @@ with the `CustomAutowireConfigurer`
|
||||
|
||||
When multiple beans qualify as autowire candidates, the determination of a "`primary`" is
|
||||
as follows: If exactly one bean definition among the candidates has a `primary`
|
||||
attribute set to `true`, it is selected. For annotation-based configuration, see
|
||||
xref:core/beans/annotation-config/autowired-primary.adoc[Fine-tuning with `@Primary` or `@Fallback`].
|
||||
attribute set to `true`, it is selected.
|
||||
|
||||
|
||||
|
||||
|
||||
+3
@@ -96,3 +96,6 @@ Kotlin::
|
||||
private lateinit var s: List<Store<Integer>>
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
|
||||
|
||||
+4
@@ -64,3 +64,7 @@ JDK 11. As of Jakarta EE 9, the package lives in `jakarta.annotation` now. If ne
|
||||
the `jakarta.annotation-api` artifact needs to be obtained via Maven Central now,
|
||||
simply to be added to the application's classpath like any other library.
|
||||
====
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -142,3 +142,4 @@ Kotlin::
|
||||
`ApplicationContext`.
|
||||
======
|
||||
--
|
||||
|
||||
|
||||
+46
-47
@@ -9,15 +9,15 @@ Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@Component
|
||||
public class MovieRecommender {
|
||||
@Component
|
||||
public class MovieRecommender {
|
||||
|
||||
private final String catalog;
|
||||
private final String catalog;
|
||||
|
||||
public MovieRecommender(@Value("${catalog.name}") String catalog) {
|
||||
this.catalog = catalog;
|
||||
}
|
||||
}
|
||||
public MovieRecommender(@Value("${catalog.name}") String catalog) {
|
||||
this.catalog = catalog;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
@@ -37,9 +37,9 @@ Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@Configuration
|
||||
@PropertySource("classpath:application.properties")
|
||||
public class AppConfig { }
|
||||
@Configuration
|
||||
@PropertySource("classpath:application.properties")
|
||||
public class AppConfig { }
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
@@ -56,7 +56,7 @@ And the following `application.properties` file:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
catalog.name=MovieCatalog
|
||||
catalog.name=MovieCatalog
|
||||
----
|
||||
|
||||
In that case, the `catalog` parameter and field will be equal to the `MovieCatalog` value.
|
||||
@@ -101,11 +101,8 @@ NOTE: When configuring a `PropertySourcesPlaceholderConfigurer` using JavaConfig
|
||||
|
||||
Using the above configuration ensures Spring initialization failure if any `${}`
|
||||
placeholder could not be resolved. It is also possible to use methods like
|
||||
`setPlaceholderPrefix()`, `setPlaceholderSuffix()`, `setValueSeparator()`, or
|
||||
`setEscapeCharacter()` to customize the placeholder syntax. In addition, the default
|
||||
escape character can be changed or disabled globally by setting the
|
||||
`spring.placeholder.escapeCharacter.default` property via a JVM system property (or via
|
||||
the xref:appendix.adoc#appendix-spring-properties[`SpringProperties`] mechanism).
|
||||
`setPlaceholderPrefix`, `setPlaceholderSuffix`, `setValueSeparator`, or
|
||||
`setEscapeCharacter` to customize placeholders.
|
||||
|
||||
NOTE: Spring Boot configures by default a `PropertySourcesPlaceholderConfigurer` bean that
|
||||
will get properties from `application.properties` and `application.yml` files.
|
||||
@@ -122,15 +119,15 @@ Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@Component
|
||||
public class MovieRecommender {
|
||||
@Component
|
||||
public class MovieRecommender {
|
||||
|
||||
private final String catalog;
|
||||
private final String catalog;
|
||||
|
||||
public MovieRecommender(@Value("${catalog.name:defaultCatalog}") String catalog) {
|
||||
this.catalog = catalog;
|
||||
}
|
||||
}
|
||||
public MovieRecommender(@Value("${catalog.name:defaultCatalog}") String catalog) {
|
||||
this.catalog = catalog;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
@@ -153,16 +150,16 @@ Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@Configuration
|
||||
public class AppConfig {
|
||||
@Configuration
|
||||
public class AppConfig {
|
||||
|
||||
@Bean
|
||||
public ConversionService conversionService() {
|
||||
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
|
||||
conversionService.addConverter(new MyCustomConverter());
|
||||
return conversionService;
|
||||
}
|
||||
}
|
||||
@Bean
|
||||
public ConversionService conversionService() {
|
||||
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
|
||||
conversionService.addConverter(new MyCustomConverter());
|
||||
return conversionService;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
@@ -191,15 +188,15 @@ Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@Component
|
||||
public class MovieRecommender {
|
||||
@Component
|
||||
public class MovieRecommender {
|
||||
|
||||
private final String catalog;
|
||||
private final String catalog;
|
||||
|
||||
public MovieRecommender(@Value("#{systemProperties['user.catalog'] + 'Catalog' }") String catalog) {
|
||||
this.catalog = catalog;
|
||||
}
|
||||
}
|
||||
public MovieRecommender(@Value("#{systemProperties['user.catalog'] + 'Catalog' }") String catalog) {
|
||||
this.catalog = catalog;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
@@ -220,16 +217,16 @@ Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@Component
|
||||
public class MovieRecommender {
|
||||
@Component
|
||||
public class MovieRecommender {
|
||||
|
||||
private final Map<String, Integer> countOfMoviesPerCatalog;
|
||||
private final Map<String, Integer> countOfMoviesPerCatalog;
|
||||
|
||||
public MovieRecommender(
|
||||
@Value("#{{'Thriller': 100, 'Comedy': 300}}") Map<String, Integer> countOfMoviesPerCatalog) {
|
||||
this.countOfMoviesPerCatalog = countOfMoviesPerCatalog;
|
||||
}
|
||||
}
|
||||
public MovieRecommender(
|
||||
@Value("#{{'Thriller': 100, 'Comedy': 300}}") Map<String, Integer> countOfMoviesPerCatalog) {
|
||||
this.countOfMoviesPerCatalog = countOfMoviesPerCatalog;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
@@ -241,3 +238,5 @@ Kotlin::
|
||||
@Value("#{{'Thriller': 100, 'Comedy': 300}}") private val countOfMoviesPerCatalog: Map<String, Int>)
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ created and initialized, you have a fully configured and executable system or ap
|
||||
image::container-magic.png[]
|
||||
|
||||
|
||||
|
||||
[[beans-factory-metadata]]
|
||||
== Configuration Metadata
|
||||
|
||||
@@ -62,6 +63,8 @@ Typically, one does not configure fine-grained domain objects in the container,
|
||||
it is usually the responsibility of repositories and business logic to create and load
|
||||
domain objects.
|
||||
|
||||
|
||||
|
||||
[[beans-factory-xml]]
|
||||
=== XML as an External Configuration DSL
|
||||
|
||||
@@ -116,7 +119,7 @@ Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
val context = ClassPathXmlApplicationContext("services.xml", "daos.xml")
|
||||
val context = ClassPathXmlApplicationContext("services.xml", "daos.xml")
|
||||
----
|
||||
======
|
||||
|
||||
@@ -185,6 +188,7 @@ definition. This linkage between `id` and `ref` elements expresses the dependenc
|
||||
collaborating objects. For details of configuring an object's dependencies, see
|
||||
xref:core/beans/dependencies.adoc[Dependencies].
|
||||
|
||||
|
||||
[[beans-factory-xml-import]]
|
||||
=== Composing XML-based Configuration Metadata
|
||||
|
||||
@@ -240,6 +244,7 @@ The namespace itself provides the import directive feature. Further
|
||||
configuration features beyond plain bean definitions are available in a selection
|
||||
of XML namespaces provided by Spring -- for example, the `context` and `util` namespaces.
|
||||
|
||||
|
||||
[[beans-factory-groovy]]
|
||||
=== The Groovy Bean Definition DSL
|
||||
|
||||
@@ -274,6 +279,7 @@ supports Spring's XML configuration namespaces. It also allows for importing XML
|
||||
bean definition files through an `importBeans` directive.
|
||||
|
||||
|
||||
|
||||
[[beans-factory-client]]
|
||||
== Using the Container
|
||||
|
||||
@@ -304,16 +310,16 @@ Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
import org.springframework.beans.factory.getBean
|
||||
import org.springframework.beans.factory.getBean
|
||||
|
||||
// create and configure beans
|
||||
val context = ClassPathXmlApplicationContext("services.xml", "daos.xml")
|
||||
val context = ClassPathXmlApplicationContext("services.xml", "daos.xml")
|
||||
|
||||
// retrieve configured instance
|
||||
val service = context.getBean<PetStoreService>("petStore")
|
||||
// retrieve configured instance
|
||||
val service = context.getBean<PetStoreService>("petStore")
|
||||
|
||||
// use configured instance
|
||||
var userList = service.getUsernameList()
|
||||
// use configured instance
|
||||
var userList = service.getUsernameList()
|
||||
----
|
||||
======
|
||||
|
||||
@@ -397,3 +403,6 @@ code should never use them. Indeed, your application code should have no calls t
|
||||
Spring's integration with web frameworks provides dependency injection for various web
|
||||
framework components such as controllers and JSF-managed beans, letting you declare
|
||||
a dependency on a specific bean through metadata (such as an autowiring annotation).
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ operate on shared `BeanDefinition` objects as a core metadata representation.
|
||||
This is the essence of what makes Spring's container so flexible and extensible.
|
||||
|
||||
|
||||
|
||||
[[context-introduction-ctx-vs-beanfactory]]
|
||||
== `BeanFactory` or `ApplicationContext`?
|
||||
|
||||
|
||||
@@ -78,3 +78,7 @@ important (at least for singleton beans) that if you have a (parent) bean defini
|
||||
which you intend to use only as a template, and this definition specifies a class, you
|
||||
must make sure to set the __abstract__ attribute to __true__, otherwise the application
|
||||
context will actually (attempt to) pre-instantiate the `abstract` bean.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,29 +1,28 @@
|
||||
[[beans-classpath-scanning]]
|
||||
= Classpath Scanning and Managed Components
|
||||
|
||||
Most examples in this chapter use XML to specify the configuration metadata that
|
||||
produces each `BeanDefinition` within the Spring container. The previous section
|
||||
(xref:core/beans/annotation-config.adoc[Annotation-based Container Configuration])
|
||||
demonstrates how to provide a lot of the configuration metadata through source-level
|
||||
annotations. Even in those examples, however, the "base" bean definitions are explicitly
|
||||
defined in the XML file, while the annotations drive only the dependency injection.
|
||||
|
||||
This section describes an option for implicitly detecting the candidate components by
|
||||
scanning the classpath. Candidate components are classes that match against a filter
|
||||
criteria and have a corresponding bean definition registered with the container.
|
||||
This removes the need to use XML to perform bean registration. Instead, you can use
|
||||
annotations (for example, `@Component`), AspectJ type expressions, or your own
|
||||
Most examples in this chapter use XML to specify the configuration metadata that produces
|
||||
each `BeanDefinition` within the Spring container. The previous section
|
||||
(xref:core/beans/annotation-config.adoc[Annotation-based Container Configuration]) demonstrates how to provide a lot of the configuration
|
||||
metadata through source-level annotations. Even in those examples, however, the "base"
|
||||
bean definitions are explicitly defined in the XML file, while the annotations drive only
|
||||
the dependency injection. This section describes an option for implicitly detecting the
|
||||
candidate components by scanning the classpath. Candidate components are classes that
|
||||
match against a filter criteria and have a corresponding bean definition registered with
|
||||
the container. This removes the need to use XML to perform bean registration. Instead, you
|
||||
can use annotations (for example, `@Component`), AspectJ type expressions, or your own
|
||||
custom filter criteria to select which classes have bean definitions registered with
|
||||
the container.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
You can define beans using Java rather than using XML files. Take a look at the
|
||||
`@Configuration`, `@Bean`, `@Import`, and `@DependsOn` annotations for examples
|
||||
of how to use these features.
|
||||
`@Configuration`, `@Bean`, `@Import`, and `@DependsOn` annotations for examples of how to
|
||||
use these features.
|
||||
====
|
||||
|
||||
|
||||
|
||||
[[beans-stereotype-annotations]]
|
||||
== `@Component` and Further Stereotype Annotations
|
||||
|
||||
@@ -47,6 +46,7 @@ clearly the better choice. Similarly, as stated earlier, `@Repository` is alread
|
||||
supported as a marker for automatic exception translation in your persistence layer.
|
||||
|
||||
|
||||
|
||||
[[beans-meta-annotations]]
|
||||
== Using Meta-annotations and Composed Annotations
|
||||
|
||||
@@ -195,6 +195,7 @@ For further details, see the
|
||||
wiki page.
|
||||
|
||||
|
||||
|
||||
[[beans-scanning-autodetection]]
|
||||
== Automatically Detecting Classes and Registering Bean Definitions
|
||||
|
||||
@@ -333,6 +334,7 @@ NOTE: You can disable the registration of `AutowiredAnnotationBeanPostProcessor`
|
||||
with a value of `false`.
|
||||
|
||||
|
||||
|
||||
[[beans-scanning-filters]]
|
||||
== Using Filters to Customize Scanning
|
||||
|
||||
@@ -424,6 +426,7 @@ annotated or meta-annotated with `@Component`, `@Repository`, `@Service`, `@Cont
|
||||
`@RestController`, or `@Configuration`.
|
||||
|
||||
|
||||
|
||||
[[beans-factorybeans-annotations]]
|
||||
== Defining Bean Metadata within Components
|
||||
|
||||
@@ -660,6 +663,7 @@ analogous to how the container selects between multiple `@Autowired` constructor
|
||||
====
|
||||
|
||||
|
||||
|
||||
[[beans-scanning-name-generator]]
|
||||
== Naming Autodetected Components
|
||||
|
||||
@@ -793,6 +797,7 @@ components may be making explicit references to it. On the other hand, the
|
||||
auto-generated names are adequate whenever the container is responsible for wiring.
|
||||
|
||||
|
||||
|
||||
[[beans-scanning-scope-resolver]]
|
||||
== Providing a Scope for Autodetected Components
|
||||
|
||||
@@ -832,10 +837,10 @@ definitions, there is no notion of bean definition inheritance, and inheritance
|
||||
hierarchies at the class level are irrelevant for metadata purposes.
|
||||
|
||||
For details on web-specific scopes such as "`request`" or "`session`" in a Spring context,
|
||||
see xref:core/beans/factory-scopes.adoc#beans-factory-scopes-other[Request, Session, Application, and WebSocket Scopes].
|
||||
As with the pre-built annotations for those scopes, you may also compose your own scoping
|
||||
annotations by using Spring's meta-annotation approach: for example, a custom annotation
|
||||
meta-annotated with `@Scope("prototype")`, possibly also declaring a custom scoped-proxy mode.
|
||||
see xref:core/beans/factory-scopes.adoc#beans-factory-scopes-other[Request, Session, Application, and WebSocket Scopes]. As with the pre-built annotations for those scopes,
|
||||
you may also compose your own scoping annotations by using Spring's meta-annotation
|
||||
approach: for example, a custom annotation meta-annotated with `@Scope("prototype")`,
|
||||
possibly also declaring a custom scoped-proxy mode.
|
||||
|
||||
NOTE: To provide a custom strategy for scope resolution rather than relying on the
|
||||
annotation-based approach, you can implement the
|
||||
@@ -877,8 +882,7 @@ Kotlin::
|
||||
----
|
||||
|
||||
When using certain non-singleton scopes, it may be necessary to generate proxies for the
|
||||
scoped objects. The reasoning is described in
|
||||
xref:core/beans/factory-scopes.adoc#beans-factory-scopes-other-injection[Scoped Beans as Dependencies].
|
||||
scoped objects. The reasoning is described in xref:core/beans/factory-scopes.adoc#beans-factory-scopes-other-injection[Scoped Beans as Dependencies].
|
||||
For this purpose, a scoped-proxy attribute is available on the component-scan
|
||||
element. The three possible values are: `no`, `interfaces`, and `targetClass`. For example,
|
||||
the following configuration results in standard JDK dynamic proxies:
|
||||
@@ -916,6 +920,7 @@ Kotlin::
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[beans-scanning-qualifiers]]
|
||||
== Providing Qualifier Metadata with Annotations
|
||||
|
||||
@@ -1007,3 +1012,7 @@ NOTE: As with most annotation-based alternatives, keep in mind that the annotati
|
||||
bound to the class definition itself, while the use of XML allows for multiple beans
|
||||
of the same type to provide variations in their qualifier metadata, because that
|
||||
metadata is provided per-instance rather than per-class.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ package also provides the following functionality:
|
||||
`HierarchicalBeanFactory` interface.
|
||||
|
||||
|
||||
|
||||
[[context-functionality-messagesource]]
|
||||
== Internationalization using `MessageSource`
|
||||
|
||||
@@ -272,6 +273,7 @@ See the {spring-framework-api}/context/support/ReloadableResourceBundleMessageSo
|
||||
javadoc for details.
|
||||
|
||||
|
||||
|
||||
[[context-functionality-events]]
|
||||
== Standard and Custom Events
|
||||
|
||||
@@ -511,7 +513,7 @@ the classes above:
|
||||
<property name="notificationAddress" value="blockedlist@example.org"/>
|
||||
</bean>
|
||||
|
||||
<!-- optional: a custom ApplicationEventMulticaster definition -->
|
||||
<!-- optional: a custom ApplicationEventMulticaster definition -->
|
||||
<bean id="applicationEventMulticaster" class="org.springframework.context.event.SimpleApplicationEventMulticaster">
|
||||
<property name="taskExecutor" ref="..."/>
|
||||
<property name="errorHandler" ref="..."/>
|
||||
@@ -532,6 +534,7 @@ complete support for building lightweight,
|
||||
https://www.enterpriseintegrationpatterns.com[pattern-oriented], event-driven
|
||||
architectures that build upon the well-known Spring programming model.
|
||||
|
||||
|
||||
[[context-functionality-events-annotation]]
|
||||
=== Annotation-based Event Listeners
|
||||
|
||||
@@ -575,7 +578,7 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
NOTE: Do not define such beans to be lazy as the `ApplicationContext` will honor that and will not register the method to listen to events.
|
||||
NOTE: Do not define such beans to be lazy as the `ApplicationContext` will honour that and will not register the method to listen to events.
|
||||
|
||||
The method signature once again declares the event type to which it listens,
|
||||
but, this time, with a flexible name and without implementing a specific listener interface.
|
||||
@@ -704,6 +707,7 @@ The `handleBlockedListEvent()` method publishes a new `ListUpdateEvent` for ever
|
||||
`BlockedListEvent` that it handles. If you need to publish several events, you can return
|
||||
a `Collection` or an array of events instead.
|
||||
|
||||
|
||||
[[context-functionality-events-async]]
|
||||
=== Asynchronous Listeners
|
||||
|
||||
@@ -750,6 +754,7 @@ Be aware of the following limitations when using asynchronous events:
|
||||
See xref:integration/observability.adoc#observability.application-events[the `@EventListener` Observability section]
|
||||
for more information on Observability concerns.
|
||||
|
||||
|
||||
[[context-functionality-events-order]]
|
||||
=== Ordering Listeners
|
||||
|
||||
@@ -781,6 +786,7 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
[[context-functionality-events-generics]]
|
||||
=== Generic Events
|
||||
|
||||
@@ -874,6 +880,7 @@ for example, for processing all events asynchronously and/or for handling listen
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[context-functionality-resources]]
|
||||
== Convenient Access to Low-level Resources
|
||||
|
||||
@@ -906,6 +913,7 @@ with special prefixes to force loading of definitions from the classpath or a UR
|
||||
regardless of the actual context type.
|
||||
|
||||
|
||||
|
||||
[[context-functionality-startup]]
|
||||
== Application Startup Tracking
|
||||
|
||||
@@ -982,7 +990,6 @@ or ask for the `ApplicationStartup` type on any injection point.
|
||||
NOTE: Developers should not use the `"spring.*"` namespace when creating custom startup steps.
|
||||
This namespace is reserved for internal Spring usage and is subject to change.
|
||||
|
||||
|
||||
[[context-create]]
|
||||
== Convenient ApplicationContext Instantiation for Web Applications
|
||||
|
||||
@@ -1015,6 +1022,7 @@ Examples are `/WEB-INF/{asterisk}Context.xml` (for all files with names that end
|
||||
(for all such files in any subdirectory of `WEB-INF`).
|
||||
|
||||
|
||||
|
||||
[[context-deploy-rar]]
|
||||
== Deploying a Spring `ApplicationContext` as a Jakarta EE RAR File
|
||||
|
||||
@@ -1045,8 +1053,7 @@ all application classes into a RAR file (which is a standard JAR file with a dif
|
||||
file extension).
|
||||
. Add all required library JARs into the root of the RAR archive.
|
||||
. Add a
|
||||
`META-INF/ra.xml` deployment descriptor (as shown in the
|
||||
{spring-framework-api}/jca/context/SpringContextResourceAdapter.html[javadoc for `SpringContextResourceAdapter`])
|
||||
`META-INF/ra.xml` deployment descriptor (as shown in the {spring-framework-api}/jca/context/SpringContextResourceAdapter.html[javadoc for `SpringContextResourceAdapter`])
|
||||
and the corresponding Spring XML bean definition file(s) (typically
|
||||
`META-INF/applicationContext.xml`).
|
||||
. Drop the resulting RAR file into your
|
||||
@@ -1059,3 +1066,7 @@ other modules. A RAR-based `ApplicationContext` may also, for example, schedule
|
||||
or react to new files in the file system (or the like). If it needs to allow synchronous
|
||||
access from the outside, it could (for example) export RMI endpoints, which may be used
|
||||
by other application modules on the same machine.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -45,5 +45,8 @@ xref:data-access/orm/jpa.adoc[Spring's JPA support] where load-time weaving may
|
||||
necessary for JPA class transformation.
|
||||
Consult the
|
||||
{spring-framework-api}/orm/jpa/LocalContainerEntityManagerFactoryBean.html[`LocalContainerEntityManagerFactoryBean`]
|
||||
javadoc for more detail. For more on AspectJ load-time weaving, see
|
||||
xref:core/aop/using-aspectj.adoc#aop-aj-ltw[Load-time Weaving with AspectJ in the Spring Framework].
|
||||
javadoc for more detail. For more on AspectJ load-time weaving, see xref:core/aop/using-aspectj.adoc#aop-aj-ltw[Load-time Weaving with AspectJ in the Spring Framework].
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -57,9 +57,9 @@ The following table describes these properties:
|
||||
In addition to bean definitions that contain information on how to create a specific
|
||||
bean, the `ApplicationContext` implementations also permit the registration of existing
|
||||
objects that are created outside the container (by users). This is done by accessing the
|
||||
ApplicationContext's `BeanFactory` through the `getAutowireCapableBeanFactory()` method,
|
||||
which returns the `DefaultListableBeanFactory` implementation. `DefaultListableBeanFactory`
|
||||
supports this registration through the `registerSingleton(..)` and `registerBeanDefinition(..)`
|
||||
ApplicationContext's `BeanFactory` through the `getBeanFactory()` method, which returns
|
||||
the `DefaultListableBeanFactory` implementation. `DefaultListableBeanFactory` supports
|
||||
this registration through the `registerSingleton(..)` and `registerBeanDefinition(..)`
|
||||
methods. However, typical applications work solely with beans defined through regular
|
||||
bean definition metadata.
|
||||
|
||||
@@ -74,6 +74,7 @@ lead to concurrent access exceptions, inconsistent state in the bean container,
|
||||
====
|
||||
|
||||
|
||||
|
||||
[[beans-definition-overriding]]
|
||||
== Overriding Beans
|
||||
|
||||
@@ -103,6 +104,7 @@ explicit support for this as of Spring Framework 6.2. Please refer to
|
||||
xref:testing/testcontext-framework/bean-overriding.adoc[this section] for more details.
|
||||
|
||||
|
||||
|
||||
[[beans-beanname]]
|
||||
== Naming Beans
|
||||
|
||||
@@ -145,6 +147,7 @@ case when there is more than one character and both the first and second charact
|
||||
are upper case, the original casing gets preserved. These are the same rules as
|
||||
defined by `java.beans.Introspector.decapitalize` (which Spring uses here).
|
||||
|
||||
|
||||
[[beans-beanname-alias]]
|
||||
=== Aliasing a Bean outside the Bean Definition
|
||||
|
||||
@@ -194,6 +197,7 @@ See xref:core/beans/java/bean-annotation.adoc[Using the `@Bean` Annotation] for
|
||||
****
|
||||
|
||||
|
||||
|
||||
[[beans-factory-class]]
|
||||
== Instantiating Beans
|
||||
|
||||
@@ -205,8 +209,7 @@ If you use XML-based configuration metadata, you specify the type (or class) of
|
||||
that is to be instantiated in the `class` attribute of the `<bean/>` element. This
|
||||
`class` attribute (which, internally, is a `Class` property on a `BeanDefinition`
|
||||
instance) is usually mandatory. (For exceptions, see
|
||||
xref:core/beans/definition.adoc#beans-factory-class-instance-factory-method[Instantiation by Using an Instance Factory Method]
|
||||
and xref:core/beans/child-bean-definitions.adoc[Bean Definition Inheritance].)
|
||||
xref:core/beans/definition.adoc#beans-factory-class-instance-factory-method[Instantiation by Using an Instance Factory Method] and xref:core/beans/child-bean-definitions.adoc[Bean Definition Inheritance].)
|
||||
You can use the `Class` property in one of two ways:
|
||||
|
||||
* Typically, to specify the bean class to be constructed in the case where the container
|
||||
@@ -230,6 +233,7 @@ a bean definition would be `com.example.SomeThing$OtherThing` or
|
||||
`com.example.SomeThing.OtherThing`.
|
||||
****
|
||||
|
||||
|
||||
[[beans-factory-class-ctor]]
|
||||
=== Instantiation with a Constructor
|
||||
|
||||
@@ -264,6 +268,7 @@ NOTE: In the case of constructor arguments, the container can select a correspon
|
||||
constructor among several overloaded constructors. That said, to avoid ambiguities,
|
||||
it is recommended to keep your constructor signatures as straightforward as possible.
|
||||
|
||||
|
||||
[[beans-factory-class-static-factory-method]]
|
||||
=== Instantiation with a Static Factory Method
|
||||
|
||||
@@ -341,6 +346,7 @@ overloads of the `mock` method. Choose the most specific variant of `mock` possi
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
[[beans-factory-class-instance-factory-method]]
|
||||
=== Instantiation by Using an Instance Factory Method
|
||||
|
||||
@@ -472,6 +478,7 @@ xref:core/beans/definition.adoc#beans-factory-class-static-factory-method[static
|
||||
`FactoryBean` (notice the capitalization) refers to a Spring-specific
|
||||
xref:core/beans/factory-extension.adoc#beans-factory-extension-factorybean[`FactoryBean`] implementation class.
|
||||
|
||||
|
||||
[[beans-factory-type-determination]]
|
||||
=== Determining a Bean's Runtime Type
|
||||
|
||||
@@ -487,3 +494,5 @@ The recommended way to find out about the actual runtime type of a particular be
|
||||
a `BeanFactory.getType` call for the specified bean name. This takes all of the above
|
||||
cases into account and returns the type of object that a `BeanFactory.getBean` call is
|
||||
going to return for the same bean name.
|
||||
|
||||
|
||||
|
||||
@@ -7,3 +7,6 @@ Spring parlance). Even the simplest application has a few objects that work toge
|
||||
present what the end-user sees as a coherent application. This next section explains how
|
||||
you go from defining a number of bean definitions that stand alone to a fully realized
|
||||
application where objects collaborate to achieve a goal.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -16,8 +16,7 @@ advantages:
|
||||
during development, without negating the option of switching to explicit wiring when
|
||||
the code base becomes more stable.
|
||||
|
||||
When using XML-based configuration metadata (see
|
||||
xref:core/beans/dependencies/factory-collaborators.adoc[Dependency Injection]), you
|
||||
When using XML-based configuration metadata (see xref:core/beans/dependencies/factory-collaborators.adoc[Dependency Injection]), you
|
||||
can specify the autowire mode for a bean definition with the `autowire` attribute of the
|
||||
`<bean/>` element. The autowiring functionality has four modes. You specify autowiring
|
||||
per bean and can thus choose which ones to autowire. The following table describes the
|
||||
@@ -61,6 +60,7 @@ instance's values consist of all bean instances that match the expected type, an
|
||||
`Map` instance's keys contain the corresponding bean names.
|
||||
|
||||
|
||||
|
||||
[[beans-autowired-exceptions]]
|
||||
== Limitations and Disadvantages of Autowiring
|
||||
|
||||
@@ -90,14 +90,14 @@ In the latter scenario, you have several options:
|
||||
|
||||
* Abandon autowiring in favor of explicit wiring.
|
||||
* Avoid autowiring for a bean definition by setting its `autowire-candidate` attributes
|
||||
to `false`, as described in the
|
||||
xref:core/beans/dependencies/factory-autowire.adoc#beans-factory-autowire-candidate[next section].
|
||||
to `false`, as described in the xref:core/beans/dependencies/factory-autowire.adoc#beans-factory-autowire-candidate[next section].
|
||||
* Designate a single bean definition as the primary candidate by setting the
|
||||
`primary` attribute of its `<bean/>` element to `true`.
|
||||
* Implement the more fine-grained control available with annotation-based configuration,
|
||||
as described in xref:core/beans/annotation-config.adoc[Annotation-based Container Configuration].
|
||||
|
||||
|
||||
|
||||
[[beans-factory-autowire-candidate]]
|
||||
== Excluding a Bean from Autowiring
|
||||
|
||||
@@ -139,3 +139,6 @@ get injected by plain declared type only, rather by type plus specific qualifier
|
||||
In contrast, `autowireCandidate=false` behaves exactly like the `autowire-candidate`
|
||||
attribute as explained above: Such a bean will never get injected by type at all.
|
||||
====
|
||||
|
||||
|
||||
|
||||
|
||||
+5
-3
@@ -16,9 +16,8 @@ not know the location or class of the dependencies. As a result, your classes be
|
||||
to test, particularly when the dependencies are on interfaces or abstract base classes,
|
||||
which allow for stub or mock implementations to be used in unit tests.
|
||||
|
||||
DI exists in two major variants:
|
||||
xref:core/beans/dependencies/factory-collaborators.adoc#beans-constructor-injection[Constructor-based dependency injection]
|
||||
and xref:core/beans/dependencies/factory-collaborators.adoc#beans-setter-injection[Setter-based dependency injection].
|
||||
DI exists in two major variants: xref:core/beans/dependencies/factory-collaborators.adoc#beans-constructor-injection[Constructor-based dependency injection]
|
||||
and xref:core/beans/dependencies/factory-collaborators.adoc#beans-setter-injection[Setter-based dependency injection].
|
||||
|
||||
|
||||
[[beans-constructor-injection]]
|
||||
@@ -607,3 +606,6 @@ contains the `static` factory method (although, in this example, it is). An inst
|
||||
(non-static) factory method can be used in an essentially identical fashion (aside
|
||||
from the use of the `factory-bean` attribute instead of the `class` attribute), so we
|
||||
do not discuss those details here.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -37,3 +37,6 @@ in the case of xref:core/beans/factory-scopes.adoc#beans-factory-scopes-singleto
|
||||
beans only, a corresponding destruction-time dependency. Dependent beans that define a
|
||||
`depends-on` relationship with a given bean are destroyed first, prior to the given bean
|
||||
itself being destroyed. Thus, `depends-on` can also control shutdown order.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -29,3 +29,6 @@ annotated class or in XML using the `default-lazy-init` attribute on the `<beans
|
||||
shows:
|
||||
|
||||
include-code::./LazyConfiguration[tag=snippet,indent=0]
|
||||
|
||||
|
||||
|
||||
|
||||
+19
-9
@@ -2,17 +2,16 @@
|
||||
= Method Injection
|
||||
|
||||
In most application scenarios, most beans in the container are
|
||||
xref:core/beans/factory-scopes.adoc#beans-factory-scopes-singleton[singletons]. When a
|
||||
singleton bean needs to collaborate with another singleton bean or a non-singleton bean
|
||||
needs to collaborate with another non-singleton bean, you typically handle the dependency
|
||||
by defining one bean as a property of the other. A problem arises when the bean lifecycles
|
||||
are different. Suppose singleton bean A needs to use non-singleton (prototype) bean B,
|
||||
xref:core/beans/factory-scopes.adoc#beans-factory-scopes-singleton[singletons]. When a singleton bean needs to
|
||||
collaborate with another singleton bean or a non-singleton bean needs to collaborate
|
||||
with another non-singleton bean, you typically handle the dependency by defining one
|
||||
bean as a property of the other. A problem arises when the bean lifecycles are
|
||||
different. Suppose singleton bean A needs to use non-singleton (prototype) bean B,
|
||||
perhaps on each method invocation on A. The container creates the singleton bean A only
|
||||
once, and thus only gets one opportunity to set the properties. The container cannot
|
||||
provide bean A with a new instance of bean B every time one is needed.
|
||||
|
||||
A solution is to forego some inversion of control. You can
|
||||
xref:core/beans/factory-nature.adoc#beans-factory-aware[make bean A aware of the container]
|
||||
A solution is to forego some inversion of control. You can xref:core/beans/factory-nature.adoc#beans-factory-aware[make bean A aware of the container]
|
||||
by implementing the `ApplicationContextAware` interface,
|
||||
and by xref:core/beans/basics.adoc#beans-factory-client[making a `getBean("B")` call to the container] ask for (a
|
||||
typically new) bean B instance every time bean A needs it. The following example
|
||||
@@ -104,6 +103,7 @@ You can read more about the motivation for Method Injection in
|
||||
****
|
||||
|
||||
|
||||
|
||||
[[beans-factory-lookup-method-injection]]
|
||||
== Lookup Method Injection
|
||||
|
||||
@@ -120,6 +120,8 @@ dynamically generate a subclass that overrides the method.
|
||||
subclasses cannot be `final`, and the method to be overridden cannot be `final`, either.
|
||||
* Unit-testing a class that has an `abstract` method requires you to subclass the class
|
||||
yourself and to supply a stub implementation of the `abstract` method.
|
||||
* Concrete methods are also necessary for component scanning, which requires concrete
|
||||
classes to pick up.
|
||||
* A further key limitation is that lookup methods do not work with factory methods and
|
||||
in particular not with `@Bean` methods in configuration classes, since, in that case,
|
||||
the container is not in charge of creating the instance and therefore cannot create
|
||||
@@ -291,17 +293,22 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
Note that you should typically declare such annotated lookup methods with a concrete
|
||||
stub implementation, in order for them to be compatible with Spring's component
|
||||
scanning rules where abstract classes get ignored by default. This limitation does not
|
||||
apply to explicitly registered or explicitly imported bean classes.
|
||||
|
||||
[TIP]
|
||||
====
|
||||
Another way of accessing differently scoped target beans is an `ObjectFactory`/
|
||||
`Provider` injection point. See
|
||||
xref:core/beans/factory-scopes.adoc#beans-factory-scopes-other-injection[Scoped Beans as Dependencies].
|
||||
`Provider` injection point. See xref:core/beans/factory-scopes.adoc#beans-factory-scopes-other-injection[Scoped Beans as Dependencies].
|
||||
|
||||
You may also find the `ServiceLocatorFactoryBean` (in the
|
||||
`org.springframework.beans.factory.config` package) to be useful.
|
||||
====
|
||||
|
||||
|
||||
|
||||
[[beans-factory-arbitrary-method-replacement]]
|
||||
== Arbitrary Method Replacement
|
||||
|
||||
@@ -422,3 +429,6 @@ substring of the fully qualified type name. For example, the following all match
|
||||
Because the number of arguments is often enough to distinguish between each possible
|
||||
choice, this shortcut can save a lot of typing, by letting you type only the
|
||||
shortest string that matches an argument type.
|
||||
|
||||
|
||||
|
||||
|
||||
+35
-27
@@ -1,10 +1,11 @@
|
||||
[[beans-factory-properties-detailed]]
|
||||
= Dependencies and Configuration in Detail
|
||||
|
||||
As mentioned in the xref:core/beans/dependencies/factory-collaborators.adoc[previous section],
|
||||
you can define bean properties and constructor arguments as references to other managed beans
|
||||
(collaborators) or as values defined inline. Spring's XML-based configuration metadata supports
|
||||
sub-element types within its `<property/>` and `<constructor-arg/>` elements for this purpose.
|
||||
As mentioned in the xref:core/beans/dependencies/factory-collaborators.adoc[previous section], you can define bean
|
||||
properties and constructor arguments as references to other managed beans (collaborators)
|
||||
or as values defined inline. Spring's XML-based configuration metadata supports
|
||||
sub-element types within its `<property/>` and `<constructor-arg/>` elements for this
|
||||
purpose.
|
||||
|
||||
|
||||
[[beans-value-element]]
|
||||
@@ -50,8 +51,9 @@ XML configuration:
|
||||
|
||||
The preceding XML is more succinct. However, typos are discovered at runtime rather than
|
||||
design time, unless you use an IDE (such as https://www.jetbrains.com/idea/[IntelliJ
|
||||
IDEA] or the {spring-site-tools}[Spring Tools]) that supports automatic property
|
||||
completion when you create bean definitions. Such IDE assistance is highly recommended.
|
||||
IDEA] or the {spring-site-tools}[Spring Tools for Eclipse])
|
||||
that supports automatic property completion when you create bean definitions. Such IDE
|
||||
assistance is highly recommended.
|
||||
|
||||
You can also configure a `java.util.Properties` instance, as follows:
|
||||
|
||||
@@ -84,11 +86,11 @@ element. The following example shows how to use it:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<bean id="collaborator" class="..." />
|
||||
<bean id="theTargetBean" class="..."/>
|
||||
|
||||
<bean id="client" class="...">
|
||||
<bean id="theClientBean" class="...">
|
||||
<property name="targetName">
|
||||
<idref bean="collaborator" />
|
||||
<idref bean="theTargetBean"/>
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
@@ -98,24 +100,28 @@ following snippet:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<bean id="collaborator" class="..." />
|
||||
<bean id="theTargetBean" class="..." />
|
||||
|
||||
<bean id="client" class="...">
|
||||
<property name="targetName" value="collaborator" />
|
||||
<bean id="theClientBean" class="...">
|
||||
<property name="targetName" ref="theTargetBean"/>
|
||||
</bean>
|
||||
----
|
||||
|
||||
The first form is preferable to the second, because using the `idref` tag lets the
|
||||
container validate at deployment time that the referenced, named bean actually exists. In
|
||||
the second variation, no validation is performed on the value that is passed to the
|
||||
`targetName` property of the `client` bean. Typos are therefore only discovered (with most
|
||||
container validate at deployment time that the referenced, named bean actually
|
||||
exists. In the second variation, no validation is performed on the value that is passed
|
||||
to the `targetName` property of the `client` bean. Typos are only discovered (with most
|
||||
likely fatal results) when the `client` bean is actually instantiated. If the `client`
|
||||
bean is a xref:core/beans/factory-scopes.adoc[prototype] bean, this typo and the resulting
|
||||
exception may only be discovered long after the container is deployed.
|
||||
bean is a xref:core/beans/factory-scopes.adoc[prototype] bean, this typo and the resulting exception
|
||||
may only be discovered long after the container is deployed.
|
||||
|
||||
NOTE: A common place (at least in versions earlier than Spring 2.0) where the `<idref/>`
|
||||
element brings value is in the configuration of xref:core/aop-api/pfb.adoc#aop-pfb-1[AOP interceptors]
|
||||
in a `ProxyFactoryBean` bean definition. Using `<idref/>` elements when you specify the
|
||||
NOTE: The `local` attribute on the `idref` element is no longer supported in the 4.0 beans
|
||||
XSD, since it does not provide value over a regular `bean` reference any more. Change
|
||||
your existing `idref local` references to `idref bean` when upgrading to the 4.0 schema.
|
||||
|
||||
A common place (at least in versions earlier than Spring 2.0) where the `<idref/>` element
|
||||
brings value is in the configuration of xref:core/aop-api/pfb.adoc#aop-pfb-1[AOP interceptors] in a
|
||||
`ProxyFactoryBean` bean definition. Using `<idref/>` elements when you specify the
|
||||
interceptor names prevents you from misspelling an interceptor ID.
|
||||
|
||||
|
||||
@@ -538,10 +544,9 @@ three approaches at the same time.
|
||||
[[beans-c-namespace]]
|
||||
== XML Shortcut with the c-namespace
|
||||
|
||||
Similar to the
|
||||
xref:core/beans/dependencies/factory-properties-detailed.adoc#beans-p-namespace[XML Shortcut with the p-namespace],
|
||||
the c-namespace, introduced in Spring 3.1, allows inlined attributes for configuring
|
||||
the constructor arguments rather then nested `constructor-arg` elements.
|
||||
Similar to the xref:core/beans/dependencies/factory-properties-detailed.adoc#beans-p-namespace[XML Shortcut with the p-namespace], the c-namespace, introduced in Spring
|
||||
3.1, allows inlined attributes for configuring the constructor arguments rather
|
||||
then nested `constructor-arg` elements.
|
||||
|
||||
The following example uses the `c:` namespace to do the same thing as the from
|
||||
xref:core/beans/dependencies/factory-collaborators.adoc#beans-constructor-injection[Constructor-based Dependency Injection]:
|
||||
@@ -593,9 +598,9 @@ A corresponding index notation is also available for `<constructor-arg>` element
|
||||
not commonly used since the plain order of declaration is usually sufficient there.
|
||||
|
||||
In practice, the constructor resolution
|
||||
xref:core/beans/dependencies/factory-collaborators.adoc#beans-factory-ctor-arguments-resolution[mechanism]
|
||||
is quite efficient in matching arguments, so unless you really need to, we recommend
|
||||
using the name notation throughout your configuration.
|
||||
xref:core/beans/dependencies/factory-collaborators.adoc#beans-factory-ctor-arguments-resolution[mechanism] is quite efficient in matching
|
||||
arguments, so unless you really need to, we recommend using the name notation
|
||||
throughout your configuration.
|
||||
|
||||
|
||||
[[beans-compound-property-names]]
|
||||
@@ -616,3 +621,6 @@ The `something` bean has a `fred` property, which has a `bob` property, which ha
|
||||
property, and that final `sammy` property is being set to a value of `123`. In order for
|
||||
this to work, the `fred` property of `something` and the `bob` property of `fred` must not
|
||||
be `null` after the bean is constructed. Otherwise, a `NullPointerException` is thrown.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ user with a convenient service interface for configuring property sources and re
|
||||
properties from them.
|
||||
|
||||
|
||||
|
||||
[[beans-definition-profiles]]
|
||||
== Bean Definition Profiles
|
||||
|
||||
@@ -113,6 +114,7 @@ certain contexts but not in others. You could say that you want to register a
|
||||
certain profile of bean definitions in situation A and a different profile in
|
||||
situation B. We start by updating our configuration to reflect this need.
|
||||
|
||||
|
||||
[[beans-definition-profiles-java]]
|
||||
=== Using `@Profile`
|
||||
|
||||
@@ -343,6 +345,7 @@ way to represent such an arrangement in a valid Java class in the first place
|
||||
(since there can only be one method of a particular name and argument signature).
|
||||
====
|
||||
|
||||
|
||||
[[beans-definition-profiles-xml]]
|
||||
=== XML Bean Definition Profiles
|
||||
|
||||
@@ -434,6 +437,7 @@ In the preceding example, the `dataSource` bean is exposed if both the `producti
|
||||
`us-east` profiles are active.
|
||||
=====
|
||||
|
||||
|
||||
[[beans-definition-profiles-enable]]
|
||||
=== Activating a Profile
|
||||
|
||||
@@ -508,6 +512,7 @@ as the following example shows:
|
||||
-Dspring.profiles.active="profile1,profile2"
|
||||
----
|
||||
|
||||
|
||||
[[beans-definition-profiles-default]]
|
||||
=== Default Profile
|
||||
|
||||
@@ -562,6 +567,7 @@ the default profile by using `setDefaultProfiles()` on the `Environment` or,
|
||||
declaratively, by using the `spring.profiles.default` property.
|
||||
|
||||
|
||||
|
||||
[[beans-property-source-abstraction]]
|
||||
== `PropertySource` Abstraction
|
||||
|
||||
@@ -662,6 +668,7 @@ API exposes a number of methods that allow for precise manipulation of the set o
|
||||
property sources.
|
||||
|
||||
|
||||
|
||||
[[beans-using-propertysource]]
|
||||
== Using `@PropertySource`
|
||||
|
||||
@@ -770,6 +777,7 @@ may also be used as a meta-annotation to create custom composed annotations with
|
||||
attribute overrides.
|
||||
|
||||
|
||||
|
||||
[[beans-placeholder-resolution-in-statements]]
|
||||
== Placeholder Resolution in Statements
|
||||
|
||||
@@ -790,3 +798,7 @@ property is defined, as long as it is available in the `Environment`:
|
||||
<import resource="com/bank/service/${customer}-config.xml"/>
|
||||
</beans>
|
||||
----
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ implementations of special integration interfaces. The next few sections describ
|
||||
integration interfaces.
|
||||
|
||||
|
||||
|
||||
[[beans-factory-extension-bpp]]
|
||||
== Customizing Beans by Using a `BeanPostProcessor`
|
||||
|
||||
@@ -67,13 +68,6 @@ interface, clearly indicating the post-processor nature of that bean. Otherwise,
|
||||
Since a `BeanPostProcessor` needs to be instantiated early in order to apply to the
|
||||
initialization of other beans in the context, this early type detection is critical.
|
||||
|
||||
Furthermore, when registering a `BeanPostProcessor` via an `@Bean` factory method,
|
||||
declare the method as `static` and ideally with no dependencies. Doing so avoids eager
|
||||
initialization of the configuration class and other beans, which would make them
|
||||
ineligible for full post-processing (such as auto-proxying). See the
|
||||
"BeanPostProcessor-returning `@Bean` methods" section in the
|
||||
{spring-framework-api}/context/annotation/Bean.html[`@Bean`] javadoc for details.
|
||||
|
||||
[[beans-factory-programmatically-registering-beanpostprocessors]]
|
||||
.Programmatically registering `BeanPostProcessor` instances
|
||||
NOTE: While the recommended approach for `BeanPostProcessor` registration is through
|
||||
@@ -87,7 +81,7 @@ of execution. Note also that `BeanPostProcessor` instances registered programmat
|
||||
are always processed before those registered through auto-detection, regardless of any
|
||||
explicit ordering.
|
||||
|
||||
.`BeanPostProcessor` instances and early initialization
|
||||
.`BeanPostProcessor` instances and AOP auto-proxying
|
||||
[NOTE]
|
||||
====
|
||||
Classes that implement the `BeanPostProcessor` interface are special and are treated
|
||||
@@ -97,23 +91,17 @@ of the `ApplicationContext`. Next, all `BeanPostProcessor` instances are registe
|
||||
in a sorted fashion and applied to all further beans in the container. Because AOP
|
||||
auto-proxying is implemented as a `BeanPostProcessor` itself, neither `BeanPostProcessor`
|
||||
instances nor the beans they directly reference are eligible for auto-proxying and,
|
||||
thus, do not have aspects woven into them. More generally, any bean that is instantiated
|
||||
during this early phase is not eligible for full post-processing by all
|
||||
`BeanPostProcessor` instances.
|
||||
thus, do not have aspects woven into them.
|
||||
|
||||
For any such bean, you should see a WARN-level log message similar to the following.
|
||||
For any such bean, you should see an informational log message: `Bean someBean is not
|
||||
eligible for getting processed by all BeanPostProcessor interfaces (for example: not
|
||||
eligible for auto-proxying)`.
|
||||
|
||||
[quote]
|
||||
Bean 'someBean' of type [org.example.SomeType] is not eligible for getting processed by
|
||||
all BeanPostProcessors (for example: not eligible for auto-proxying).
|
||||
|
||||
To minimize the number of beans affected, register a `BeanPostProcessor` with a
|
||||
`static` `@Bean` method that has no dependencies (see the note above). If you have
|
||||
beans wired into your `BeanPostProcessor` by using autowiring or `@Resource` (which
|
||||
may fall back to autowiring), Spring might access unexpected beans when searching
|
||||
for type-matching dependency candidates and, therefore, make them ineligible for
|
||||
auto-proxying or other kinds of bean post-processing. For example, if you have a
|
||||
dependency annotated with `@Resource` where the field or setter name does not
|
||||
If you have beans wired into your `BeanPostProcessor` by using autowiring or
|
||||
`@Resource` (which may fall back to autowiring), Spring might access unexpected beans
|
||||
when searching for type-matching dependency candidates and, therefore, make them
|
||||
ineligible for auto-proxying or other kinds of bean post-processing. For example, if you
|
||||
have a dependency annotated with `@Resource` where the field or setter name does not
|
||||
directly correspond to the declared name of a bean and no name attribute is used,
|
||||
Spring accesses other beans for matching them by type.
|
||||
====
|
||||
@@ -121,6 +109,7 @@ Spring accesses other beans for matching them by type.
|
||||
The following examples show how to write, register, and use `BeanPostProcessor` instances
|
||||
in an `ApplicationContext`.
|
||||
|
||||
|
||||
[[beans-factory-extension-bpp-examples-hw]]
|
||||
=== Example: Hello World, `BeanPostProcessor`-style
|
||||
|
||||
@@ -148,7 +137,7 @@ Java::
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) {
|
||||
System.out.println("Bean '" + beanName + "' created : " + bean);
|
||||
System.out.println("Bean '" + beanName + "' created : " + bean.toString());
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
@@ -177,48 +166,7 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
You can register the `InstantiationTracingBeanPostProcessor` with Java configuration
|
||||
by using a `static` `@Bean` method (recommended to avoid eager initialization of the
|
||||
configuration class and other beans):
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
|
||||
----
|
||||
@Configuration
|
||||
public class AppConfig {
|
||||
|
||||
@Bean
|
||||
public static InstantiationTracingBeanPostProcessor instantiationTracingBeanPostProcessor() {
|
||||
return new InstantiationTracingBeanPostProcessor();
|
||||
}
|
||||
|
||||
// ... other bean definitions
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",chomp="-packages"]
|
||||
----
|
||||
@Configuration
|
||||
class AppConfig {
|
||||
|
||||
@Bean
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun instantiationTracingBeanPostProcessor() = InstantiationTracingBeanPostProcessor()
|
||||
}
|
||||
|
||||
// ... other bean definitions
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
Alternatively, the `InstantiationTracingBeanPostProcessor` can be registered via the
|
||||
`bean` element with XML configuration:
|
||||
The following `beans` element uses the `InstantiationTracingBeanPostProcessor`:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -246,7 +194,7 @@ Alternatively, the `InstantiationTracingBeanPostProcessor` can be registered via
|
||||
----
|
||||
|
||||
Notice how the `InstantiationTracingBeanPostProcessor` is merely defined. It does not
|
||||
even have a name, and, because it is a bean, it can be dependency-injected as with any
|
||||
even have a name, and, because it is a bean, it can be dependency-injected as you would any
|
||||
other bean. (The preceding configuration also defines a bean that is backed by a Groovy
|
||||
script. The Spring dynamic language support is detailed in the chapter entitled
|
||||
xref:languages/dynamic.adoc[Dynamic Language Support].)
|
||||
@@ -278,7 +226,7 @@ Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
import org.springframework.beans.factory.getBean
|
||||
import org.springframework.beans.factory.getBean
|
||||
|
||||
fun main() {
|
||||
val ctx = ClassPathXmlApplicationContext("scripting/beans.xml")
|
||||
@@ -296,6 +244,7 @@ Bean 'messenger' created : org.springframework.scripting.groovy.GroovyMessenger@
|
||||
org.springframework.scripting.groovy.GroovyMessenger@272961
|
||||
----
|
||||
|
||||
|
||||
[[beans-factory-extension-bpp-examples-aabpp]]
|
||||
=== Example: The `AutowiredAnnotationBeanPostProcessor`
|
||||
|
||||
@@ -306,6 +255,7 @@ that ships with the Spring distribution and autowires annotated fields, setter m
|
||||
and arbitrary config methods.
|
||||
|
||||
|
||||
|
||||
[[beans-factory-extension-factory-postprocessors]]
|
||||
== Customizing Configuration Metadata with a `BeanFactoryPostProcessor`
|
||||
|
||||
@@ -355,23 +305,6 @@ implement the `BeanFactoryPostProcessor` interface. It uses these beans as bean
|
||||
post-processors, at the appropriate time. You can deploy these post-processor beans as
|
||||
you would any other bean.
|
||||
|
||||
When registering a `BeanFactoryPostProcessor` via an `@Bean` factory method in a
|
||||
`@Configuration` class, declare the method as `static` to avoid lifecycle conflicts
|
||||
with annotation processing (such as `@Autowired`, `@Value`, and `@PostConstruct`) in the
|
||||
configuration class. See the "BeanFactoryPostProcessor-returning `@Bean` methods"
|
||||
section in the {spring-framework-api}/context/annotation/Bean.html[`@Bean`] javadoc
|
||||
for details and an example.
|
||||
|
||||
For any non-static `@Bean` factory method with a `BeanFactoryPostProcessor` return type,
|
||||
you should see an INFO-level log message similar to the following.
|
||||
|
||||
[quote]
|
||||
@Bean method MyConfig.myBfpp is non-static and returns an object assignable to Spring's
|
||||
BeanFactoryPostProcessor interface. This will result in a failure to process annotations
|
||||
such as @Autowired, @Resource, and @PostConstruct within the method's declaring
|
||||
@Configuration class. Add the 'static' modifier to this method to avoid these container
|
||||
lifecycle issues; see @Bean javadoc for complete details.
|
||||
|
||||
NOTE: As with ``BeanPostProcessor``s , you typically do not want to configure
|
||||
``BeanFactoryPostProcessor``s for lazy initialization. If no other bean references a
|
||||
`Bean(Factory)PostProcessor`, that post-processor will not get instantiated at all.
|
||||
@@ -379,8 +312,9 @@ Thus, marking it for lazy initialization will be ignored, and the
|
||||
`Bean(Factory)PostProcessor` will be instantiated eagerly even if you set the
|
||||
`default-lazy-init` attribute to `true` on the declaration of your `<beans />` element.
|
||||
|
||||
|
||||
[[beans-factory-placeholderconfigurer]]
|
||||
=== Example: Property Placeholder Substitution with `PropertySourcesPlaceholderConfigurer`
|
||||
=== Example: The Class Name Substitution `PropertySourcesPlaceholderConfigurer`
|
||||
|
||||
You can use the `PropertySourcesPlaceholderConfigurer` to externalize property values
|
||||
from a bean definition in a separate file by using the standard Java `Properties` format.
|
||||
@@ -407,8 +341,8 @@ with placeholder values is defined:
|
||||
|
||||
The example shows properties configured from an external `Properties` file. At runtime,
|
||||
a `PropertySourcesPlaceholderConfigurer` is applied to the metadata that replaces some
|
||||
properties of the `DataSource`. The values to replace are specified as placeholders of the
|
||||
form pass:q[`${property-name}`], which follows the Ant, log4j, and JSP EL style.
|
||||
properties of the DataSource. The values to replace are specified as placeholders of the
|
||||
form pass:q[`${property-name}`], which follows the Ant and log4j and JSP EL style.
|
||||
|
||||
The actual values come from another file in the standard Java `Properties` format:
|
||||
|
||||
@@ -421,15 +355,11 @@ jdbc.password=root
|
||||
----
|
||||
|
||||
Therefore, the `${jdbc.username}` string is replaced at runtime with the value, 'sa', and
|
||||
the same applies for other placeholder values that match keys in the properties file. The
|
||||
`PropertySourcesPlaceholderConfigurer` checks for placeholders in most properties and
|
||||
attributes of a bean definition. Furthermore, you can customize the placeholder prefix,
|
||||
suffix, default value separator, and escape character. In addition, the default escape
|
||||
character can be changed or disabled globally by setting the
|
||||
`spring.placeholder.escapeCharacter.default` property via a JVM system property (or via
|
||||
the xref:appendix.adoc#appendix-spring-properties[`SpringProperties`] mechanism).
|
||||
the same applies for other placeholder values that match keys in the properties file.
|
||||
The `PropertySourcesPlaceholderConfigurer` checks for placeholders in most properties and
|
||||
attributes of a bean definition. Furthermore, you can customize the placeholder prefix and suffix.
|
||||
|
||||
With the `context` namespace, you can configure property placeholders
|
||||
With the `context` namespace introduced in Spring 2.5, you can configure property placeholders
|
||||
with a dedicated configuration element. You can provide one or more locations as a
|
||||
comma-separated list in the `location` attribute, as the following example shows:
|
||||
|
||||
@@ -478,6 +408,7 @@ fails when it is about to be created, which is during the `preInstantiateSinglet
|
||||
phase of an `ApplicationContext` for a non-lazy-init bean.
|
||||
=====
|
||||
|
||||
|
||||
[[beans-factory-overrideconfigurer]]
|
||||
=== Example: The `PropertyOverrideConfigurer`
|
||||
|
||||
@@ -534,6 +465,7 @@ property overriding with a dedicated configuration element, as the following exa
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[beans-factory-extension-factorybean]]
|
||||
== Customizing Instantiation Logic with a `FactoryBean`
|
||||
|
||||
@@ -566,3 +498,6 @@ calling the `getBean()` method of the `ApplicationContext`. So, for a given `Fac
|
||||
with an `id` of `myBean`, invoking `getBean("myBean")` on the container returns the
|
||||
product of the `FactoryBean`, whereas invoking `getBean("&myBean")` returns the
|
||||
`FactoryBean` instance itself.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ of a bean. This section groups them as follows:
|
||||
* xref:core/beans/factory-nature.adoc#aware-list[Other `Aware` Interfaces]
|
||||
|
||||
|
||||
|
||||
[[beans-factory-lifecycle]]
|
||||
== Lifecycle Callbacks
|
||||
|
||||
@@ -40,6 +41,8 @@ startup and shutdown process, as driven by the container's own lifecycle.
|
||||
|
||||
The lifecycle callback interfaces are described in this section.
|
||||
|
||||
|
||||
|
||||
[[beans-factory-lifecycle-initializingbean]]
|
||||
=== Initialization Callbacks
|
||||
|
||||
@@ -153,6 +156,8 @@ the container's overall lifecycle management, including an auto-startup mechanis
|
||||
a pre-destroy stop step, and potential stop/restart callbacks (see below).
|
||||
====
|
||||
|
||||
|
||||
|
||||
[[beans-factory-lifecycle-disposablebean]]
|
||||
=== Destruction Callbacks
|
||||
|
||||
@@ -262,6 +267,8 @@ You may also implement `SmartLifecycle` for a time-bound stop step where the con
|
||||
will wait for all such stop processing to complete before moving on to destroy methods.
|
||||
====
|
||||
|
||||
|
||||
|
||||
[[beans-factory-lifecycle-default-init-destroy-methods]]
|
||||
=== Default Initialization and Destroy Methods
|
||||
|
||||
@@ -362,6 +369,8 @@ interceptors to the `init` method, because doing so would couple the lifecycle o
|
||||
target bean to its proxy or interceptors and leave strange semantics when your code
|
||||
interacts directly with the raw target bean.
|
||||
|
||||
|
||||
|
||||
[[beans-factory-lifecycle-combined-effects]]
|
||||
=== Combining Lifecycle Mechanisms
|
||||
|
||||
@@ -393,6 +402,8 @@ Destroy methods are called in the same order:
|
||||
. `destroy()` as defined by the `DisposableBean` callback interface
|
||||
. A custom configured `destroy()` method
|
||||
|
||||
|
||||
|
||||
[[beans-factory-lifecycle-processor]]
|
||||
=== Startup and Shutdown Callbacks
|
||||
|
||||
@@ -515,6 +526,8 @@ its own `start()` method (unlike the context refresh, the context start does not
|
||||
automatically for a standard context implementation). The `phase` value and any
|
||||
"`depends-on`" relationships determine the startup order as described earlier.
|
||||
|
||||
|
||||
|
||||
[[beans-factory-shutdown]]
|
||||
=== Shutting Down the Spring IoC Container Gracefully in Non-Web Applications
|
||||
|
||||
@@ -577,6 +590,8 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
|
||||
[[beans-factory-thread-safety]]
|
||||
=== Thread Safety and Visibility
|
||||
|
||||
@@ -610,6 +625,7 @@ destroy callback without a preceding stop since this may happen during an extrao
|
||||
shutdown after a cancelled bootstrap or in case of a stop timeout caused by another bean.
|
||||
|
||||
|
||||
|
||||
[[beans-factory-aware]]
|
||||
== `ApplicationContextAware` and `BeanNameAware`
|
||||
|
||||
@@ -666,6 +682,7 @@ initialization callback such as `InitializingBean.afterPropertiesSet()` or a cus
|
||||
init-method.
|
||||
|
||||
|
||||
|
||||
[[aware-list]]
|
||||
== Other `Aware` Interfaces
|
||||
|
||||
@@ -730,3 +747,6 @@ dependency type. The following table summarizes the most important `Aware` inter
|
||||
Note again that using these interfaces ties your code to the Spring API and does not
|
||||
follow the Inversion of Control style. As a result, we recommend them for infrastructure
|
||||
beans that require programmatic access to the container.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ For instructions on how to register this or any other custom scope, see
|
||||
xref:core/beans/factory-scopes.adoc#beans-factory-scopes-custom-using[Using a Custom Scope].
|
||||
|
||||
|
||||
|
||||
[[beans-factory-scopes-singleton]]
|
||||
== The Singleton Scope
|
||||
|
||||
@@ -90,6 +91,7 @@ following example:
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[beans-factory-scopes-prototype]]
|
||||
== The Prototype Scope
|
||||
|
||||
@@ -132,6 +134,7 @@ be handled by the client. (For details on the lifecycle of a bean in the Spring
|
||||
container, see xref:core/beans/factory-nature.adoc#beans-factory-lifecycle[Lifecycle Callbacks].)
|
||||
|
||||
|
||||
|
||||
[[beans-factory-scopes-sing-prot-interaction]]
|
||||
== Singleton Beans with Prototype-bean Dependencies
|
||||
|
||||
@@ -149,6 +152,7 @@ and injects its dependencies. If you need a new instance of a prototype bean at
|
||||
runtime more than once, see xref:core/beans/dependencies/factory-method-injection.adoc[Method Injection].
|
||||
|
||||
|
||||
|
||||
[[beans-factory-scopes-other]]
|
||||
== Request, Session, Application, and WebSocket Scopes
|
||||
|
||||
@@ -158,6 +162,8 @@ if you use a web-aware Spring `ApplicationContext` implementation (such as
|
||||
such as the `ClassPathXmlApplicationContext`, an `IllegalStateException` that complains
|
||||
about an unknown bean scope is thrown.
|
||||
|
||||
|
||||
|
||||
[[beans-factory-scopes-other-web-configuration]]
|
||||
=== Initial Web Configuration
|
||||
|
||||
@@ -217,6 +223,8 @@ the same thing, namely bind the HTTP request object to the `Thread` that is serv
|
||||
that request. This makes beans that are request- and session-scoped available further
|
||||
down the call chain.
|
||||
|
||||
|
||||
|
||||
[[beans-factory-scopes-request]]
|
||||
=== Request scope
|
||||
|
||||
@@ -264,6 +272,8 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
|
||||
[[beans-factory-scopes-session]]
|
||||
=== Session Scope
|
||||
|
||||
@@ -312,6 +322,8 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
|
||||
[[beans-factory-scopes-application]]
|
||||
=== Application Scope
|
||||
|
||||
@@ -359,6 +371,8 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
|
||||
[[beans-factory-scopes-websocket]]
|
||||
=== WebSocket Scope
|
||||
|
||||
@@ -366,6 +380,8 @@ WebSocket scope is associated with the lifecycle of a WebSocket session and appl
|
||||
STOMP over WebSocket applications, see
|
||||
xref:web/websocket/stomp/scope.adoc[WebSocket scope] for more details.
|
||||
|
||||
|
||||
|
||||
[[beans-factory-scopes-other-injection]]
|
||||
=== Scoped Beans as Dependencies
|
||||
|
||||
@@ -523,6 +539,8 @@ interfaces. The following example shows a proxy based on an interface:
|
||||
For more detailed information about choosing class-based or interface-based proxying,
|
||||
see xref:core/aop/proxying.adoc[Proxying Mechanisms].
|
||||
|
||||
|
||||
|
||||
[[beans-factory-scopes-injection]]
|
||||
=== Injecting Request/Session References Directly
|
||||
|
||||
@@ -535,6 +553,7 @@ objects which has the advantage of working in singleton beans and serializable b
|
||||
as well, similar to scoped proxies for factory-scoped beans.
|
||||
|
||||
|
||||
|
||||
[[beans-factory-scopes-custom]]
|
||||
== Custom Scopes
|
||||
|
||||
@@ -542,6 +561,7 @@ The bean scoping mechanism is extensible. You can define your own
|
||||
scopes or even redefine existing scopes, although the latter is considered bad practice
|
||||
and you cannot override the built-in `singleton` and `prototype` scopes.
|
||||
|
||||
|
||||
[[beans-factory-scopes-custom-creating]]
|
||||
=== Creating a Custom Scope
|
||||
|
||||
@@ -644,6 +664,8 @@ Kotlin::
|
||||
This identifier is different for each scope. For a session scoped implementation, this
|
||||
identifier can be the session identifier.
|
||||
|
||||
|
||||
|
||||
[[beans-factory-scopes-custom-using]]
|
||||
=== Using a Custom Scope
|
||||
|
||||
@@ -751,3 +773,7 @@ of the scope. You can also do the `Scope` registration declaratively, by using t
|
||||
NOTE: When you place `<aop:scoped-proxy/>` within a `<bean>` declaration for a
|
||||
`FactoryBean` implementation, it is the factory bean itself that is scoped, not the object
|
||||
returned from `getObject()`.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -37,3 +37,7 @@ by the Spring IoC container are called beans. A bean is an object that is
|
||||
instantiated, assembled, and managed by a Spring IoC container. Otherwise, a
|
||||
bean is simply one of many objects in your application. Beans, and the dependencies
|
||||
among them, are reflected in the configuration metadata used by a container.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,3 +4,4 @@
|
||||
|
||||
This section covers how to use annotations in your Java code to configure the Spring
|
||||
container.
|
||||
|
||||
|
||||
@@ -84,3 +84,6 @@ subclassing has to be applied at runtime, reducing the overhead and the footprin
|
||||
The `@Bean` and `@Configuration` annotations are discussed in depth in the following sections.
|
||||
First, however, we cover the various ways of creating a Spring container by using
|
||||
Java-based configuration.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -468,7 +468,6 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
[[beans-java-customizing-bean-naming]]
|
||||
== Customizing Bean Naming
|
||||
|
||||
@@ -586,3 +585,6 @@ Kotlin::
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
|
||||
|
||||
+6
-5
@@ -339,11 +339,11 @@ In the preceding scenario, using `@Autowired` works well and provides the desire
|
||||
modularity, but determining exactly where the autowired bean definitions are declared is
|
||||
still somewhat ambiguous. For example, as a developer looking at `ServiceConfig`, how do
|
||||
you know exactly where the `@Autowired AccountRepository` bean is declared? It is not
|
||||
explicit in the code, and this may be just fine. Note that the
|
||||
{spring-site-tools}[Spring Tools] IDE support provides tooling that can render graphs
|
||||
showing how everything is wired, which may be all you need. Also, your Java IDE can
|
||||
easily find all declarations and uses of the `AccountRepository` type and quickly show
|
||||
you the location of `@Bean` methods that return that type.
|
||||
explicit in the code, and this may be just fine. Remember that the
|
||||
{spring-site-tools}[Spring Tools for Eclipse] provides tooling that
|
||||
can render graphs showing how everything is wired, which may be all you need. Also,
|
||||
your Java IDE can easily find all declarations and uses of the `AccountRepository` type
|
||||
and quickly show you the location of `@Bean` methods that return that type.
|
||||
|
||||
In cases where this ambiguity is not acceptable and you wish to have direct navigation
|
||||
from within your IDE from one `@Configuration` class to another, consider autowiring the
|
||||
@@ -905,3 +905,4 @@ Kotlin::
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
`@Configuration` is a class-level annotation indicating that an object is a source of
|
||||
bean definitions. `@Configuration` classes declare beans through `@Bean`-annotated
|
||||
methods. Calls to `@Bean` methods on `@Configuration` classes can also be used to define
|
||||
inter-bean dependencies. See
|
||||
xref:core/beans/java/basic-concepts.adoc[Basic Concepts: `@Bean` and `@Configuration`]
|
||||
for a general introduction.
|
||||
inter-bean dependencies. See xref:core/beans/java/basic-concepts.adoc[Basic Concepts: `@Bean` and `@Configuration`] for a general introduction.
|
||||
|
||||
|
||||
[[beans-java-injecting-dependencies]]
|
||||
@@ -60,6 +58,7 @@ is declared within a `@Configuration` class. You cannot declare inter-bean depen
|
||||
by using plain `@Component` classes.
|
||||
|
||||
|
||||
|
||||
[[beans-java-method-injection]]
|
||||
== Lookup Method Injection
|
||||
|
||||
@@ -260,3 +259,6 @@ instead) or by annotating your configuration class with
|
||||
are then not intercepted, so you have to exclusively rely on dependency injection at the
|
||||
constructor or method level there.
|
||||
====
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -206,8 +206,7 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
NOTE: Remember that `@Configuration` classes are
|
||||
xref:core/beans/classpath-scanning.adoc#beans-meta-annotations[meta-annotated]
|
||||
NOTE: Remember that `@Configuration` classes are xref:core/beans/classpath-scanning.adoc#beans-meta-annotations[meta-annotated]
|
||||
with `@Component`, so they are candidates for component-scanning. In the preceding example,
|
||||
assuming that `AppConfig` is declared within the `com.acme` package (or any package
|
||||
underneath), it is picked up during the call to `scan()`. Upon `refresh()`, all its `@Bean`
|
||||
@@ -281,3 +280,5 @@ NOTE: For programmatic use cases, a `GenericWebApplicationContext` can be used a
|
||||
alternative to `AnnotationConfigWebApplicationContext`. See the
|
||||
{spring-framework-api}/web/context/support/GenericWebApplicationContext.html[`GenericWebApplicationContext`]
|
||||
javadoc for details.
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ You can add the following dependency to your file pom.xml:
|
||||
=====
|
||||
|
||||
|
||||
|
||||
[[beans-inject-named]]
|
||||
== Dependency Injection with `@Inject` and `@Named`
|
||||
|
||||
@@ -213,6 +214,7 @@ Kotlin::
|
||||
======
|
||||
|
||||
|
||||
|
||||
[[beans-named]]
|
||||
== `@Named` and `@ManagedBean`: Standard Equivalents to the `@Component` Annotation
|
||||
|
||||
@@ -337,6 +339,7 @@ annotations are not composable. You should use Spring's stereotype model for bui
|
||||
custom component annotations.
|
||||
|
||||
|
||||
|
||||
[[beans-standard-annotations-limitations]]
|
||||
== Limitations of JSR-330 Standard Annotations
|
||||
|
||||
@@ -385,3 +388,6 @@ features are not available, as the following table shows:
|
||||
only with a shorter `get()` method name. It can also be used in combination with
|
||||
Spring's `@Autowired` or with non-annotated constructors and setter methods.
|
||||
|===
|
||||
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user