Compare commits
1 Commits
v6.1.2
..
v3.0.0.RC2
| Author | SHA1 | Date | |
|---|---|---|---|
| e3b58bf678 |
@@ -1,10 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*.{adoc,bat,groovy,html,java,js,jsp,kt,kts,md,properties,py,rb,sh,sql,svg,txt,xml,xsd}]
|
||||
charset = utf-8
|
||||
|
||||
[*.{groovy,java,kt,kts,xml,xsd}]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
continuation_indent_size = 8
|
||||
end_of_line = lf
|
||||
@@ -1,16 +0,0 @@
|
||||
# Normalize line endings to LF.
|
||||
* text eol=lf
|
||||
|
||||
# Ensure that line endings for multipart files in spring-web are not modified.
|
||||
*.multipart -text
|
||||
|
||||
# Ensure that line endings for DOS batch files are not modified.
|
||||
*.bat -text
|
||||
|
||||
# Ensure the following are treated as binary.
|
||||
*.gif binary
|
||||
*.jar binary
|
||||
*.jpeg binary
|
||||
*.jpg binary
|
||||
*.png binary
|
||||
*.vsd binary
|
||||
@@ -1,17 +0,0 @@
|
||||
<!--
|
||||
!!! For Security Vulnerabilities, please go to https://spring.io/security-policy !!!
|
||||
-->
|
||||
**Affects:** \<Spring Framework version>
|
||||
|
||||
---
|
||||
<!--
|
||||
Thanks for taking the time to create an issue. Please read the following:
|
||||
|
||||
- Questions should be asked on Stack Overflow.
|
||||
- For bugs, specify affected versions and explain what you are trying to do.
|
||||
- For enhancements, provide context and describe the problem.
|
||||
|
||||
Issue or Pull Request? Create only one, not both. GitHub treats them as the same.
|
||||
If unsure, start with an issue, and if you submit a pull request later, the
|
||||
issue will be closed as superseded.
|
||||
-->
|
||||
@@ -1,32 +0,0 @@
|
||||
name: Backport Bot
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [labeled]
|
||||
pull_request:
|
||||
types: [labeled]
|
||||
push:
|
||||
branches:
|
||||
- '*.x'
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
build:
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
- name: Download BackportBot
|
||||
run: wget https://github.com/spring-io/backport-bot/releases/download/latest/backport-bot-0.0.1-SNAPSHOT.jar
|
||||
- name: Backport
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITHUB_EVENT: ${{ toJSON(github.event) }}
|
||||
run: java -jar backport-bot-0.0.1-SNAPSHOT.jar --github.accessToken="$GITHUB_TOKEN" --github.event_name "$GITHUB_EVENT_NAME" --github.event "$GITHUB_EVENT"
|
||||
@@ -1,32 +0,0 @@
|
||||
name: Deploy Docs
|
||||
on:
|
||||
push:
|
||||
branches-ignore: [ gh-pages ]
|
||||
tags: '**'
|
||||
repository_dispatch:
|
||||
types: request-build-reference # legacy
|
||||
schedule:
|
||||
- cron: '0 10 * * *' # Once per day at 10am UTC
|
||||
workflow_dispatch:
|
||||
permissions:
|
||||
actions: write
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'spring-projects'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: docs-build
|
||||
fetch-depth: 1
|
||||
- name: Dispatch (partial build)
|
||||
if: github.ref_type == 'branch'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: gh workflow run deploy-docs.yml -r $(git rev-parse --abbrev-ref HEAD) -f build-refname=${{ github.ref_name }}
|
||||
- name: Dispatch (full build)
|
||||
if: github.ref_type == 'tag'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: gh workflow run deploy-docs.yml -r $(git rev-parse --abbrev-ref HEAD)
|
||||
@@ -1,13 +0,0 @@
|
||||
name: "Validate Gradle Wrapper"
|
||||
on: [push, pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
validation:
|
||||
name: "Validation"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
@@ -1,53 +0,0 @@
|
||||
# Miscellaneous
|
||||
*.java.hsp
|
||||
*.sonarj
|
||||
*.sw*
|
||||
.DS_Store
|
||||
build.sh
|
||||
integration-repo
|
||||
ivy-cache
|
||||
argfile*
|
||||
activemq-data/
|
||||
classes/
|
||||
|
||||
# Log files
|
||||
jxl.log
|
||||
jmx.log
|
||||
derby.log
|
||||
|
||||
# Gradle artifacts
|
||||
.gradle
|
||||
.gradletasknamecache
|
||||
/build
|
||||
buildSrc/build
|
||||
/spring-*/build
|
||||
/framework-*/build
|
||||
/integration-tests/build
|
||||
/src/asciidoc/build
|
||||
spring-test/test-output/
|
||||
|
||||
# Maven artifacts
|
||||
pom.xml
|
||||
/target/
|
||||
|
||||
# Eclipse artifacts, including WTP generated manifests
|
||||
bin
|
||||
.classpath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
spring-*/src/main/java/META-INF/MANIFEST.MF
|
||||
|
||||
# IDEA artifacts and output dirs
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea
|
||||
out
|
||||
test-output
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# VS Code
|
||||
.vscode/
|
||||
|
||||
cached-antora-playbook.yml
|
||||
@@ -1,3 +0,0 @@
|
||||
# Enable auto-env through the sdkman_auto_env config
|
||||
# Add key=value pairs of SDKs to use below
|
||||
java=17.0.8.1-librca
|
||||
@@ -1,44 +0,0 @@
|
||||
= Contributor Code of Conduct
|
||||
|
||||
As contributors and maintainers of this project, and in the interest of fostering an open
|
||||
and welcoming community, we pledge to respect all people who contribute through reporting
|
||||
issues, posting feature requests, updating documentation, submitting pull requests or
|
||||
patches, and other activities.
|
||||
|
||||
We are committed to making participation in this project a harassment-free experience for
|
||||
everyone, regardless of level of experience, gender, gender identity and expression,
|
||||
sexual orientation, disability, personal appearance, body size, race, ethnicity, age,
|
||||
religion, or nationality.
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery
|
||||
* Personal attacks
|
||||
* Trolling or insulting/derogatory comments
|
||||
* Public or private harassment
|
||||
* Publishing other's private information, such as physical or electronic addresses,
|
||||
without explicit permission
|
||||
* Other unethical or unprofessional conduct
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments,
|
||||
commits, code, wiki edits, issues, and other contributions that are not aligned to this
|
||||
Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors
|
||||
that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
By adopting this Code of Conduct, project maintainers commit themselves to fairly and
|
||||
consistently applying these principles to every aspect of managing this project. Project
|
||||
maintainers who do not follow or enforce the Code of Conduct may be permanently removed
|
||||
from the project team.
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an
|
||||
individual is representing the project or its community.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
|
||||
contacting a project maintainer at spring-code-of-conduct@pivotal.io . All complaints will
|
||||
be reviewed and investigated and will result in a response that is deemed necessary and
|
||||
appropriate to the circumstances. Maintainers are obligated to maintain confidentiality
|
||||
with regard to the reporter of an incident.
|
||||
|
||||
This Code of Conduct is adapted from the
|
||||
https://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at
|
||||
https://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/]
|
||||
@@ -1,135 +0,0 @@
|
||||
# Contributing to the Spring Framework
|
||||
|
||||
First off, thank you for taking the time to contribute! :+1: :tada:
|
||||
|
||||
### Table of Contents
|
||||
|
||||
* [Code of Conduct](#code-of-conduct)
|
||||
* [How to Contribute](#how-to-contribute)
|
||||
* [Ask questions](#ask-questions)
|
||||
* [Create an Issue](#create-an-issue)
|
||||
* [Issue Lifecycle](#issue-lifecycle)
|
||||
* [Submit a Pull Request](#submit-a-pull-request)
|
||||
* [Build from Source](#build-from-source)
|
||||
* [Source Code Style](#source-code-style)
|
||||
* [Reference Docs](#reference-docs)
|
||||
|
||||
### Code of Conduct
|
||||
|
||||
This project is governed by the [Spring Code of Conduct](CODE_OF_CONDUCT.adoc).
|
||||
By participating you are expected to uphold this code.
|
||||
Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
|
||||
|
||||
### How to Contribute
|
||||
|
||||
#### Ask questions
|
||||
|
||||
If you have a question, check Stack Overflow using
|
||||
[this list of tags](https://stackoverflow.com/questions/tagged/spring+or+spring-mvc+or+spring-aop+or+spring-jdbc+or+spring-transactions+or+spring-annotations+or+spring-jms+or+spring-el+or+spring-test+or+spring+or+spring-remoting+or+spring-orm+or+spring-jmx+or+spring-cache+or+spring-webflux?tab=Newest). Find an existing discussion, or start a new one if necessary.
|
||||
|
||||
If you believe there is an issue, search through
|
||||
[existing issues](https://github.com/spring-projects/spring-framework/issues) trying a
|
||||
few different ways to find discussions, past or current, that are related to the issue.
|
||||
Reading those discussions helps you to learn about the issue, and helps us to make a
|
||||
decision.
|
||||
|
||||
|
||||
#### Create an Issue
|
||||
|
||||
Reporting an issue or making a feature request is a great way to contribute. Your feedback
|
||||
and the conversations that result from it provide a continuous flow of ideas. However,
|
||||
before creating a ticket, please take the time to [ask and research](#ask-questions) first.
|
||||
|
||||
If you create an issue after a discussion on Stack Overflow, please provide a description
|
||||
in the issue instead of simply referring to Stack Overflow. The issue tracker is an
|
||||
important place of record for design discussions and should be self-sufficient.
|
||||
|
||||
Once you're ready, create an issue on [GitHub](https://github.com/spring-projects/spring-framework/issues).
|
||||
|
||||
Many issues are caused by subtle behavior, typos, and unintended configuration.
|
||||
Creating a [Minimal Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example)
|
||||
(starting with https://start.spring.io for example) of the problem helps the team
|
||||
quickly triage your issue and get to the core of the problem.
|
||||
|
||||
#### Issue Lifecycle
|
||||
|
||||
When an issue is first created, it is flagged `waiting-for-triage` waiting for a team
|
||||
member to triage it. Once the issue has been reviewed, the team may ask for further
|
||||
information if needed, and based on the findings, the issue is either assigned a target
|
||||
milestone or is closed with a specific status.
|
||||
|
||||
When a fix is ready, the issue is closed and may still be re-opened until the fix is
|
||||
released. After that the issue will typically no longer be reopened. In rare cases if the
|
||||
issue was not at all fixed, the issue may be re-opened. In most cases however any
|
||||
follow-up reports will need to be created as new issues with a fresh description.
|
||||
|
||||
#### Submit a Pull Request
|
||||
|
||||
1. If you have not previously done so, please sign the
|
||||
[Contributor License Agreement](https://cla.spring.io/sign/spring). You will be reminded
|
||||
automatically when you submit the PR.
|
||||
|
||||
1. Should you create an issue first? No, just create the pull request and use the
|
||||
description to provide context and motivation, as you would for an issue. If you want
|
||||
to start a discussion first or have already created an issue, once a pull request is
|
||||
created, we will close the issue as superseded by the pull request, and the discussion
|
||||
about the issue will continue under the pull request.
|
||||
|
||||
1. Always check out the `main` branch and submit pull requests against it
|
||||
(for target version see [settings.gradle](settings.gradle)).
|
||||
Backports to prior versions will be considered on a case-by-case basis and reflected as
|
||||
the fix version in the issue tracker.
|
||||
|
||||
1. Choose the granularity of your commits consciously and squash commits that represent
|
||||
multiple edits or corrections of the same logical change. See
|
||||
[Rewriting History section of Pro Git](https://git-scm.com/book/en/Git-Tools-Rewriting-History)
|
||||
for an overview of streamlining the commit history.
|
||||
|
||||
1. Format commit messages using 55 characters for the subject line, 72 characters per line
|
||||
for the description, followed by the issue fixed, e.g. `Closes gh-22276`. See the
|
||||
[Commit Guidelines section of Pro Git](https://git-scm.com/book/en/Distributed-Git-Contributing-to-a-Project#Commit-Guidelines)
|
||||
for best practices around commit messages, and use `git log` to see some examples.
|
||||
|
||||
1. If there is a prior issue, reference the GitHub issue number in the description of the
|
||||
pull request.
|
||||
|
||||
If accepted, your contribution may be heavily modified as needed prior to merging.
|
||||
You will likely retain author attribution for your Git commits granted that the bulk of
|
||||
your changes remain intact. You may also be asked to rework the submission.
|
||||
|
||||
If asked to make corrections, simply push the changes against the same branch, and your
|
||||
pull request will be updated. In other words, you do not need to create a new pull request
|
||||
when asked to make changes.
|
||||
|
||||
#### Participate in Reviews
|
||||
|
||||
Helping to review pull requests is another great way to contribute. Your feedback
|
||||
can help to shape the implementation of new features. When reviewing pull requests,
|
||||
however, please refrain from approving or rejecting a PR unless you are a core
|
||||
committer for the Spring Framework.
|
||||
|
||||
### Build from Source
|
||||
|
||||
See the [Build from Source](https://github.com/spring-projects/spring-framework/wiki/Build-from-Source)
|
||||
wiki page for instructions on how to check out, build, and import the Spring Framework
|
||||
source code into your IDE.
|
||||
|
||||
### Source Code Style
|
||||
|
||||
The wiki pages
|
||||
[Code Style](https://github.com/spring-projects/spring-framework/wiki/Code-Style) and
|
||||
[IntelliJ IDEA Editor Settings](https://github.com/spring-projects/spring-framework/wiki/IntelliJ-IDEA-Editor-Settings)
|
||||
define the source file coding standards we use along with some IDEA editor settings we customize.
|
||||
|
||||
### Reference Docs
|
||||
|
||||
The reference documentation is authored in [Asciidoctor](https://asciidoctor.org/) format
|
||||
using [Antora](https://docs.antora.org/antora/latest/). The source files for the documentation
|
||||
reside in the [framework-docs/modules/ROOT](framework-docs/modules/ROOT) directory. For
|
||||
trivial changes, you may be able to browse, edit source files, and submit directly from GitHub.
|
||||
|
||||
When making changes locally, execute `./gradlew antora` and then browse the results under
|
||||
`framework-docs/build/site/index.html`.
|
||||
|
||||
Asciidoctor also supports live editing. For more details see
|
||||
[AsciiDoc Tooling](https://docs.asciidoctor.org/asciidoctor/latest/tooling/).
|
||||
@@ -1,202 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -1,38 +0,0 @@
|
||||
# <img src="framework-docs/src/docs/spring-framework.png" width="80" height="80"> Spring Framework [](https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-6.1.x?groups=Build") [](https://ge.spring.io/scans?search.rootProjectNames=spring)
|
||||
|
||||
This is the home of the Spring Framework: the foundation for all [Spring projects](https://spring.io/projects). Collectively the Spring Framework and the family of Spring projects are often referred to simply as "Spring".
|
||||
|
||||
Spring provides everything required beyond the Java programming language for creating enterprise applications for a wide range of scenarios and architectures. Please read the [Overview](https://docs.spring.io/spring-framework/reference/overview.html) section of the reference documentation for a more complete introduction.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project is governed by the [Spring Code of Conduct](CODE_OF_CONDUCT.adoc). By participating, you are expected to uphold this code of conduct. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
|
||||
|
||||
## Access to Binaries
|
||||
|
||||
For access to artifacts or a distribution zip, see the [Spring Framework Artifacts](https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Artifacts) wiki page.
|
||||
|
||||
## Documentation
|
||||
|
||||
The Spring Framework maintains reference documentation ([published](https://docs.spring.io/spring-framework/reference/) and [source](framework-docs/modules/ROOT)), GitHub [wiki pages](https://github.com/spring-projects/spring-framework/wiki), and an
|
||||
[API reference](https://docs.spring.io/spring-framework/docs/current/javadoc-api/). There are also [guides and tutorials](https://spring.io/guides) across Spring projects.
|
||||
|
||||
## Micro-Benchmarks
|
||||
|
||||
See the [Micro-Benchmarks](https://github.com/spring-projects/spring-framework/wiki/Micro-Benchmarks) wiki page.
|
||||
|
||||
## Build from Source
|
||||
|
||||
See the [Build from Source](https://github.com/spring-projects/spring-framework/wiki/Build-from-Source) wiki page and the [CONTRIBUTING.md](CONTRIBUTING.md) file.
|
||||
|
||||
## Continuous Integration Builds
|
||||
|
||||
Information regarding CI builds can be found in the [Spring Framework Concourse pipeline](ci/README.adoc) documentation.
|
||||
|
||||
## Stay in Touch
|
||||
|
||||
Follow [@SpringCentral](https://twitter.com/springcentral), [@SpringFramework](https://twitter.com/springframework), and its [team members](https://twitter.com/springframework/lists/team/members) on Twitter. In-depth articles can be found at [The Spring Blog](https://spring.io/blog/), and releases are announced via our [releases feed](https://spring.io/blog/category/releases).
|
||||
|
||||
## License
|
||||
|
||||
The Spring Framework is released under version 2.0 of the [Apache License](https://www.apache.org/licenses/LICENSE-2.0).
|
||||
@@ -1,16 +0,0 @@
|
||||
# Security Policy
|
||||
|
||||
## JAR signing
|
||||
|
||||
Spring Framework JARs released on Maven Central are signed.
|
||||
You'll find more information about the key here: https://spring.io/GPG-KEY-spring.txt
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Please see the
|
||||
[Spring Framework Versions](https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Versions)
|
||||
wiki page.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please see https://spring.io/security-policy.
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module relativePaths="true" type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="build-spring-framework" default="precommit">
|
||||
|
||||
<path id="bundles">
|
||||
<pathelement location="../org.springframework.instrument"/>
|
||||
<pathelement location="../org.springframework.instrument.tomcat"/>
|
||||
<pathelement location="../org.springframework.asm"/>
|
||||
<pathelement location="../org.springframework.core"/>
|
||||
<pathelement location="../org.springframework.expression"/>
|
||||
<pathelement location="../org.springframework.beans"/>
|
||||
<pathelement location="../org.springframework.aop"/>
|
||||
<pathelement location="../org.springframework.context"/>
|
||||
<pathelement location="../org.springframework.transaction"/>
|
||||
<pathelement location="../org.springframework.oxm"/>
|
||||
<pathelement location="../org.springframework.jms"/>
|
||||
<pathelement location="../org.springframework.aspects"/>
|
||||
<pathelement location="../org.springframework.jdbc"/>
|
||||
<pathelement location="../org.springframework.web"/>
|
||||
<pathelement location="../org.springframework.orm"/>
|
||||
<pathelement location="../org.springframework.context.support"/>
|
||||
<pathelement location="../org.springframework.web.servlet"/>
|
||||
<pathelement location="../org.springframework.web.portlet"/>
|
||||
<pathelement location="../org.springframework.test"/>
|
||||
<pathelement location="../org.springframework.web.struts"/>
|
||||
<pathelement location="../org.springframework.spring-library"/>
|
||||
<pathelement location="../org.springframework.integration-tests"/>
|
||||
</path>
|
||||
|
||||
<property file="${basedir}/../build.properties"/>
|
||||
<import file="${basedir}/package-top-level.xml"/>
|
||||
<import file="${basedir}/publish-top-level.xml"/>
|
||||
<import file="${basedir}/publish-documentation.xml"/>
|
||||
<import file="${basedir}/../spring-build/multi-bundle/default.xml"/>
|
||||
|
||||
<target name="precommit" depends="clean,clean-integration,test"/>
|
||||
|
||||
<presetdef name="javadoc.links">
|
||||
<javadoc>
|
||||
<link href="http://java.sun.com/javase/6/docs/api"/>
|
||||
<link href="http://java.sun.com/j2ee/1.4/docs/api"/>
|
||||
<link href="http://aopalliance.sourceforge.net/doc"/>
|
||||
<!-- Caucho Burlap/Hessian -->
|
||||
<link href="http://cglib.sourceforge.net/apidocs"/>
|
||||
<!-- EasyMock -->
|
||||
<link href="http://ehcache.sourceforge.net/apidocs"/>
|
||||
<link href="http://freemarker.sourceforge.net/docs/api/"/>
|
||||
<link href="http://www.hibernate.org/hib_docs/v3/api"/>
|
||||
<!-- iBATIS -->
|
||||
<!-- iText -->
|
||||
<!-- Commons Attributes -->
|
||||
<link href="http://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_0/"/>
|
||||
<link href="http://jakarta.apache.org/commons/dbcp/apidocs/"/>
|
||||
<link href="http://jakarta.apache.org/commons/fileupload/apidocs/"/>
|
||||
<link href="http://jakarta.apache.org/commons/httpclient/apidocs/"/>
|
||||
<link href="http://jakarta.apache.org/commons/logging/apidocs/"/>
|
||||
<link href="http://jakarta.apache.org/commons/pool/apidocs/"/>
|
||||
<!-- JasperReports -->
|
||||
<!-- JDO -->
|
||||
<!-- JMX -->
|
||||
<!-- JOTM -->
|
||||
<!-- JPA -->
|
||||
<!-- JSF -->
|
||||
<link href="http://junit.sourceforge.net/javadoc_40/"/>
|
||||
<link href="http://logging.apache.org/log4j/docs/api/"/>
|
||||
<link href="http://jakarta.apache.org/regexp/apidocs/"/>
|
||||
<link href="http://jakarta.apache.org/poi/apidocs/"/>
|
||||
<link href="http://portals.apache.org/pluto/multiproject/portlet-api/apidocs/"/>
|
||||
<link href="http://www.opensymphony.com/quartz/api/"/>
|
||||
<link href="http://struts.apache.org/struts-doc-1.2.9/api/"/>
|
||||
<link href="http://java.sun.com/javase/6/docs/jre/api/net/httpserver/spec/"/>
|
||||
<link href="http://tiles.apache.org/framework/apidocs/"/>
|
||||
<link href="http://velocity.apache.org/engine/devel/apidocs/"/>
|
||||
</javadoc>
|
||||
</presetdef>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,131 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="generate-poms" xmlns:ivy="antlib:org.apache.ivy.ant">
|
||||
|
||||
<property file="${basedir}/../build.properties"/>
|
||||
<import file="${basedir}/../spring-build/multi-bundle/default.xml"/>
|
||||
|
||||
|
||||
<path id="modules-to-process">
|
||||
<pathelement location="../org.springframework.instrument"/>
|
||||
<pathelement location="../org.springframework.instrument.tomcat"/>
|
||||
<pathelement location="../org.springframework.asm"/>
|
||||
<pathelement location="../org.springframework.core"/>
|
||||
<pathelement location="../org.springframework.expression"/>
|
||||
<pathelement location="../org.springframework.beans"/>
|
||||
<pathelement location="../org.springframework.aop"/>
|
||||
<pathelement location="../org.springframework.context"/>
|
||||
<pathelement location="../org.springframework.transaction"/>
|
||||
<pathelement location="../org.springframework.oxm"/>
|
||||
<pathelement location="../org.springframework.jms"/>
|
||||
<pathelement location="../org.springframework.aspects"/>
|
||||
<pathelement location="../org.springframework.jdbc"/>
|
||||
<pathelement location="../org.springframework.web"/>
|
||||
<pathelement location="../org.springframework.orm"/>
|
||||
<pathelement location="../org.springframework.context.support"/>
|
||||
<pathelement location="../org.springframework.web.servlet"/>
|
||||
<pathelement location="../org.springframework.web.portlet"/>
|
||||
<pathelement location="../org.springframework.test"/>
|
||||
<pathelement location="../org.springframework.web.struts"/>
|
||||
</path>
|
||||
|
||||
<condition property="maven.extension" value=".bat" else="">
|
||||
<os family="windows"/>
|
||||
</condition>
|
||||
<property name="mvn.exe" value="mvn${maven.extension}"/>
|
||||
|
||||
|
||||
<target name="test">
|
||||
<echo message="pom version = ${project.version}"/>
|
||||
</target>
|
||||
|
||||
<target name="generate-pom" depends="ivy.init">
|
||||
<all-bundles target="do-generate-pom" buildpathRef="modules-to-process"/>
|
||||
</target>
|
||||
|
||||
<target name="generate-pom-test">
|
||||
<all-bundles target="do-generate-pom-test" buildpathRef="modules-to-process"/>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="do-generate-pom" depends="ivy.init">
|
||||
|
||||
|
||||
<delete file="pom.xml" quiet="true"/>
|
||||
<delete file="central-pom.xml" quiet="true"/>
|
||||
|
||||
<ivy:makepom ivyfile="ivy.xml" pomfile="pom.xml">
|
||||
<mapping conf="compile" scope="compile"/>
|
||||
<mapping conf="test" scope="test"/>
|
||||
<mapping conf="provided" scope="provided"/>
|
||||
<mapping conf="runtime" scope="runtime"/>
|
||||
</ivy:makepom>
|
||||
|
||||
<xmlproperty file="../org.springframework.spring-library/pom.xml"/>
|
||||
|
||||
<replaceregexp file="pom.xml"
|
||||
match="<version>.*?</version>"
|
||||
replace="<version>@project-version@</version>" />
|
||||
|
||||
|
||||
<exec executable="${mvn.exe}" failonerror="true">
|
||||
<arg line="org.springframework.build.repository:org.springframework.build.repository.maven:create-central"/>
|
||||
</exec>
|
||||
|
||||
<move file="pom.xml" tofile="pom-bundle.xml"/>
|
||||
<move file="central-pom.xml" tofile="pom.xml"/>
|
||||
|
||||
<replace file="pom.xml">
|
||||
<replacetoken><![CDATA[ <version>@project-version@</version>]]></replacetoken>
|
||||
<replacevalue><![CDATA[ <version>@project-version@</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>@project-version@</version>
|
||||
</parent>
|
||||
]]></replacevalue>
|
||||
</replace>
|
||||
|
||||
<replace file="pom.xml" token="@project-version@" value="${project.version}"/>
|
||||
<replace file="pom.xml" token="latest.integration" value="${project.version}"/>
|
||||
|
||||
|
||||
<fixcrlf srcDir="."
|
||||
eol="lf"
|
||||
eof="remove"
|
||||
includes="pom.xml"/>
|
||||
|
||||
</target>
|
||||
|
||||
<target name="remove-unresolved-references">
|
||||
<!-- TODO in spring-context these are only found in S2 bundle repo, not maven central -->
|
||||
|
||||
<replace file="pom.xml">
|
||||
<replacetoken><![CDATA[<dependency>
|
||||
<groupId>com.oracle.oc4j</groupId>
|
||||
<artifactId>oracle.classloader</artifactId>
|
||||
<version>10.1.3.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.enterprise</groupId>
|
||||
<artifactId>com.sun.enterprise.loader</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
]]></replacetoken>
|
||||
<replacevalue><![CDATA[]]></replacevalue>
|
||||
</replace>
|
||||
|
||||
|
||||
</target>
|
||||
|
||||
<target name="do-generate-pom-test">
|
||||
<exec executable="${mvn.exe}" failonerror="true">
|
||||
<env key="MAVEN_TERMINATE_CMD" value="on" />
|
||||
<arg line="-P stage,fast install"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="package-bundle">
|
||||
|
||||
<import file="publish-maven.xml"/>
|
||||
|
||||
<target name="package" depends="ivy.init">
|
||||
<dist-jar/>
|
||||
<src-jar/>
|
||||
</target>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="package-library">
|
||||
|
||||
<import file="publish-maven.xml"/>
|
||||
|
||||
<target name="package" depends="ivy.init">
|
||||
<dist-jar/>
|
||||
</target>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="package-top-level">
|
||||
|
||||
<target name="package" description="Creates the release package for this project">
|
||||
<delete dir="${package.output.dir}" quiet="true"/>
|
||||
<mkdir dir="${package.output.dir}"/>
|
||||
<delete file="${package.output.file}" quiet="true"/>
|
||||
<mkdir dir="${artifacts.dir}"/>
|
||||
|
||||
<all-bundles target="package">
|
||||
<property name="package.output.dir" value="${package.output.dir}"/>
|
||||
</all-bundles>
|
||||
|
||||
<ant target="javadoc-api" inheritAll="false">
|
||||
<property name="target.dir" value="${package.docs.dir}"/>
|
||||
</ant>
|
||||
|
||||
<!-- Reference Document START-->
|
||||
<path id="doc.projects">
|
||||
<path location="${basedir}/../spring-framework-reference"/>
|
||||
</path>
|
||||
|
||||
<all-bundles target="doc" buildpathRef="doc.projects"/>
|
||||
|
||||
<delete>
|
||||
<fileset dir="${basedir}/../spring-framework-reference" includes="**/*.zip"/>
|
||||
</delete>
|
||||
|
||||
<all-bundles target="package" buildpathRef="doc.projects">
|
||||
<property name="package.output.dir" value="${package.output.dir}"/>
|
||||
</all-bundles>
|
||||
|
||||
<!-- Reference Document END-->
|
||||
|
||||
<copy todir="${package.output.dir}">
|
||||
<fileset dir="${basedir}/resources"/>
|
||||
</copy>
|
||||
|
||||
<copy todir="${package.output.dir}/projects">
|
||||
<fileset dir="${basedir}/..">
|
||||
<exclude name="*/target/**"/>
|
||||
<exclude name="integration-repo/**"/>
|
||||
<exclude name="ivy-cache/**"/>
|
||||
<exclude name="org.springframework.samples.petclinic/**"/>
|
||||
<!--exclude name="ivy-cache/repository/org.apache.velocity/org.apache.velocity.docbookframework.dist/**"/-->
|
||||
<exclude name="spring-build/lib/docbook/**" />
|
||||
<exclude name="**/*OLD*/**"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
<replaceregexp match="build.stamp.*\n" replace="" flags="g"
|
||||
file="${package.output.dir}/projects/build.properties"/>
|
||||
|
||||
<replaceregexp match="release.type=.*" replace="release.type=integration" flags="g"
|
||||
file="${package.output.dir}/projects/build.properties"/>
|
||||
|
||||
<zip destfile="${package.output.file}">
|
||||
<zipfileset dir="${package.dir}">
|
||||
<exclude name="${package.basename}/docs/**"/>
|
||||
<exclude name="${package.basename}/projects/ivy-cache/**"/>
|
||||
</zipfileset>
|
||||
</zip>
|
||||
|
||||
<zip destfile="${artifacts.dir}/${package.basename}-with-docs.zip">
|
||||
<zipfileset dir="${package.dir}">
|
||||
<exclude name="${package.basename}/projects/ivy-cache/**"/>
|
||||
</zipfileset>
|
||||
</zip>
|
||||
|
||||
<!--zip destfile="${artifacts.dir}/${package.basename}-with-dependencies.zip">
|
||||
<zipfileset dir="${package.dir}"/>
|
||||
</zip-->
|
||||
</target>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
|
||||
<!--
|
||||
|
||||
This POM cannot be used to build Spring; it is a work in progress and should only be used as
|
||||
part of a Maven repository upload bundle using artifacts created by the spring build system.
|
||||
|
||||
-->
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>3.0.0.RC2</version>
|
||||
<name>Spring Framework</name>
|
||||
<description>Spring is a layered Java/J2EE application platform, based on code published in Expert
|
||||
One-on-One J2EE Design and Development by Rod Johnson (Wrox, 2002). </description>
|
||||
<url>http://www.springframework.org</url>
|
||||
<issueManagement>
|
||||
<system>JIRA</system>
|
||||
<url>http://jira.springframework.org/browse/SPR</url>
|
||||
</issueManagement>
|
||||
<ciManagement>
|
||||
<system>Bamboo</system>
|
||||
<url>https://build.springframework.org/browse/SPR</url>
|
||||
</ciManagement>
|
||||
<inceptionYear>2003</inceptionYear>
|
||||
<organization>
|
||||
<name>SpringSource</name>
|
||||
<url>http://www.springsource.com</url>
|
||||
</organization>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>The Apache Software License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
<scm>
|
||||
<url>https://fisheye.springframework.org/browse/spring-framework</url>
|
||||
<connection>scm:svn:https://src.springframework.org/svn/spring-framework/trunk</connection>
|
||||
<developerConnection>scm:svn:https://src.springframework.org/svn/spring-framework/trunk</developerConnection>
|
||||
</scm>
|
||||
<mailingLists>
|
||||
<mailingList>
|
||||
<name> Spring Forum
|
||||
</name>
|
||||
<post>http://forum.springframework.org</post>
|
||||
<archive>http://forum.springframework.org</archive>
|
||||
</mailingList>
|
||||
</mailingLists>
|
||||
|
||||
<modules>
|
||||
<module>../org.springframework.spring-parent</module>
|
||||
<module>../org.springframework.instrument</module>
|
||||
<module>../org.springframework.instrument.tomcat</module>
|
||||
<module>../org.springframework.asm</module>
|
||||
<module>../org.springframework.core</module>
|
||||
<module>../org.springframework.expression</module>
|
||||
<module>../org.springframework.beans</module>
|
||||
<module>../org.springframework.aop</module>
|
||||
<module>../org.springframework.context</module>
|
||||
<module>../org.springframework.transaction</module>
|
||||
<module>../org.springframework.oxm</module>
|
||||
<module>../org.springframework.jms</module>
|
||||
<module>../org.springframework.aspects</module>
|
||||
<module>../org.springframework.jdbc</module>
|
||||
<module>../org.springframework.web</module>
|
||||
<module>../org.springframework.orm</module>
|
||||
<module>../org.springframework.context.support</module>
|
||||
<module>../org.springframework.web.servlet</module>
|
||||
<module>../org.springframework.web.portlet</module>
|
||||
<module>../org.springframework.test</module>
|
||||
<module>../org.springframework.web.struts</module>
|
||||
</modules>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>staging</id>
|
||||
<distributionManagement>
|
||||
<site>
|
||||
<id>staging</id>
|
||||
<url>file:///${user.dir}/target/staging</url>
|
||||
</site>
|
||||
<repository>
|
||||
<id>staging</id>
|
||||
<url>file:///${user.dir}/target/staging</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>staging</id>
|
||||
<url>file:///${user.dir}/target/staging</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="publish-documentation">
|
||||
|
||||
<!-- Main targets -->
|
||||
<target name="publish-documentation" depends="publish-documentation.init">
|
||||
<sshexec host="spring02.managed.contegix.com" username="${username}" keyfile="${key.file}" passphrase="${passphrase}"
|
||||
command="mkdir /opt/www/domains/springframework.org/www/htdocs/spring/docs/${bundle.version}"/>
|
||||
|
||||
<scp remoteToDir="${username}@spring02.managed.contegix.com:/opt/www/domains/springframework.org/www/htdocs/spring/docs/${bundle.version}"
|
||||
keyfile="${key.file}" passphrase="${passphrase}" sftp="true" verbose="true">
|
||||
<fileset dir="${package.output.dir}">
|
||||
<include name="changelog.txt" />
|
||||
<include name="license.txt" />
|
||||
<include name="readme.txt" />
|
||||
</fileset>
|
||||
<fileset dir="${package.docs.dir}" />
|
||||
</scp>
|
||||
|
||||
<sshexec host="spring02.managed.contegix.com" username="${username}" keyfile="${key.file}" passphrase="${passphrase}"
|
||||
command="rm /opt/www/domains/springframework.org/www/htdocs/spring/docs/3.0.x ; ln -s /opt/www/domains/springframework.org/www/htdocs/spring/docs/${bundle.version} /opt/www/domains/springframework.org/www/htdocs/spring/docs/3.0.x"/>
|
||||
</target>
|
||||
|
||||
<!-- Other targets -->
|
||||
<target name="publish-documentation.init">
|
||||
<fail message="The 'username' property must be set">
|
||||
<condition>
|
||||
<not>
|
||||
<isset property="username"/>
|
||||
</not>
|
||||
</condition>
|
||||
</fail>
|
||||
<fail message="The 'key.file' property must be set">
|
||||
<condition>
|
||||
<not>
|
||||
<isset property="key.file"/>
|
||||
</not>
|
||||
</condition>
|
||||
</fail>
|
||||
<fail message="The 'passphrase' property must be set">
|
||||
<condition>
|
||||
<not>
|
||||
<isset property="passphrase"/>
|
||||
</not>
|
||||
</condition>
|
||||
</fail>
|
||||
</target>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="publish-maven-central-only-pom" xmlns:maven="antlib:org.apache.maven.artifact.ant">
|
||||
|
||||
<description>
|
||||
This build file publishes to a maven repository and two ways.
|
||||
1. Publish jar, source-jar, and pom artifacts.
|
||||
2. Publish only the pom artifact.
|
||||
The additional complexity in the implementation is due to a bug in the maven ant tasks version 2.0.8 that
|
||||
prevents deploying to a local file repository on windows.
|
||||
</description>
|
||||
|
||||
|
||||
<condition property="is.windows" value="windows">
|
||||
<os family="windows"/>
|
||||
</condition>
|
||||
|
||||
|
||||
<!-- top level targets -->
|
||||
|
||||
<target name="publish-maven-central-only-pom-artifacts" depends="publish-central-only-pom-windows,publish-central-only-pom-unix">
|
||||
</target>
|
||||
|
||||
<target name="publish-maven-central-code-artifacts" depends="publish-central-windows,publish-code-unix">
|
||||
</target>
|
||||
|
||||
|
||||
<target name="publish-maven-milestone-only-pom-artifacts" depends="maven.init">
|
||||
<maven:deploy>
|
||||
<remoteRepository url="s3://${publish.bucket}/maven/bundles/${adjusted.release.type}">
|
||||
<authentication username="${accessKey}" passphrase="${secretKey}"/>
|
||||
</remoteRepository>
|
||||
<pom file="${local.pom.output.file}"/>
|
||||
</maven:deploy>
|
||||
</target>
|
||||
|
||||
<target name="publish-maven-milestone-code-artifacts" depends="maven.init">
|
||||
<maven:deploy file="${jar.output.file}">
|
||||
<remoteRepository url="s3://${publish.bucket}/maven/bundles/${adjusted.release.type}">
|
||||
<authentication username="${accessKey}" passphrase="${secretKey}"/>
|
||||
</remoteRepository>
|
||||
<pom file="${pom.output.file}"/>
|
||||
<attach file="${source-jar.output.file}" classifier="sources"/>
|
||||
</maven:deploy>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="install-pom" depends="maven.init">
|
||||
<maven:install>
|
||||
<pom file="${local.pom.output.file}"/>
|
||||
</maven:install>
|
||||
</target>
|
||||
|
||||
<!-- Supporting targets -->
|
||||
|
||||
<!-- POM only deployment -->
|
||||
|
||||
<target name="publish-central-only-pom-windows" depends="maven.init" if="is.windows">
|
||||
<maven:deploy>
|
||||
<!-- Due to http://jira.codehaus.org/browse/MANTTASKS-103 in 2.0.8 on windows, fixed in 2.0.9 -->
|
||||
<!-- Assuming using local file, value of variable should be of the form L:\temp\maven-repo-test -->
|
||||
<remoteRepository id="localDisk" url="file:${maven.central.repository}"/>
|
||||
<pom file="${local.pom.output.file}"/>
|
||||
</maven:deploy>
|
||||
</target>
|
||||
|
||||
<target name="publish-central-only-pom-unix" depends="maven.init" unless="is.windows">
|
||||
<maven:deploy>
|
||||
<remoteRepository url="${maven.central.repository}"/>
|
||||
<pom file="${local.pom.output.file}"/>
|
||||
</maven:deploy>
|
||||
</target>
|
||||
|
||||
|
||||
<!-- jar, source-jar and POM deployment -->
|
||||
|
||||
<target name="publish-central-windows" depends="maven.init">
|
||||
<maven:deploy file="${jar.output.file}">
|
||||
<!-- Due to http://jira.codehaus.org/browse/MANTTASKS-103 in 2.0.8 on windows, fixed in 2.0.9 -->
|
||||
<!-- Assuming using local file, value of variable should be of the form L:\temp\maven-repo-test -->
|
||||
<remoteRepository id="localDisk" url="file:${maven.central.repository}"/>
|
||||
<pom file="${local.pom.output.file}"/>
|
||||
<attach file="${source-jar.output.file}" classifier="sources"/>
|
||||
</maven:deploy>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="publish-code-unix" depends="maven.init" unless="is.windows">
|
||||
<maven:deploy file="${jar.output.file}">
|
||||
<remoteRepository url="${maven.central.repository}"/>
|
||||
<pom file="${local.pom.output.file}"/>
|
||||
<attach file="${source-jar.output.file}" classifier="sources"/>
|
||||
</maven:deploy>
|
||||
</target>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="publish-top-level" xmlns:aws="antlib:org.springframework.build.aws">
|
||||
|
||||
<target name="publish" depends="publish-package, publish-multi-bundle.publish"
|
||||
description="Publish package, Ivy, and Maven artifacts"/>
|
||||
|
||||
<target name="publish-package" depends="aws.init">
|
||||
<checksum file="${package.output.file}" algorithm="sha1"/>
|
||||
<checksum file="${artifacts.dir}/${package.basename}-with-docs.zip" algorithm="sha1"/>
|
||||
<!--checksum file="${artifacts.dir}/${package.basename}-with-dependencies.zip" algorithm="sha1"/-->
|
||||
|
||||
<aws:s3 accessKey="${accessKey}" secretKey="${secretKey}">
|
||||
<upload bucketName="dist.${bucket.basename}" file="${package.output.file}"
|
||||
toFile="${adjusted.release.type}/${project.key}/${package.file.name}" publicRead="true">
|
||||
<metadata name="project.name" value="Spring Framework"/>
|
||||
<metadata name="release.type" value="${release.type}"/>
|
||||
<metadata name="bundle.version" value="${bundle.version}"/>
|
||||
<metadata name="package.file.name" value="${package.file.name}"/>
|
||||
</upload>
|
||||
<upload bucketName="dist.${bucket.basename}" file="${package.output.file}.sha1"
|
||||
toFile="${adjusted.release.type}/${project.key}/${package.file.name}.sha1" publicRead="true"/>
|
||||
|
||||
<upload bucketName="dist.${bucket.basename}" file="${artifacts.dir}/${package.basename}-with-docs.zip"
|
||||
toFile="${adjusted.release.type}/${project.key}/${package.basename}-with-docs.zip" publicRead="true">
|
||||
<metadata name="project.name" value="Spring Framework"/>
|
||||
<metadata name="release.type" value="${release.type}"/>
|
||||
<metadata name="bundle.version" value="${bundle.version}"/>
|
||||
<metadata name="package.file.name" value="${package.basename}-with-docs.zip"/>
|
||||
</upload>
|
||||
<upload bucketName="dist.${bucket.basename}" file="${artifacts.dir}/${package.basename}-with-docs.zip.sha1"
|
||||
toFile="${adjusted.release.type}/${project.key}/${package.basename}-with-docs.zip.sha1" publicRead="true"/>
|
||||
|
||||
<!--upload bucketName="dist.${bucket.basename}" file="${artifacts.dir}/${package.basename}-with-dependencies.zip"
|
||||
toFile="${adjusted.release.type}/${project.key}/${package.basename}-with-dependencies.zip" publicRead="true">
|
||||
<metadata name="project.name" value="Spring Framework"/>
|
||||
<metadata name="release.type" value="${release.type}"/>
|
||||
<metadata name="bundle.version" value="${bundle.version}"/>
|
||||
<metadata name="package.file.name" value="${package.basename}-with-dependencies.zip"/>
|
||||
</upload>
|
||||
<upload bucketName="dist.${bucket.basename}" file="${artifacts.dir}/${package.basename}-with-dependencies.zip.sha1"
|
||||
toFile="${adjusted.release.type}/${project.key}/${package.basename}-with-dependencies.zip.sha1" publicRead="true"/-->
|
||||
</aws:s3>
|
||||
</target>
|
||||
</project>
|
||||
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="publish-spring-framework" xmlns:maven="antlib:org.apache.maven.artifact.ant">
|
||||
|
||||
<property file="${basedir}/../build.properties"/>
|
||||
<import file="${basedir}/../spring-build/multi-bundle/default.xml"/>
|
||||
|
||||
<path id="modules-with-code-artifacts">
|
||||
<pathelement location="../org.springframework.instrument"/>
|
||||
<pathelement location="../org.springframework.instrument.tomcat"/>
|
||||
<pathelement location="../org.springframework.asm"/>
|
||||
<pathelement location="../org.springframework.core"/>
|
||||
<pathelement location="../org.springframework.expression"/>
|
||||
<pathelement location="../org.springframework.beans"/>
|
||||
<pathelement location="../org.springframework.aop"/>
|
||||
<pathelement location="../org.springframework.context"/>
|
||||
<pathelement location="../org.springframework.transaction"/>
|
||||
<pathelement location="../org.springframework.oxm"/>
|
||||
<pathelement location="../org.springframework.jms"/>
|
||||
<pathelement location="../org.springframework.aspects"/>
|
||||
<pathelement location="../org.springframework.jdbc"/>
|
||||
<pathelement location="../org.springframework.web"/>
|
||||
<pathelement location="../org.springframework.orm"/>
|
||||
<pathelement location="../org.springframework.context.support"/>
|
||||
<pathelement location="../org.springframework.web.servlet"/>
|
||||
<pathelement location="../org.springframework.web.portlet"/>
|
||||
<pathelement location="../org.springframework.test"/>
|
||||
<pathelement location="../org.springframework.web.struts"/>
|
||||
</path>
|
||||
|
||||
<path id="modules-with-only-pom-artifacts">
|
||||
<pathelement location="../org.springframework.spring-library"/>
|
||||
<pathelement location="../org.springframework.spring-parent"/>
|
||||
</path>
|
||||
|
||||
<!-- for milestones -->
|
||||
|
||||
<target name="publish-maven-milestone" depends="publish-maven-milestone-only-pom">
|
||||
<all-bundles target="publish-maven-milestone-code-artifacts" buildpathRef="modules-with-code-artifacts"/>
|
||||
</target>
|
||||
|
||||
<target name="publish-maven-milestone-only-pom">
|
||||
<all-bundles target="publish-maven-milestone-only-pom-artifacts" buildpathRef="modules-with-only-pom-artifacts"/>
|
||||
</target>
|
||||
|
||||
<!-- for releases -->
|
||||
|
||||
<target name="publish-maven-central-release" depends="publish-maven-central-only-pom-release">
|
||||
<all-bundles target="publish-maven-central-code-artifacts" buildpathRef="modules-with-code-artifacts"/>
|
||||
</target>
|
||||
|
||||
<target name="publish-maven-central-only-pom-release">
|
||||
<all-bundles target="publish-maven-central-only-pom-artifacts" buildpathRef="modules-with-only-pom-artifacts"/>
|
||||
</target>
|
||||
|
||||
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,27 @@
|
||||
This is where the master build that creates releases of Spring Framework resides. The build system is based on spring-build, which is linked in using an SVN external to https://src.springframework.org/svn/spring-build.
|
||||
|
||||
USERS
|
||||
- To build all Spring Framework projects, including samples:
|
||||
|
||||
1. From this directory, run:
|
||||
ant
|
||||
|
||||
Build Pre-requisites:
|
||||
- javac 1.6 or > must be in your system path
|
||||
- ant 1.7 or > must be in your system path
|
||||
|
||||
DEVELOPERS
|
||||
- To build a new Spring Framework distribution for release:
|
||||
|
||||
1. Update the files containing the version number to reflect the new release version, if necessary.
|
||||
|
||||
build.properties
|
||||
build-spring-framework/resources/readme.txt
|
||||
spring-framework/src/spring-framework-reference.xml
|
||||
|
||||
2. From this directory, run:
|
||||
|
||||
ant jar package
|
||||
|
||||
The release archive will be created and placed in:
|
||||
target/artifacts
|
||||
@@ -0,0 +1,293 @@
|
||||
SPRING FRAMEWORK CHANGELOG
|
||||
==========================
|
||||
http://www.springsource.org
|
||||
|
||||
|
||||
Changes in version 3.0.0.RC2 (2009-11-13)
|
||||
-----------------------------------------
|
||||
|
||||
* updated to final versions of JSR-330 "javax.inject" and JSR-303 "javax.validation" APIs
|
||||
* full compliance with the JSR-330 TCK (i.e. full compliance with the final specification)
|
||||
* support for Hibernate Validator 4.0 GA (as the JSR-303 reference implementation)
|
||||
* added support for load-time weaving in JBoss 5.x
|
||||
* added support for recent EHCache 1.6 configuration properties to EHCacheFactoryBean
|
||||
* added AnnotatedBeanDefinitionReader helper for programmatic registration of annotated classes
|
||||
* added AnnotationConfig(Web)ApplicationContext for convenient registration/scanning of classes
|
||||
* added GenericXmlApplicationContext with flexible configuration options for its XML support
|
||||
* AbstractApplicationContext can also start up in case of system properties access failure
|
||||
* internal MergedBeanDefinitionPostProcessors apply after all other post-processors
|
||||
* inner beans detected as ApplicationListeners as well (only supported for inner singletons)
|
||||
* child bean definition's scope attribute can be inherited from parent bean definition now
|
||||
* introduced SmartLifecycle interface with auto-startup and shutdown order support
|
||||
* introduced LifecycleProcessor delegate, customizable through "lifecycleProcessor" bean
|
||||
* MessageListenerContainers and Quartz SchedulerFactoryBean start up on refresh instead of init
|
||||
* added initialize-database tag to jdbc namespace for populating external data sources with data
|
||||
* PathMatchingResourcePatternResolver leniently ignores non-existing root directories
|
||||
* DefaultConversionService understands "on"/"off", "yes"/"no", "1"/"0" as boolean values
|
||||
* CustomEditorConfigurer supports PropertyEditor instances again (with deprecation warning)
|
||||
* revised MethodParameter's annotation accessor methods
|
||||
* ClassUtils is now parameterized with Class<?> and Class<T> where appropriate
|
||||
* DataBinder now accepts var-args to set allowed, disallowed, and required fields
|
||||
* DataBinder auto-grows nested paths on traversal (avoiding NullValueInNestedPathException)
|
||||
* fixed enum binding regression with WebRequestDataBinder (as used by @MVC data binding now)
|
||||
* fixed FieldError to expose rejected input value as String value instead of as array
|
||||
* JSR-303 Validator will only register validation failures if no binding failure happened
|
||||
* ContentNegotiatingViewResolver works with ignoreAcceptHeader and defaultContentType as well
|
||||
* added Spring MVC namespace, with convenient mvc:annotation-driven configuration element
|
||||
* default number and datetime formatters configured when using the Spring MVC namespace
|
||||
* full support for datetime formatting using the Joda Time library (automatically enabled)
|
||||
* added convenient @NumberFormat and @DateTimeFormat annotations for declarative formatting
|
||||
* implicit T.valueOf(S) and constructor T(S) lookup if no explicit S->T converter matches
|
||||
* AbstractExcelView is compatible with Apache POI 3.0 as well as 3.5 now
|
||||
* TilesConfigurer only sets up EL support if JSP 2.1 is present (for JSP 2.0 compatibility)
|
||||
* re-introduced Struts 1.x support ("org.springframework.web.struts") in deprecated form
|
||||
* deprecated scheduling support for JDK 1.3 Timer ("org.springframework.scheduling.timer")
|
||||
* deprecated remoting support for JAX-RPC (in favor of JAX-WS)
|
||||
|
||||
|
||||
Changes in version 3.0.0.RC1 (2009-09-25)
|
||||
-----------------------------------------
|
||||
|
||||
* upgraded to CGLIB 2.2, AspectJ 1.6.5, Groovy 1.6.3, EHCache 1.6.2, JUnit 4.7, TestNG 5.10
|
||||
* introduced early support for JSR-330 "javax.inject" annotations (for autowiring)
|
||||
* introduced early support for JSR-303 Bean Validation (setup and MVC integration)
|
||||
* added default editors for "java.util.Currency" and "java.util.TimeZone"
|
||||
* refined PathMatchingResourcePatternResolver's treatment of non-readable directories
|
||||
* PathMatchingResourcePatternResolver understands VFS resources (i.e. works on JBoss 5.x)
|
||||
* revised AccessControlContext access from BeanFactory
|
||||
* AbstractBeanDefinitionParser can deal with null return value as well
|
||||
* PropertyOverrideConfigurer's "ignoreInvalidKeys" ignores invalid property names as well
|
||||
* PropertyPlaceholderConfigurer supports "${myKey:myDefaultValue}" defaulting syntax
|
||||
* BeanFactory's default type conversion falls back to String constructor on target type
|
||||
* BeanFactory tries to create unknown collection implementation types via default constructor
|
||||
* BeanFactory supports ObjectFactory as a dependency type for @Autowired and @Value
|
||||
* BeanFactory supports JSR-330 Provider interface as a dependency type for @Inject
|
||||
* BeanFactory prefers local primary bean to primary bean in parent factory
|
||||
* protected @Autowired method can be overridden with non-annotated method to suppress injection
|
||||
* private @Autowired methods with same signature will be called individually across a hierarchy
|
||||
* @PostConstruct processed top-down (base class first); @PreDestroy bottom-up (subclass first)
|
||||
* ConfigurationClassPostProcessor detect @Bean methods on registered plain bean classes as well
|
||||
* support for default "conversionService" bean in an ApplicationContext
|
||||
* MBeanServerFactoryBean returns JDK 1.5 platform MBeanServer for agent id "" (empty String)
|
||||
* changed NamedParameter/SimpleJdbcOperations parameter signatures to accept any Map value type
|
||||
* refined logging in JMS SingleConnectionFactory and DefaultMessageListenerContainer
|
||||
* introduced "ui.format" package as an alternative to PropertyEditors for data binding
|
||||
* @RequestMapping annotation now supported for annotated interfaces (and JDK proxies) as well
|
||||
* @RequestParam and co support placeholders and expressions in their defaultValue attributes
|
||||
* @Value expressions supported as MVC handler method arguments as well (against request scope)
|
||||
* JSR-303 support for validation of @MVC handler method arguments driven by @Valid annotations
|
||||
* refined response handling for @ExceptionHandler methods
|
||||
* @ResponseStatus usage in handler methods detected by RedirectView
|
||||
* all @SessionAttributes get exposed to the model before handler method execution
|
||||
* @Event/ResourceMapping uniquely mapped to through event/resource id, even across controllers
|
||||
* MultipartRequest is available as a mixin interface on (Native)WebRequest as well
|
||||
* removed outdated "cacheJspExpressions" feature from ExpressionEvaluationUtils
|
||||
* introduced common ErrorHandler strategy, supported by message listener container
|
||||
* Jpa/JdoTransactionManager passes resolved timeout into Jpa/JdoDialect's beginTransaction
|
||||
* HibernateJpaDialect applies timeout onto native Hibernate Transaction before begin call
|
||||
* Spring's Hibernate support is now compatible with Hibernate 3.5 beta 1 as well
|
||||
* Spring's JPA support is now fully compatible with JPA 2.0 as in EclipseLink 2.0.0.M7
|
||||
* SpringJUnit4ClassRunner is now compatible with JUnit 4.5, 4.6, and 4.7
|
||||
* SpringJUnit4ClassRunner once again supports collective timeouts for repeated tests
|
||||
* deprecated @NotTransactional annotation for test classes in favor of @BeforeTransaction
|
||||
|
||||
|
||||
Changes in version 3.0.0.M4 (2009-08-10)
|
||||
----------------------------------------
|
||||
|
||||
* upgraded to JUnit 4.6, TestNG 5.9, and EasyMock 2.5.1
|
||||
* updated all Spring Framework OSGI manifests to list unversioned imports explicitly
|
||||
* relaxed several OSGi bundle dependencies (optional, extended version ranges)
|
||||
* revised Java 6 checks to test for the presence of specific Java 6 interfaces/classes only
|
||||
* replaced Commons Collections dependency with Spring-provided LinkedCaseInsensitiveMap
|
||||
* case-insensitive Maps and key Sets preserve original casing for introspection/logging
|
||||
* constructor argument type matching supports arrays and simple class names now
|
||||
* XML constructor-arg element allows for specifying a constructor argument by name now
|
||||
* XML import elements with relative resource patterns are supported as well now
|
||||
* introduced non-lenient constructor resolution mode for BeanDefinitions (for RFC-124)
|
||||
* revised DefaultListableBeanFactory's access control when running within a SecurityManager
|
||||
* BeanWrapper and DefaultListableBeanFactory accept a custom ConversionService now
|
||||
* DefaultListableBeanFactory references are serializable now when initialized with an id
|
||||
* scoped proxies are serializable now, for web scopes as well as for singleton beans
|
||||
* injected request/session references are serializable proxies for the current request now
|
||||
* Servlet/Portlet ApplicationContexts use a specific id based on servlet/portlet name
|
||||
* ReloadableResourceBundleMessageSource correctly calculates filenames for all locales now
|
||||
* @PostConstruct works for multiple private init methods of the same name in a hierarchy
|
||||
* @Primary/@Lazy/@DependsOn supported as meta-annotations as well
|
||||
* @Bean/@Scope etc supported as meta-annotations on factory methods as well now
|
||||
* @Required does not get processed on beans returned by @Bean factory methods
|
||||
* @Import detects and accepts existing configuration class of the desired type
|
||||
* @Transactional supports qualifier value for choosing between multiple transaction managers
|
||||
* WebSphereUowTransactionManager falls back to UOWManagerFactory lookup by default
|
||||
* JMS SingleConnectionFactory performs start call within connection monitor (for Oracle AQ)
|
||||
* @ManagedResource is marked as inherited now, for generic management-aware base classes
|
||||
* introduced dedicated @ManagedMetric annotation for metric attributes in a JMX environment
|
||||
* added task namespace with scheduler/executor configuration and scheduled task definitions
|
||||
* added jdbc namespace with embedded-database tag (supporting HSQL, H2, and Derby)
|
||||
* Hibernate AnnotationSessionFactoryBean detects Hibernate's special @Entity annotation too
|
||||
* added SimpleJaxWsServiceExporter workaround for WebLogic 10.3's address format requirements
|
||||
* added support for @WebServiceProvider annotation to Spring's JaxWsServiceExporters
|
||||
* updated Hessian support for Hessian 3.2 compatibility (requiring Hessian 3.2 or above now)
|
||||
* updated Tiles support for Tiles 2.1 compatibility (requiring Tiles 2.1.2 or above now)
|
||||
* Velocity/FreeMarker/TilesViewResolver only returns a view if the target resource exists now
|
||||
* @DirtiesContext is now supported at the test class level with configurable class modes
|
||||
* added beforeTestClass() and afterTestClass() to the TestExecutionListener API
|
||||
* ProfileValueUtils now enforces class-level overrides for @IfProfileValue
|
||||
* @ContextConfiguration's loader attribute is now inherited if not declared locally
|
||||
* TransactionalTestExecutionListener no longer flushes transactions before rolling back
|
||||
|
||||
|
||||
Changes in version 3.0.0.M3 (2009-05-06)
|
||||
----------------------------------------
|
||||
|
||||
* Spring 3.0 includes reference documentation now
|
||||
* Spring 3.0 is shipping with proper Maven POMs now
|
||||
* updated to JRuby 1.2 (remaining compatible with JRuby 1.1 and above)
|
||||
* updated to Hessian 3.2.1 (remaining compatible with Hessian 3.1.3 and above)
|
||||
* updated to FreeMarker 2.3.15 (for exposure of FreeMarkerServlet-style HTTP scopes)
|
||||
* removed Axis 1.x support package, keeping basic JAX-RPC support only (next to JAX-WS)
|
||||
* introduced explicit XML array element in spring-beans-3.0.xsd
|
||||
* introduced new type conversion SPI and converter API in spring-core convert package
|
||||
* introduced annotated @Bean factory methods and JavaConfig-style @Configuration classes
|
||||
* introduced @Primary, @Lazy and @DependsOn annotations for scanned components
|
||||
* custom stereotype annotations can be meta-annotated with @Service, @Controller etc as well
|
||||
* @Scope and @Transactional are now supported as meta-annotations on custom annotations
|
||||
* @Autowired uses field/parameter name as fallback qualifier value
|
||||
* qualifier annotations can be used at method level as well (applying to all parameters)
|
||||
* @Value annotation can be used at method level as well (e.g. on bean property setters)
|
||||
* @Value values may use ${...} placeholders (driven by PropertyPlaceholderConfigurer)
|
||||
* @Resource names may use ${...} placeholders (driven by PropertyPlaceholderConfigurer)
|
||||
* fixed EL evaluation of prepared constructor arguments for repeated prototype creation
|
||||
* ConstructorArgumentValues exposed indexed arguments in the order of definition
|
||||
* AutowiredAnnotationBeanPostProcessor calculates cached arguments in a synchronized block
|
||||
* declarative destroy-method="..." specifications get validated at bean creation time
|
||||
* component-scan's "base-package" attribute supports spaces as separators as well
|
||||
* CachedIntrospectionResults always caches bean classes except in case of custom BeanInfo
|
||||
* GenericTypeResolver's type variable cache uses weak values (for OSGi compatibility)
|
||||
* fixed CachingMapDecorator to support garbage-collected weak references (again)
|
||||
* AOP ProxyFactory excludes non-public interfaces when autodetecting proxy interfaces
|
||||
* added DuplicateKeyException to DAO exception hierachy
|
||||
* added EmbeddedDatabase support in spring-jdbc embedded package, with initial HSQL support
|
||||
* SessionAwareMessageListener supports generic declaration of concrete JMS Message type
|
||||
* RmiServiceExporter and RmiRegistryFactoryBean synchronize registry lookup/creation
|
||||
* added "unregisterManagedResource" method to MBeanExporter/MBeanExportOperations
|
||||
* TimerTaskExecutor creates non-daemon Timer and uses bean name as default Timer name
|
||||
* added TaskScheduler interface and Trigger abstraction
|
||||
* added ConcurrentTaskScheduler and ThreadPoolTaskScheduler
|
||||
* added CommonJ TimerManagerTaskScheduler
|
||||
* added CronTrigger implementation for cron expression support
|
||||
* renamed "contextProperties" attribute to "contextParameters" (matching web.xml naming)
|
||||
* "contextParameters" contains Servlet/PortletConfig parameters as well
|
||||
* added default "servletContext" and "servletConfig" environment beans
|
||||
* added default "portletContext" and "portletConfig" environment beans
|
||||
* added default web scope "application", wrapping a ServletContext/PortletContext
|
||||
* JSF FacesContext and ExternalContext are resolvable dependencies by default, if available
|
||||
* FacesRequestAttributes (as used by RequestContextHolder) can access global Portlet session
|
||||
* revised @RequestMapping semantics for REST support purposes
|
||||
* request handler methods with @ModelAttribute annotation always return a model attribute
|
||||
* introduced @ExceptionHandler annotation for used in annotated web controllers
|
||||
* introduced ModelAndViewResolver SPI for custom handler method return types
|
||||
* FreeMarkerView can be initialized with ServletContext only (e.g. for testing)
|
||||
* MockPortletSession supports destruction of session attributes on invalidation
|
||||
* completed upgrade of the TestContext Framework to JUnit 4.5
|
||||
* SpringJUnit4ClassRunner subclasses can now override the default ContextLoader class
|
||||
* added "value" alias for @ContextConfiguration's "locations" attribute
|
||||
|
||||
|
||||
Changes in version 3.0.0.M2 (2009-02-25)
|
||||
----------------------------------------
|
||||
|
||||
* revised expression parser API design
|
||||
* added SimpleThreadScope implementation
|
||||
* refined OSGi version constraints for "javax.annotation" and "junit.framework"
|
||||
* "systemProperties" bean is not considered a default match for type Properties anymore
|
||||
* SimpleAliasRegistry's "getAliases" method returns transitive aliases now
|
||||
* SimpleAliasRegistry detects resolved aliases that loop back to the original name
|
||||
* PropertyPlaceholderConfigurer does not modify Map in case of equal String keys
|
||||
* improved NoClassDefFoundError handling during constructor resolution
|
||||
* inner class names in Java source style ("java.lang.Thread.State") supported as well
|
||||
* pre-converted property values are preserved more eagerly for re-created beans
|
||||
* prototype beans receive independent collection/array even when based on single value
|
||||
* registered plain singletons will be fully matched according to their qualifiers
|
||||
* @Qualifier value matching takes chained aliases of target beans into account as well
|
||||
* ASM-based AnnotationMetadata fully resolves class arguments and enums into Java types
|
||||
* ProceedingJoinPoint resolves parameter names using ASM-based parameter name discovery
|
||||
* MethodInvocations and ProceedingJoinPoints always expose original method (not bridge)
|
||||
* bridge method resolution works with Hibernate-generated CGLIB proxies as well
|
||||
* generic collection type resolution respects upper bound (e.g. ? extends Number) as well
|
||||
* TypeUtils detects variations of ParameterizedType/GenericArrayType assignability as well
|
||||
* ReflectionUtils findMethod detects methods on "java.lang.Object" as well
|
||||
* UrlResource eagerly closes HTTP connections in case of "getInputStream()" failure
|
||||
* PathMatchingResourcePatternResolver avoids NPE when initialized with null ClassLoader
|
||||
* all "taskExecutor" bean properties now accept any "java.util.concurrent.Executor"
|
||||
* added "Future submit(Runnable)" and "Future submit(Callable)" to AsyncTaskExecutor
|
||||
* SimpleAsyncTaskExecutor supports a custom "java.util.concurrent.ThreadFactory"
|
||||
* SchedulingTaskExecutor interface extends AsyncTaskExecutor now
|
||||
* added ThreadPoolExecutorFactoryBean (exposing the native ExecutorService interface)
|
||||
* added ExecutorServiceAdapter class as a standard wrapper for a Spring TaskExecutor
|
||||
* reduced backport-concurrent support to TaskExecutor adapters
|
||||
* added @Async annotation and AsyncAnnotationAdvisor (namespace support coming in M3)
|
||||
* EJB 3.1's @Asynchronous annotation gets detected and supported by default as well
|
||||
* ApplicationListener beans get obtained on demand, supporting non-singletons as well
|
||||
* ApplicationListeners will be called in the order according to the Ordered contract
|
||||
* generified ApplicationListener interface, narrowing the event type to be received
|
||||
* introduced SmartApplicationListener interface for supported event/source types
|
||||
* generified Transaction/Hibernate/Jdo/JpaCallback with generic "doInXxx" return type
|
||||
* HibernateOperations uses generic parameter/return types where possible
|
||||
* JdoOperations uses generic parameter/return types where possible (following JDO 2.1)
|
||||
* removed "flush" operation from JdoDialect (fully relying on JDO 2.0+ compliance now)
|
||||
* added JDO 2.1 compliant StandardPersistenceManagerProxy/SpringPersistenceManagerProxy
|
||||
* Spring-created EntityManagers support JPA 2.0 draft API ("unwrap", "getQueryBuilder")
|
||||
* Spring initiates JPA 2.0 query timeout with remaining Spring transaction timeout
|
||||
* added support for WebSphere's ResourceAdapter-managed messaging transactions
|
||||
* made SpringBeanAutowiringInterceptor callback signature compatible with WebSphere
|
||||
* WebSphereUowTransactionManager preserves original exception in case of rollback
|
||||
* added "flush()" method to TransactionStatus and TransactionSynchronization interfaces
|
||||
* test context manager automatically flushes transactions before rolling back
|
||||
* DefaultLobHandler uses explicit Blob/Clob access for reading when "wrapAsLob"=true
|
||||
* fixed JmsException/JmsUtils to fully avoid NPEs in case of cause messages being null
|
||||
* fixed MessageListenerAdapter's "getSubscriptionName()" to work without delegate as well
|
||||
* fixed HTTP invoker to support resolution of multi-level primitive array classes again
|
||||
* deprecated support for JMS 1.0.2 providers (JmsTemplate102 etc)
|
||||
* introduced top-level HTTP support package "org.springframework.http"
|
||||
* introduced RestTemplate facility in package "org.springframework.web.client"
|
||||
* introduced OXM support package (originating from Spring Web Services)
|
||||
* introduced OXM-based MarshallingMessageConverter for Spring JMS
|
||||
* introduced OXM-based MarshallingView for Spring MVC
|
||||
* refined @PathVariable handling in MVC handler methods
|
||||
* updated Spring Portlet MVC infrastructure and mocks for Portlet API 2.0
|
||||
* added resource and event methods to Portlet HandlerAdapter/HandlerInterceptor
|
||||
* added resolveException method for resource requests to HandlerExceptionResolver
|
||||
* introduced Resource/EventAwareController subinterfaces of Portlet Controller
|
||||
* introduced @Action/@Render/@Resource/@EventMapping annotations for Portlet MVC
|
||||
* added @RequestHeader support for Portlet MVC (based on Portlet request properties)
|
||||
* introduced @CookieValue annotation for Servlet and Portlet MVC handler methods
|
||||
* @RequestMapping type-level param constraints taken into account consistently
|
||||
* optional boolean parameters in MVC handler methods resolve to "false" if not present
|
||||
* "url" macro in "spring.ftl" performs standard Servlet URL encoding automatically
|
||||
|
||||
|
||||
Changes in version 3.0.0.M1 (2008-12-05)
|
||||
----------------------------------------
|
||||
|
||||
* revised project layout and build system (module-based sources, bundle repository)
|
||||
* updated entire codebase for Java 5 code style (generics, varargs, StringBuilder)
|
||||
* updated to JUnit 4.5 and JRuby 1.1
|
||||
* removed WebLogic 8.1 and WebSphere 5.1 support
|
||||
* removed native TopLink API support (superseded by JPA)
|
||||
* removed Commons Attributes support (superseded by Java 5 annotations)
|
||||
* removed Jakarta JSTL support for JSP 1.2 (superseded by JSP 2.0)
|
||||
* removed outdated Struts 1.x Action delegation support
|
||||
* removed ContextLoaderServlet and Log4jConfigServlet
|
||||
* deprecated form controller hierarchy in favor of @MVC form object handling
|
||||
* deprecated JUnit 3.8 test class hierarchy in favor of test context framework
|
||||
* revised TaskExecutor interface to extend "java.util.concurrent.Executor" now
|
||||
* introduced Spring EL parser in org.springframework.expression package
|
||||
* introduced #{...} expression support in bean definitions
|
||||
* introduced @Value annotation for embedded expression support
|
||||
* introduced @PathVariable annotation for MVC handler methods
|
||||
* introduced ShallowEtagHeaderFilter
|
||||
* introduced AbstractAtomFeedView and AbstractRssFeedView
|
||||
* introduced default value support for @RequestParam
|
||||
* introduced @RequestHeader annotation for MVC handler methods
|
||||
* introduced "spring:url" and "spring:param" JSP tags
|
||||
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -0,0 +1,22 @@
|
||||
======================================================================
|
||||
== NOTICE file corresponding to section 4 d of the Apache License, ==
|
||||
== Version 2.0, for the Spring Framework distribution. ==
|
||||
======================================================================
|
||||
|
||||
This product includes software developed by
|
||||
the Apache Software Foundation (http://www.apache.org).
|
||||
|
||||
The end-user documentation included with a redistribution, if any,
|
||||
must include the following acknowledgement:
|
||||
|
||||
"This product includes software developed by the Spring Framework
|
||||
Project (http://www.springframework.org)."
|
||||
|
||||
Alternately, this acknowledgement may appear in the software itself,
|
||||
if and wherever such third-party acknowledgements normally appear.
|
||||
|
||||
The names "Spring", "Spring Framework", and "Spring Web Flow" must
|
||||
not be used to endorse or promote products derived from this
|
||||
software without prior written permission. For written permission,
|
||||
please contact enquiries@springsource.com.
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
SPRING FRAMEWORK 3.0 RC2 (November 2009)
|
||||
-------------------------------------
|
||||
http://www.springframework.org
|
||||
|
||||
1. INTRODUCTION
|
||||
|
||||
This is the second release candidate of Spring 3.0, which is scheduled for final release in Q4 2009.
|
||||
It release is feature complete, but may still have some issues.
|
||||
|
||||
2. RELEASE NOTES
|
||||
|
||||
This release comes with complete reference documentation already. Consult the provided
|
||||
javadoc for technical details of specific packages and classes.
|
||||
|
||||
3. DISTRIBUTION JAR FILES
|
||||
|
||||
The Spring Framework module jar files can be found in the 'dist' directory. Note that
|
||||
this release does not contain a 'spring.jar' file anymore, in contrast to previous Spring
|
||||
generations. Furthermore, the jar file names follow bundle repository conventions now.
|
||||
|
||||
4. GETTING STARTED
|
||||
|
||||
A Getting Started guide is to be provided in time for Spring 3.0 GA. For the time being,
|
||||
please consult the blog examples at http://blog.springsource.com as well as the sections
|
||||
of interest in the reference documentation.
|
||||
@@ -1,120 +0,0 @@
|
||||
plugins {
|
||||
id 'io.freefair.aspectj' version '8.4' apply false
|
||||
// kotlinVersion is managed in gradle.properties
|
||||
id 'org.jetbrains.kotlin.plugin.serialization' version "${kotlinVersion}" apply false
|
||||
id 'org.jetbrains.dokka' version '1.8.20'
|
||||
id 'org.unbroken-dome.xjc' version '2.0.0' apply false
|
||||
id 'com.github.ben-manes.versions' version '0.49.0'
|
||||
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
|
||||
id 'de.undercouch.download' version '5.4.0'
|
||||
id 'me.champeau.jmh' version '0.7.2' apply false
|
||||
id 'me.champeau.mrjar' version '0.1.1'
|
||||
}
|
||||
|
||||
ext {
|
||||
moduleProjects = subprojects.findAll { it.name.startsWith("spring-") }
|
||||
javaProjects = subprojects.findAll { !it.name.startsWith("framework-") }
|
||||
}
|
||||
|
||||
description = "Spring Framework"
|
||||
|
||||
configure(allprojects) { project ->
|
||||
apply plugin: "org.springframework.build.localdev"
|
||||
group = "org.springframework"
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url "https://repo.spring.io/milestone"
|
||||
content {
|
||||
// Netty 5 optional support
|
||||
includeGroup 'io.projectreactor.netty'
|
||||
}
|
||||
}
|
||||
if (version.contains('-')) {
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
}
|
||||
if (version.endsWith('-SNAPSHOT')) {
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
}
|
||||
}
|
||||
configurations.all {
|
||||
resolutionStrategy {
|
||||
cacheChangingModulesFor 0, "seconds"
|
||||
cacheDynamicVersionsFor 0, "seconds"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configure(allprojects - project(":framework-platform")) {
|
||||
configurations {
|
||||
dependencyManagement {
|
||||
canBeConsumed = false
|
||||
canBeResolved = false
|
||||
visible = false
|
||||
}
|
||||
matching { it.name.endsWith("Classpath") }.all { it.extendsFrom(dependencyManagement) }
|
||||
}
|
||||
dependencies {
|
||||
dependencyManagement(enforcedPlatform(dependencies.project(path: ":framework-platform")))
|
||||
}
|
||||
}
|
||||
|
||||
configure([rootProject] + javaProjects) { project ->
|
||||
apply plugin: "java"
|
||||
apply plugin: "java-test-fixtures"
|
||||
apply plugin: 'org.springframework.build.conventions'
|
||||
apply from: "${rootDir}/gradle/toolchains.gradle"
|
||||
apply from: "${rootDir}/gradle/ide.gradle"
|
||||
|
||||
dependencies {
|
||||
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")
|
||||
// JSR-305 only used for non-required meta-annotations
|
||||
compileOnly("com.google.code.findbugs:jsr305")
|
||||
testCompileOnly("com.google.code.findbugs:jsr305")
|
||||
}
|
||||
|
||||
ext.javadocLinks = [
|
||||
"https://docs.oracle.com/en/java/javase/17/docs/api/",
|
||||
"https://jakarta.ee/specifications/platform/9/apidocs/",
|
||||
"https://docs.oracle.com/cd/E13222_01/wls/docs90/javadocs/", // CommonJ and weblogic.* packages
|
||||
"https://www.ibm.com/docs/api/v1/content/SSEQTP_8.5.5/com.ibm.websphere.javadoc.doc/web/apidocs/", // com.ibm.*
|
||||
"https://docs.jboss.org/jbossas/javadoc/4.0.5/connector/", // org.jboss.resource.*
|
||||
"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.2.x/current/httpclient5/apidocs/",
|
||||
"https://projectreactor.io/docs/test/release/api/",
|
||||
"https://junit.org/junit4/javadoc/4.13.2/",
|
||||
// TODO Uncomment link to JUnit 5 docs once we execute Gradle with Java 18+.
|
||||
// See https://github.com/spring-projects/spring-framework/issues/27497
|
||||
//
|
||||
// "https://junit.org/junit5/docs/5.10.1/api/",
|
||||
"https://www.reactive-streams.org/reactive-streams-1.0.3-javadoc/",
|
||||
//"https://javadoc.io/static/io.rsocket/rsocket-core/1.1.1/",
|
||||
"https://r2dbc.io/spec/1.0.0.RELEASE/api/",
|
||||
// Previously there could be a split-package issue between JSR250 and JSR305 javax.annotation packages,
|
||||
// but since 6.0 JSR 250 annotations such as @Resource and @PostConstruct have been replaced by their
|
||||
// JakartaEE equivalents in the jakarta.annotation package.
|
||||
//"https://www.javadoc.io/doc/com.google.code.findbugs/jsr305/3.0.2/"
|
||||
] as String[]
|
||||
}
|
||||
|
||||
configure(moduleProjects) { project ->
|
||||
apply from: "${rootDir}/gradle/spring-module.gradle"
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
version=3.0.0
|
||||
build.stamp=RC2
|
||||
release.type=milestone
|
||||
natural.name=spring-framework
|
||||
project.name=Spring Framework
|
||||
project.key=SPR
|
||||
ivy.cache.dir=${basedir}/../ivy-cache
|
||||
integration.repo.dir=${basedir}/../integration-repo
|
||||
javadoc.exclude.package.names=org/springframework/samples/**
|
||||
javadoc.max.memory=256M
|
||||
test.vm.args=-Xmx1024M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError
|
||||
compiler.args=-enableJavadoc -warn:none
|
||||
|
||||
# For when releasing
|
||||
#release.type=release
|
||||
#build.stamp=RELEASE
|
||||
|
||||
# For when releasing milestones
|
||||
#release.type=milestone
|
||||
#build.stamp=M1
|
||||
|
||||
# For development in trunk
|
||||
#release.type=integration
|
||||
#build.stamp=BUILD-SNAPSHOT
|
||||
@@ -0,0 +1,2 @@
|
||||
org.testng.version=5.10.0
|
||||
org.junit.version=4.7.0
|
||||
@@ -1,60 +0,0 @@
|
||||
# Spring Framework Build
|
||||
|
||||
This folder contains the custom plugins and conventions for the Spring Framework build.
|
||||
They are declared in the `build.gradle` file in this folder.
|
||||
|
||||
## Build Conventions
|
||||
|
||||
The `org.springframework.build.conventions` plugin applies all conventions to the Framework build:
|
||||
|
||||
* Configuring the Java compiler, see `JavaConventions`
|
||||
* Configuring the Kotlin compiler, see `KotlinConventions`
|
||||
* Configuring testing in the build with `TestConventions`
|
||||
|
||||
|
||||
## Build Plugins
|
||||
|
||||
### Optional dependencies
|
||||
|
||||
The `org.springframework.build.optional-dependencies` plugin creates a new `optional`
|
||||
Gradle configuration - it adds the dependencies to the project's compile and runtime classpath
|
||||
but doesn't affect the classpath of dependent projects.
|
||||
This plugin does not provide a `provided` configuration, as the native `compileOnly` and `testCompileOnly`
|
||||
configurations are preferred.
|
||||
|
||||
|
||||
### RuntimeHints Java Agent
|
||||
|
||||
The `spring-core-test` project module contributes the `RuntimeHintsAgent` Java agent.
|
||||
|
||||
The `RuntimeHintsAgentPlugin` Gradle plugin creates a dedicated `"runtimeHintsTest"` test task for each project.
|
||||
This task will detect and execute [tests tagged](https://junit.org/junit5/docs/current/user-guide/#running-tests-build-gradle)
|
||||
with the `"RuntimeHintsTests"` [JUnit tag](https://junit.org/junit5/docs/current/user-guide/#running-tests-tags).
|
||||
In the Spring Framework test suite, those are usually annotated with the `@EnabledIfRuntimeHintsAgent` annotation.
|
||||
|
||||
By default, the agent will instrument all classes located in the `"org.springframework"` package, as they are loaded.
|
||||
The `RuntimeHintsAgentExtension` allows to customize this using a DSL:
|
||||
|
||||
```groovy
|
||||
// this applies the `RuntimeHintsAgentPlugin` to the project
|
||||
plugins {
|
||||
id 'org.springframework.build.runtimehints-agent'
|
||||
}
|
||||
|
||||
// You can configure the agent to include and exclude packages from the instrumentation process.
|
||||
runtimeHintsAgent {
|
||||
includedPackages = ["org.springframework", "io.spring"]
|
||||
excludedPackages = ["org.example"]
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// to use the test infrastructure, the project should also depend on the "spring-core-test" module
|
||||
testImplementation(project(":spring-core-test"))
|
||||
}
|
||||
```
|
||||
|
||||
With this configuration, `./gradlew runtimeHintsTest` will run all tests instrumented by this java agent.
|
||||
The global `./gradlew check` task depends on `runtimeHintsTest`.
|
||||
|
||||
NOTE: the "spring-core-test" module doesn't shade "spring-core" by design, so the agent should never instrument
|
||||
code that doesn't have "spring-core" on its classpath.
|
||||
@@ -1,48 +0,0 @@
|
||||
plugins {
|
||||
id 'java-gradle-plugin'
|
||||
id 'checkstyle'
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
|
||||
ext {
|
||||
def propertiesFile = new File(new File("$projectDir").parentFile, "gradle.properties")
|
||||
propertiesFile.withInputStream {
|
||||
def properties = new Properties()
|
||||
properties.load(it)
|
||||
set("kotlinVersion", properties["kotlinVersion"])
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
checkstyle "io.spring.javaformat:spring-javaformat-checkstyle:${javaFormatVersion}"
|
||||
implementation "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}"
|
||||
implementation "org.jetbrains.kotlin:kotlin-compiler-embeddable:${kotlinVersion}"
|
||||
implementation "org.gradle:test-retry-gradle-plugin:1.5.6"
|
||||
implementation "io.spring.javaformat:spring-javaformat-gradle-plugin:${javaFormatVersion}"
|
||||
implementation "io.spring.nohttp:nohttp-gradle:0.0.11"
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
plugins {
|
||||
conventionsPlugin {
|
||||
id = "org.springframework.build.conventions"
|
||||
implementationClass = "org.springframework.build.ConventionsPlugin"
|
||||
}
|
||||
localDevPlugin {
|
||||
id = "org.springframework.build.localdev"
|
||||
implementationClass = "org.springframework.build.dev.LocalDevelopmentPlugin"
|
||||
}
|
||||
optionalDependenciesPlugin {
|
||||
id = "org.springframework.build.optional-dependencies"
|
||||
implementationClass = "org.springframework.build.optional.OptionalDependenciesPlugin"
|
||||
}
|
||||
runtimeHintsAgentPlugin {
|
||||
id = "org.springframework.build.runtimehints-agent"
|
||||
implementationClass = "org.springframework.build.hint.RuntimeHintsAgentPlugin"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module PUBLIC "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN" "https://checkstyle.org/dtds/configuration_1_3.dtd">
|
||||
<module name="com.puppycrawl.tools.checkstyle.Checker">
|
||||
|
||||
<!-- Root Checks -->
|
||||
<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-20\d\d"/>
|
||||
<property name="packageInfoHeaderType" value="none"/>
|
||||
</module>
|
||||
<module name="com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheck"/>
|
||||
|
||||
<!-- TreeWalker Checks -->
|
||||
<module name="com.puppycrawl.tools.checkstyle.TreeWalker">
|
||||
|
||||
<!-- Imports -->
|
||||
<module name="com.puppycrawl.tools.checkstyle.checks.imports.UnusedImportsCheck">
|
||||
<property name="processJavadoc" value="true"/>
|
||||
</module>
|
||||
|
||||
<!-- Modifiers -->
|
||||
<module name="com.puppycrawl.tools.checkstyle.checks.modifier.ModifierOrderCheck"/>
|
||||
|
||||
</module>
|
||||
|
||||
</module>
|
||||
@@ -1,2 +0,0 @@
|
||||
org.gradle.caching=true
|
||||
javaFormatVersion=0.0.39
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.build;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import io.spring.javaformat.gradle.SpringJavaFormatPlugin;
|
||||
import io.spring.nohttp.gradle.NoHttpExtension;
|
||||
import io.spring.nohttp.gradle.NoHttpPlugin;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.DependencySet;
|
||||
import org.gradle.api.plugins.JavaBasePlugin;
|
||||
import org.gradle.api.plugins.quality.Checkstyle;
|
||||
import org.gradle.api.plugins.quality.CheckstyleExtension;
|
||||
import org.gradle.api.plugins.quality.CheckstylePlugin;
|
||||
|
||||
/**
|
||||
* {@link Plugin} that applies conventions for checkstyle.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
public class CheckstyleConventions {
|
||||
|
||||
/**
|
||||
* Applies the Spring Java Format and Checkstyle plugins with the project conventions.
|
||||
* @param project the current project
|
||||
*/
|
||||
public void apply(Project project) {
|
||||
project.getPlugins().withType(JavaBasePlugin.class, (java) -> {
|
||||
if (project.getRootProject() == project) {
|
||||
configureNoHttpPlugin(project);
|
||||
}
|
||||
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.12.5");
|
||||
checkstyle.getConfigDirectory().set(project.getRootProject().file("src/checkstyle"));
|
||||
String version = SpringJavaFormatPlugin.class.getPackage().getImplementationVersion();
|
||||
DependencySet checkstyleDependencies = project.getConfigurations().getByName("checkstyle").getDependencies();
|
||||
checkstyleDependencies
|
||||
.add(project.getDependencies().create("io.spring.javaformat:spring-javaformat-checkstyle:" + version));
|
||||
});
|
||||
}
|
||||
|
||||
private static void configureNoHttpPlugin(Project project) {
|
||||
project.getPlugins().apply(NoHttpPlugin.class);
|
||||
NoHttpExtension noHttp = project.getExtensions().getByType(NoHttpExtension.class);
|
||||
noHttp.setAllowlistFile(project.file("src/nohttp/allowlist.lines"));
|
||||
noHttp.getSource().exclude("**/test-output/**", "**/.settings/**",
|
||||
"**/.classpath", "**/.project", "**/.gradle/**");
|
||||
List<String> buildFolders = List.of("bin", "build", "out");
|
||||
project.allprojects(subproject -> {
|
||||
Path rootPath = project.getRootDir().toPath();
|
||||
Path projectPath = rootPath.relativize(subproject.getProjectDir().toPath());
|
||||
for (String buildFolder : buildFolders) {
|
||||
Path innerBuildDir = projectPath.resolve(buildFolder);
|
||||
noHttp.getSource().exclude(innerBuildDir + File.separator + "**");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.build;
|
||||
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.plugins.JavaBasePlugin;
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinBasePlugin;
|
||||
|
||||
/**
|
||||
* Plugin to apply conventions to projects that are part of Spring Framework's build.
|
||||
* Conventions are applied in response to various plugins being applied.
|
||||
*
|
||||
* <p>When the {@link JavaBasePlugin} is applied, the conventions in {@link CheckstyleConventions},
|
||||
* {@link TestConventions} and {@link JavaConventions} are applied.
|
||||
* When the {@link KotlinBasePlugin} is applied, the conventions in {@link KotlinConventions}
|
||||
* are applied.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
public class ConventionsPlugin implements Plugin<Project> {
|
||||
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
new CheckstyleConventions().apply(project);
|
||||
new JavaConventions().apply(project);
|
||||
new KotlinConventions().apply(project);
|
||||
new TestConventions().apply(project);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.build;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.plugins.JavaBasePlugin;
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.gradle.api.plugins.JavaPluginExtension;
|
||||
import org.gradle.api.tasks.compile.JavaCompile;
|
||||
import org.gradle.jvm.toolchain.JavaLanguageVersion;
|
||||
import org.gradle.jvm.toolchain.JvmVendorSpec;
|
||||
|
||||
/**
|
||||
* {@link Plugin} that applies conventions for compiling Java sources in Spring Framework.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @author Sam Brannen
|
||||
* @author Sebastien Deleuze
|
||||
*/
|
||||
public class JavaConventions {
|
||||
|
||||
private static final List<String> COMPILER_ARGS;
|
||||
|
||||
private static final List<String> TEST_COMPILER_ARGS;
|
||||
|
||||
static {
|
||||
List<String> commonCompilerArgs = Arrays.asList(
|
||||
"-Xlint:serial", "-Xlint:cast", "-Xlint:classfile", "-Xlint:dep-ann",
|
||||
"-Xlint:divzero", "-Xlint:empty", "-Xlint:finally", "-Xlint:overrides",
|
||||
"-Xlint:path", "-Xlint:processing", "-Xlint:static", "-Xlint:try", "-Xlint:-options",
|
||||
"-parameters"
|
||||
);
|
||||
COMPILER_ARGS = new ArrayList<>();
|
||||
COMPILER_ARGS.addAll(commonCompilerArgs);
|
||||
COMPILER_ARGS.addAll(Arrays.asList(
|
||||
"-Xlint:varargs", "-Xlint:fallthrough", "-Xlint:rawtypes", "-Xlint:deprecation",
|
||||
"-Xlint:unchecked", "-Werror"
|
||||
));
|
||||
TEST_COMPILER_ARGS = new ArrayList<>();
|
||||
TEST_COMPILER_ARGS.addAll(commonCompilerArgs);
|
||||
TEST_COMPILER_ARGS.addAll(Arrays.asList("-Xlint:-varargs", "-Xlint:-fallthrough", "-Xlint:-rawtypes",
|
||||
"-Xlint:-deprecation", "-Xlint:-unchecked"));
|
||||
}
|
||||
|
||||
public void apply(Project project) {
|
||||
project.getPlugins().withType(JavaBasePlugin.class, javaPlugin -> applyJavaCompileConventions(project));
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the common Java compiler options for main sources, test fixture sources, and
|
||||
* test sources.
|
||||
* @param project the current project
|
||||
*/
|
||||
private void applyJavaCompileConventions(Project project) {
|
||||
project.getExtensions().getByType(JavaPluginExtension.class).toolchain(toolchain -> {
|
||||
toolchain.getVendor().set(JvmVendorSpec.BELLSOFT);
|
||||
toolchain.getLanguageVersion().set(JavaLanguageVersion.of(17));
|
||||
});
|
||||
project.getTasks().withType(JavaCompile.class)
|
||||
.matching(compileTask -> compileTask.getName().equals(JavaPlugin.COMPILE_JAVA_TASK_NAME))
|
||||
.forEach(compileTask -> {
|
||||
compileTask.getOptions().setCompilerArgs(COMPILER_ARGS);
|
||||
compileTask.getOptions().setEncoding("UTF-8");
|
||||
});
|
||||
project.getTasks().withType(JavaCompile.class)
|
||||
.matching(compileTask -> compileTask.getName().equals(JavaPlugin.COMPILE_TEST_JAVA_TASK_NAME)
|
||||
|| compileTask.getName().equals("compileTestFixturesJava"))
|
||||
.forEach(compileTask -> {
|
||||
compileTask.getOptions().setCompilerArgs(TEST_COMPILER_ARGS);
|
||||
compileTask.getOptions().setEncoding("UTF-8");
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.build;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions;
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile;
|
||||
|
||||
/**
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
public class KotlinConventions {
|
||||
|
||||
void apply(Project project) {
|
||||
project.getPlugins().withId("org.jetbrains.kotlin.jvm",
|
||||
(plugin) -> project.getTasks().withType(KotlinCompile.class, this::configure));
|
||||
}
|
||||
|
||||
private void configure(KotlinCompile compile) {
|
||||
KotlinJvmOptions kotlinOptions = compile.getKotlinOptions();
|
||||
kotlinOptions.setApiVersion("1.7");
|
||||
kotlinOptions.setLanguageVersion("1.7");
|
||||
kotlinOptions.setJvmTarget("17");
|
||||
kotlinOptions.setJavaParameters(true);
|
||||
kotlinOptions.setAllWarningsAsErrors(true);
|
||||
List<String> freeCompilerArgs = new ArrayList<>(compile.getKotlinOptions().getFreeCompilerArgs());
|
||||
freeCompilerArgs.addAll(List.of("-Xsuppress-version-warnings", "-Xjsr305=strict", "-opt-in=kotlin.RequiresOptIn"));
|
||||
compile.getKotlinOptions().setFreeCompilerArgs(freeCompilerArgs);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.build;
|
||||
|
||||
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.testretry.TestRetryPlugin;
|
||||
import org.gradle.testretry.TestRetryTaskExtension;
|
||||
|
||||
/**
|
||||
* Conventions that are applied in the presence of the {@link JavaBasePlugin}. When the
|
||||
* plugin is applied:
|
||||
* <ul>
|
||||
* <li>The {@link TestRetryPlugin Test Retry} plugin is applied so that flaky tests
|
||||
* are retried 3 times when running on the CI server.
|
||||
* </ul>
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class TestConventions {
|
||||
|
||||
void apply(Project project) {
|
||||
project.getPlugins().withType(JavaBasePlugin.class, (java) -> configureTestConventions(project));
|
||||
}
|
||||
|
||||
private void configureTestConventions(Project project) {
|
||||
project.getTasks().withType(Test.class,
|
||||
test -> {
|
||||
configureTests(project, test);
|
||||
configureTestRetryPlugin(project, test);
|
||||
});
|
||||
}
|
||||
|
||||
private void configureTests(Project project, Test test) {
|
||||
test.useJUnitPlatform();
|
||||
test.include("**/*Tests.class", "**/*Test.class");
|
||||
test.setSystemProperties(Map.of(
|
||||
"java.awt.headless", "true",
|
||||
"io.netty.leakDetection.level", "paranoid",
|
||||
"io.netty5.leakDetectionLevel", "paranoid",
|
||||
"io.netty5.leakDetection.targetRecords", "32",
|
||||
"io.netty5.buffer.lifecycleTracingEnabled", "true"
|
||||
));
|
||||
if (project.hasProperty("testGroups")) {
|
||||
test.systemProperty("testGroups", project.getProperties().get("testGroups"));
|
||||
}
|
||||
test.jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED",
|
||||
"--add-opens=java.base/java.util=ALL-UNNAMED",
|
||||
"-Djava.locale.providers=COMPAT");
|
||||
}
|
||||
|
||||
private void configureTestRetryPlugin(Project project, Test test) {
|
||||
project.getPlugins().withType(TestRetryPlugin.class, testRetryPlugin -> {
|
||||
TestRetryTaskExtension testRetry = test.getExtensions().getByType(TestRetryTaskExtension.class);
|
||||
testRetry.getFailOnPassedAfterRetry().set(true);
|
||||
testRetry.getMaxRetries().set(isCi() ? 3 : 0);
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isCi() {
|
||||
return Boolean.parseBoolean(System.getenv("CI"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.build.dev;
|
||||
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.plugins.JavaBasePlugin;
|
||||
|
||||
/**
|
||||
* {@link Plugin} that skips documentation tasks when the {@code "-PskipDocs"} property is defined.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
public class LocalDevelopmentPlugin implements Plugin<Project> {
|
||||
|
||||
private static final String SKIP_DOCS_PROPERTY = "skipDocs";
|
||||
|
||||
@Override
|
||||
public void apply(Project target) {
|
||||
if (target.hasProperty(SKIP_DOCS_PROPERTY)) {
|
||||
skipDocumentationTasks(target);
|
||||
target.subprojects(this::skipDocumentationTasks);
|
||||
}
|
||||
}
|
||||
|
||||
private void skipDocumentationTasks(Project project) {
|
||||
project.afterEvaluate(p -> {
|
||||
p.getTasks().matching(task -> {
|
||||
return JavaBasePlugin.DOCUMENTATION_GROUP.equals(task.getGroup())
|
||||
|| "distribution".equals(task.getGroup());
|
||||
})
|
||||
.forEach(task -> task.setEnabled(false));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.build.hint;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.gradle.api.file.ConfigurableFileCollection;
|
||||
import org.gradle.api.provider.SetProperty;
|
||||
import org.gradle.api.tasks.Classpath;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.process.CommandLineArgumentProvider;
|
||||
|
||||
/**
|
||||
* Argument provider for registering the runtime hints agent with a Java process.
|
||||
*/
|
||||
public interface RuntimeHintsAgentArgumentProvider extends CommandLineArgumentProvider {
|
||||
|
||||
@Classpath
|
||||
ConfigurableFileCollection getAgentJar();
|
||||
|
||||
@Input
|
||||
SetProperty<String> getIncludedPackages();
|
||||
|
||||
@Input
|
||||
SetProperty<String> getExcludedPackages();
|
||||
|
||||
@Override
|
||||
default Iterable<String> asArguments() {
|
||||
StringBuilder packages = new StringBuilder();
|
||||
getIncludedPackages().get().forEach(packageName -> packages.append('+').append(packageName).append(','));
|
||||
getExcludedPackages().get().forEach(packageName -> packages.append('-').append(packageName).append(','));
|
||||
return Collections.singleton("-javaagent:" + getAgentJar().getSingleFile() + "=" + packages);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.build.hint;
|
||||
|
||||
import org.gradle.api.provider.SetProperty;
|
||||
|
||||
/**
|
||||
* Entry point to the DSL extension for the {@link RuntimeHintsAgentPlugin} Gradle plugin.
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
public interface RuntimeHintsAgentExtension {
|
||||
|
||||
SetProperty<String> getIncludedPackages();
|
||||
|
||||
SetProperty<String> getExcludedPackages();
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.build.hint;
|
||||
|
||||
import org.gradle.api.JavaVersion;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.attributes.Bundling;
|
||||
import org.gradle.api.attributes.Category;
|
||||
import org.gradle.api.attributes.LibraryElements;
|
||||
import org.gradle.api.attributes.Usage;
|
||||
import org.gradle.api.attributes.java.TargetJvmVersion;
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.gradle.api.tasks.testing.Test;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* {@link Plugin} that configures the {@code RuntimeHints} Java agent to test tasks.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @author Sebastien Deleuze
|
||||
*/
|
||||
public class RuntimeHintsAgentPlugin implements Plugin<Project> {
|
||||
|
||||
public static final String RUNTIMEHINTS_TEST_TASK = "runtimeHintsTest";
|
||||
private static final String EXTENSION_NAME = "runtimeHintsAgent";
|
||||
private static final String CONFIGURATION_NAME = "testRuntimeHintsAgentJar";
|
||||
|
||||
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
|
||||
project.getPlugins().withType(JavaPlugin.class, javaPlugin -> {
|
||||
RuntimeHintsAgentExtension agentExtension = createRuntimeHintsAgentExtension(project);
|
||||
Test agentTest = project.getTasks().create(RUNTIMEHINTS_TEST_TASK, Test.class, test -> {
|
||||
test.useJUnitPlatform(options -> {
|
||||
options.includeTags("RuntimeHintsTests");
|
||||
});
|
||||
test.include("**/*Tests.class", "**/*Test.class");
|
||||
test.systemProperty("java.awt.headless", "true");
|
||||
test.systemProperty("org.graalvm.nativeimage.imagecode", "runtime");
|
||||
test.getJvmArgumentProviders().add(createRuntimeHintsAgentArgumentProvider(project, agentExtension));
|
||||
});
|
||||
project.getTasks().getByName("check", task -> task.dependsOn(agentTest));
|
||||
project.getDependencies().add(CONFIGURATION_NAME, project.project(":spring-core-test"));
|
||||
});
|
||||
}
|
||||
|
||||
private static RuntimeHintsAgentExtension createRuntimeHintsAgentExtension(Project project) {
|
||||
RuntimeHintsAgentExtension agentExtension = project.getExtensions().create(EXTENSION_NAME, RuntimeHintsAgentExtension.class);
|
||||
agentExtension.getIncludedPackages().convention(Collections.singleton("org.springframework"));
|
||||
agentExtension.getExcludedPackages().convention(Collections.emptySet());
|
||||
return agentExtension;
|
||||
}
|
||||
|
||||
private static RuntimeHintsAgentArgumentProvider createRuntimeHintsAgentArgumentProvider(
|
||||
Project project, RuntimeHintsAgentExtension agentExtension) {
|
||||
RuntimeHintsAgentArgumentProvider agentArgumentProvider = project.getObjects().newInstance(RuntimeHintsAgentArgumentProvider.class);
|
||||
agentArgumentProvider.getAgentJar().from(createRuntimeHintsAgentConfiguration(project));
|
||||
agentArgumentProvider.getIncludedPackages().set(agentExtension.getIncludedPackages());
|
||||
agentArgumentProvider.getExcludedPackages().set(agentExtension.getExcludedPackages());
|
||||
return agentArgumentProvider;
|
||||
}
|
||||
|
||||
private static Configuration createRuntimeHintsAgentConfiguration(Project project) {
|
||||
return project.getConfigurations().create(CONFIGURATION_NAME, configuration -> {
|
||||
configuration.setCanBeConsumed(false);
|
||||
configuration.setTransitive(false); // Only the built artifact is required
|
||||
configuration.attributes(attributes -> {
|
||||
attributes.attribute(Bundling.BUNDLING_ATTRIBUTE, project.getObjects().named(Bundling.class, Bundling.EXTERNAL));
|
||||
attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.getObjects().named(Category.class, Category.LIBRARY));
|
||||
attributes.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.getObjects().named(LibraryElements.class, LibraryElements.JAR));
|
||||
attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, Integer.valueOf(JavaVersion.current().getMajorVersion()));
|
||||
attributes.attribute(Usage.USAGE_ATTRIBUTE, project.getObjects().named(Usage.class, Usage.JAVA_RUNTIME));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.build.optional;
|
||||
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.plugins.JavaBasePlugin;
|
||||
import org.gradle.api.plugins.JavaPluginExtension;
|
||||
import org.gradle.api.tasks.SourceSetContainer;
|
||||
|
||||
/**
|
||||
* A {@code Plugin} that adds support for Maven-style optional dependencies. Creates a new
|
||||
* {@code optional} configuration. The {@code optional} configuration is part of the
|
||||
* project's compile and runtime classpaths but does not affect the classpath of
|
||||
* dependent projects.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class OptionalDependenciesPlugin implements Plugin<Project> {
|
||||
|
||||
/**
|
||||
* Name of the {@code optional} configuration.
|
||||
*/
|
||||
public static final String OPTIONAL_CONFIGURATION_NAME = "optional";
|
||||
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
Configuration optional = project.getConfigurations().create(OPTIONAL_CONFIGURATION_NAME);
|
||||
optional.setCanBeConsumed(false);
|
||||
optional.setCanBeResolved(false);
|
||||
project.getPlugins().withType(JavaBasePlugin.class, (javaBasePlugin) -> {
|
||||
SourceSetContainer sourceSets = project.getExtensions().getByType(JavaPluginExtension.class)
|
||||
.getSourceSets();
|
||||
sourceSets.all((sourceSet) -> {
|
||||
project.getConfigurations().getByName(sourceSet.getCompileClasspathConfigurationName()).extendsFrom(optional);
|
||||
project.getConfigurations().getByName(sourceSet.getRuntimeClasspathConfigurationName()).extendsFrom(optional);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.build.shadow;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.component.ModuleComponentSelector;
|
||||
import org.gradle.api.artifacts.query.ArtifactResolutionQuery;
|
||||
import org.gradle.api.artifacts.result.ArtifactResolutionResult;
|
||||
import org.gradle.api.artifacts.result.ComponentArtifactsResult;
|
||||
import org.gradle.api.artifacts.result.DependencyResult;
|
||||
import org.gradle.api.artifacts.result.ResolutionResult;
|
||||
import org.gradle.api.artifacts.result.ResolvedArtifactResult;
|
||||
import org.gradle.api.file.DirectoryProperty;
|
||||
import org.gradle.api.file.FileCopyDetails;
|
||||
import org.gradle.api.file.FileTree;
|
||||
import org.gradle.api.tasks.Classpath;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.Nested;
|
||||
import org.gradle.api.tasks.Optional;
|
||||
import org.gradle.api.tasks.OutputDirectory;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.gradle.jvm.JvmLibrary;
|
||||
import org.gradle.language.base.artifact.SourcesArtifact;
|
||||
|
||||
/**
|
||||
* Gradle task to add source from shadowed jars into our own source jars.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ShadowSource extends DefaultTask {
|
||||
|
||||
private final DirectoryProperty outputDirectory = getProject().getObjects().directoryProperty();
|
||||
|
||||
private List<Configuration> configurations = new ArrayList<>();
|
||||
|
||||
private final List<Relocation> relocations = new ArrayList<>();
|
||||
|
||||
|
||||
@Classpath
|
||||
@Optional
|
||||
public List<Configuration> getConfigurations() {
|
||||
return this.configurations;
|
||||
}
|
||||
|
||||
public void setConfigurations(List<Configuration> configurations) {
|
||||
this.configurations = configurations;
|
||||
}
|
||||
|
||||
@Nested
|
||||
public List<Relocation> getRelocations() {
|
||||
return this.relocations;
|
||||
}
|
||||
|
||||
public void relocate(String pattern, String destination) {
|
||||
this.relocations.add(new Relocation(pattern, destination));
|
||||
}
|
||||
|
||||
@OutputDirectory
|
||||
DirectoryProperty getOutputDirectory() {
|
||||
return this.outputDirectory;
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
void syncSourceJarFiles() {
|
||||
sync(getSourceJarFiles());
|
||||
}
|
||||
|
||||
private List<File> getSourceJarFiles() {
|
||||
List<File> sourceJarFiles = new ArrayList<>();
|
||||
for (Configuration configuration : this.configurations) {
|
||||
ResolutionResult resolutionResult = configuration.getIncoming().getResolutionResult();
|
||||
resolutionResult.getRootComponent().get().getDependencies().forEach(dependency -> {
|
||||
Set<ComponentArtifactsResult> artifactsResults = resolveSourceArtifacts(dependency);
|
||||
for (ComponentArtifactsResult artifactResult : artifactsResults) {
|
||||
artifactResult.getArtifacts(SourcesArtifact.class).forEach(sourceArtifact -> {
|
||||
sourceJarFiles.add(((ResolvedArtifactResult) sourceArtifact).getFile());
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
return Collections.unmodifiableList(sourceJarFiles);
|
||||
}
|
||||
|
||||
private Set<ComponentArtifactsResult> resolveSourceArtifacts(DependencyResult dependency) {
|
||||
ModuleComponentSelector componentSelector = (ModuleComponentSelector) dependency.getRequested();
|
||||
ArtifactResolutionQuery query = getProject().getDependencies().createArtifactResolutionQuery()
|
||||
.forModule(componentSelector.getGroup(), componentSelector.getModule(), componentSelector.getVersion());
|
||||
return executeQuery(query).getResolvedComponents();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private ArtifactResolutionResult executeQuery(ArtifactResolutionQuery query) {
|
||||
return query.withArtifacts(JvmLibrary.class, SourcesArtifact.class).execute();
|
||||
}
|
||||
|
||||
private void sync(List<File> sourceJarFiles) {
|
||||
getProject().sync(spec -> {
|
||||
spec.into(this.outputDirectory);
|
||||
spec.eachFile(this::relocateFile);
|
||||
spec.filter(this::transformContent);
|
||||
spec.exclude("META-INF/**");
|
||||
spec.setIncludeEmptyDirs(false);
|
||||
sourceJarFiles.forEach(sourceJar -> spec.from(zipTree(sourceJar)));
|
||||
});
|
||||
}
|
||||
|
||||
private void relocateFile(FileCopyDetails details) {
|
||||
String path = details.getPath();
|
||||
for (Relocation relocation : this.relocations) {
|
||||
path = relocation.relocatePath(path);
|
||||
}
|
||||
details.setPath(path);
|
||||
}
|
||||
|
||||
private String transformContent(String content) {
|
||||
for (Relocation relocation : this.relocations) {
|
||||
content = relocation.transformContent(content);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
private FileTree zipTree(File sourceJar) {
|
||||
return getProject().zipTree(sourceJar);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A single relocation.
|
||||
*/
|
||||
static class Relocation {
|
||||
|
||||
private final String pattern;
|
||||
|
||||
private final String pathPattern;
|
||||
|
||||
private final String destination;
|
||||
|
||||
private final String pathDestination;
|
||||
|
||||
|
||||
Relocation(String pattern, String destination) {
|
||||
this.pattern = pattern;
|
||||
this.pathPattern = pattern.replace('.', '/');
|
||||
this.destination = destination;
|
||||
this.pathDestination = destination.replace('.', '/');
|
||||
}
|
||||
|
||||
|
||||
@Input
|
||||
public String getPattern() {
|
||||
return this.pattern;
|
||||
}
|
||||
|
||||
@Input
|
||||
public String getDestination() {
|
||||
return this.destination;
|
||||
}
|
||||
|
||||
String relocatePath(String path) {
|
||||
return path.replace(this.pathPattern, this.pathDestination);
|
||||
}
|
||||
|
||||
public String transformContent(String content) {
|
||||
return content.replaceAll("\\b" + this.pattern, this.destination);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
# properties used by Bamboo build plan at http://build.springframework.org/build/admin/buildConfiguration.action?buildKey=SPR-TRUNKQUICK
|
||||
# run in conjunction with ANT_OPTS='-XX:MaxPermSize=512m -Xmx1024m'
|
||||
compiler.args=-enableJavadoc -warn:none
|
||||
java.awt.headless=true
|
||||
ci.build=true
|
||||
test.vm.args=-XX:MaxPermSize=512m -Xmx1024m
|
||||
@@ -1,57 +0,0 @@
|
||||
== Spring Framework Concourse pipeline
|
||||
|
||||
The Spring Framework uses https://concourse-ci.org/[Concourse] for its CI build and other automated tasks.
|
||||
The Spring team has a dedicated Concourse instance available at https://ci.spring.io with a build pipeline
|
||||
for https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-6.0.x[Spring Framework 6.0.x].
|
||||
|
||||
=== Setting up your development environment
|
||||
|
||||
If you're part of the Spring Framework project on GitHub, you can get access to CI management features.
|
||||
First, you need to go to https://ci.spring.io and install the client CLI for your platform (see bottom right of the screen).
|
||||
|
||||
You can then login with the instance using:
|
||||
|
||||
[source]
|
||||
----
|
||||
$ fly -t spring login -n spring-framework -c https://ci.spring.io
|
||||
----
|
||||
|
||||
Once logged in, you should get something like:
|
||||
|
||||
[source]
|
||||
----
|
||||
$ fly ts
|
||||
name url team expiry
|
||||
spring https://ci.spring.io spring-framework Wed, 25 Mar 2020 17:45:26 UTC
|
||||
----
|
||||
|
||||
=== Pipeline configuration and structure
|
||||
|
||||
The build pipelines are described in `pipeline.yml` file.
|
||||
|
||||
This file is listing Concourse resources, i.e. build inputs and outputs such as container images, artifact repositories, source repositories, notification services, etc.
|
||||
|
||||
It also describes jobs (a job is a sequence of inputs, tasks and outputs); jobs are organized by groups.
|
||||
|
||||
The `pipeline.yml` definition contains `((parameters))` which are loaded from the `parameters.yml` file or from our https://docs.cloudfoundry.org/credhub/[credhub instance].
|
||||
|
||||
You'll find in this folder the following resources:
|
||||
|
||||
* `pipeline.yml` the build pipeline
|
||||
* `parameters.yml` the build parameters used for the pipeline
|
||||
* `images/` holds the container images definitions used in this pipeline
|
||||
* `scripts/` holds the build scripts that ship within the CI container images
|
||||
* `tasks` contains the task definitions used in the main `pipeline.yml`
|
||||
|
||||
=== Updating the build pipeline
|
||||
|
||||
Updating files on the repository is not enough to update the build pipeline, as changes need to be applied.
|
||||
|
||||
The pipeline can be deployed using the following command:
|
||||
|
||||
[source]
|
||||
----
|
||||
$ fly -t spring set-pipeline -p spring-framework-6.0.x -c ci/pipeline.yml -l ci/parameters.yml
|
||||
----
|
||||
|
||||
NOTE: This assumes that you have credhub integration configured with the appropriate secrets.
|
||||
@@ -1,20 +0,0 @@
|
||||
changelog:
|
||||
repository: spring-projects/spring-framework
|
||||
sections:
|
||||
- title: ":star: New Features"
|
||||
labels:
|
||||
- "type: enhancement"
|
||||
- title: ":lady_beetle: Bug Fixes"
|
||||
labels:
|
||||
- "type: bug"
|
||||
- "type: regression"
|
||||
- title: ":notebook_with_decorative_cover: Documentation"
|
||||
labels:
|
||||
- "type: documentation"
|
||||
- title: ":hammer: Dependency Upgrades"
|
||||
sort: "title"
|
||||
labels:
|
||||
- "type: dependency-upgrade"
|
||||
contributors:
|
||||
exclude:
|
||||
names: ["bclozel", "jhoeller", "poutsma", "rstoyanchev", "sbrannen", "sdeleuze", "snicoll", "simonbasle"]
|
||||
@@ -1,10 +0,0 @@
|
||||
logging:
|
||||
level:
|
||||
io.spring.concourse: DEBUG
|
||||
spring:
|
||||
main:
|
||||
banner-mode: off
|
||||
sonatype:
|
||||
exclude:
|
||||
- 'build-info\.json'
|
||||
- '.*\.zip'
|
||||
@@ -1,21 +0,0 @@
|
||||
== CI Images
|
||||
|
||||
These images are used by CI to run the actual builds.
|
||||
|
||||
To build the image locally run the following from this directory:
|
||||
|
||||
----
|
||||
$ docker build --no-cache -f <image-folder>/Dockerfile .
|
||||
----
|
||||
|
||||
For example
|
||||
|
||||
----
|
||||
$ docker build --no-cache -f spring-framework-ci-image/Dockerfile .
|
||||
----
|
||||
|
||||
To test run:
|
||||
|
||||
----
|
||||
$ docker run -it --entrypoint /bin/bash <SHA>
|
||||
----
|
||||
@@ -1,12 +0,0 @@
|
||||
FROM ubuntu:jammy-20231128
|
||||
|
||||
ADD setup.sh /setup.sh
|
||||
ADD get-jdk-url.sh /get-jdk-url.sh
|
||||
RUN ./setup.sh
|
||||
|
||||
ENV JAVA_HOME /opt/openjdk/java17
|
||||
ENV JDK17 /opt/openjdk/java17
|
||||
ENV JDK21 /opt/openjdk/java21
|
||||
ENV JDK22 /opt/openjdk/java22
|
||||
|
||||
ENV PATH $JAVA_HOME/bin:$PATH
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
java17)
|
||||
echo "https://download.bell-sw.com/java/17.0.9+11/bellsoft-jdk17.0.9+11-linux-amd64.tar.gz"
|
||||
;;
|
||||
java21)
|
||||
echo "https://download.bell-sw.com/java/21.0.1+12/bellsoft-jdk21.0.1+12-linux-amd64.tar.gz"
|
||||
;;
|
||||
java22)
|
||||
echo "https://download.java.net/java/early_access/jdk22/27/GPL/openjdk-22-ea+27_linux-x64_bin.tar.gz"
|
||||
;;
|
||||
*)
|
||||
echo $"Unknown java version"
|
||||
exit 1
|
||||
esac
|
||||
@@ -1,40 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
###########################################################
|
||||
# UTILS
|
||||
###########################################################
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update
|
||||
apt-get install --no-install-recommends -y tzdata ca-certificates net-tools libxml2-utils git curl libudev1 libxml2-utils iptables iproute2 jq fontconfig
|
||||
ln -fs /usr/share/zoneinfo/UTC /etc/localtime
|
||||
dpkg-reconfigure --frontend noninteractive tzdata
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
curl https://raw.githubusercontent.com/spring-io/concourse-java-scripts/v0.0.4/concourse-java.sh > /opt/concourse-java.sh
|
||||
|
||||
###########################################################
|
||||
# JAVA
|
||||
###########################################################
|
||||
|
||||
mkdir -p /opt/openjdk
|
||||
pushd /opt/openjdk > /dev/null
|
||||
for jdk in java17 java21 java22
|
||||
do
|
||||
JDK_URL=$( /get-jdk-url.sh $jdk )
|
||||
mkdir $jdk
|
||||
pushd $jdk > /dev/null
|
||||
curl -L ${JDK_URL} | tar zx --strip-components=1
|
||||
test -f bin/java
|
||||
test -f bin/javac
|
||||
popd > /dev/null
|
||||
done
|
||||
popd
|
||||
|
||||
###########################################################
|
||||
# GRADLE ENTERPRISE
|
||||
###########################################################
|
||||
cd /
|
||||
mkdir ~/.gradle
|
||||
echo 'systemProp.user.name=concourse' > ~/.gradle/gradle.properties
|
||||
@@ -1,11 +0,0 @@
|
||||
github-repo: "https://github.com/spring-projects/spring-framework.git"
|
||||
github-repo-name: "spring-projects/spring-framework"
|
||||
sonatype-staging-profile: "org.springframework"
|
||||
docker-hub-organization: "springci"
|
||||
artifactory-server: "https://repo.spring.io"
|
||||
branch: "main"
|
||||
milestone: "6.1.x"
|
||||
build-name: "spring-framework"
|
||||
pipeline-name: "spring-framework"
|
||||
concourse-url: "https://ci.spring.io"
|
||||
task-timeout: 1h00m
|
||||
@@ -1,433 +0,0 @@
|
||||
anchors:
|
||||
git-repo-resource-source: &git-repo-resource-source
|
||||
uri: ((github-repo))
|
||||
username: ((github-username))
|
||||
password: ((github-ci-release-token))
|
||||
branch: ((branch))
|
||||
gradle-enterprise-task-params: &gradle-enterprise-task-params
|
||||
GRADLE_ENTERPRISE_ACCESS_KEY: ((gradle_enterprise_secret_access_key))
|
||||
GRADLE_ENTERPRISE_CACHE_USERNAME: ((gradle_enterprise_cache_user.username))
|
||||
GRADLE_ENTERPRISE_CACHE_PASSWORD: ((gradle_enterprise_cache_user.password))
|
||||
sonatype-task-params: &sonatype-task-params
|
||||
SONATYPE_USERNAME: ((sonatype-username))
|
||||
SONATYPE_PASSWORD: ((sonatype-password))
|
||||
SONATYPE_URL: ((sonatype-url))
|
||||
SONATYPE_STAGING_PROFILE: ((sonatype-staging-profile))
|
||||
artifactory-task-params: &artifactory-task-params
|
||||
ARTIFACTORY_SERVER: ((artifactory-server))
|
||||
ARTIFACTORY_USERNAME: ((artifactory-username))
|
||||
ARTIFACTORY_PASSWORD: ((artifactory-password))
|
||||
build-project-task-params: &build-project-task-params
|
||||
BRANCH: ((branch))
|
||||
<<: *gradle-enterprise-task-params
|
||||
docker-resource-source: &docker-resource-source
|
||||
username: ((docker-hub-username))
|
||||
password: ((docker-hub-password))
|
||||
slack-fail-params: &slack-fail-params
|
||||
text: >
|
||||
:concourse-failed: <https://ci.spring.io/teams/${BUILD_TEAM_NAME}/pipelines/${BUILD_PIPELINE_NAME}/jobs/${BUILD_JOB_NAME}/builds/${BUILD_NAME}|${BUILD_PIPELINE_NAME} ${BUILD_JOB_NAME} failed!>
|
||||
[$TEXT_FILE_CONTENT]
|
||||
text_file: git-repo/build/build-scan-uri.txt
|
||||
silent: true
|
||||
icon_emoji: ":concourse:"
|
||||
username: concourse-ci
|
||||
changelog-task-params: &changelog-task-params
|
||||
name: generated-changelog/tag
|
||||
tag: generated-changelog/tag
|
||||
body: generated-changelog/changelog.md
|
||||
github-task-params: &github-task-params
|
||||
GITHUB_USERNAME: ((github-username))
|
||||
GITHUB_TOKEN: ((github-ci-release-token))
|
||||
|
||||
resource_types:
|
||||
- name: registry-image
|
||||
type: registry-image
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: concourse/registry-image-resource
|
||||
tag: 1.8.0
|
||||
- name: artifactory-resource
|
||||
type: registry-image
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: springio/artifactory-resource
|
||||
tag: 0.0.18
|
||||
- name: github-release
|
||||
type: registry-image
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: concourse/github-release-resource
|
||||
tag: 1.8.0
|
||||
- name: github-status-resource
|
||||
type: registry-image
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: dpb587/github-status-resource
|
||||
tag: master
|
||||
- name: slack-notification
|
||||
type: registry-image
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: cfcommunity/slack-notification-resource
|
||||
tag: latest
|
||||
resources:
|
||||
- name: git-repo
|
||||
type: git
|
||||
icon: github
|
||||
source:
|
||||
<<: *git-repo-resource-source
|
||||
- name: ci-images-git-repo
|
||||
type: git
|
||||
icon: github
|
||||
source:
|
||||
uri: ((github-repo))
|
||||
branch: ((branch))
|
||||
paths: ["ci/images/*"]
|
||||
- name: ci-image
|
||||
type: registry-image
|
||||
icon: docker
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: ((docker-hub-organization))/spring-framework-ci
|
||||
tag: ((milestone))
|
||||
- name: every-morning
|
||||
type: time
|
||||
icon: alarm
|
||||
source:
|
||||
start: 8:00 AM
|
||||
stop: 9:00 AM
|
||||
location: Europe/Vienna
|
||||
- name: artifactory-repo
|
||||
type: artifactory-resource
|
||||
icon: package-variant
|
||||
source:
|
||||
uri: ((artifactory-server))
|
||||
username: ((artifactory-username))
|
||||
password: ((artifactory-password))
|
||||
build_name: ((build-name))
|
||||
- name: repo-status-build
|
||||
type: github-status-resource
|
||||
icon: eye-check-outline
|
||||
source:
|
||||
repository: ((github-repo-name))
|
||||
access_token: ((github-ci-status-token))
|
||||
branch: ((branch))
|
||||
context: build
|
||||
- name: repo-status-jdk21-build
|
||||
type: github-status-resource
|
||||
icon: eye-check-outline
|
||||
source:
|
||||
repository: ((github-repo-name))
|
||||
access_token: ((github-ci-status-token))
|
||||
branch: ((branch))
|
||||
context: jdk21-build
|
||||
- name: repo-status-jdk22-build
|
||||
type: github-status-resource
|
||||
icon: eye-check-outline
|
||||
source:
|
||||
repository: ((github-repo-name))
|
||||
access_token: ((github-ci-status-token))
|
||||
branch: ((branch))
|
||||
context: jdk22-build
|
||||
- name: slack-alert
|
||||
type: slack-notification
|
||||
icon: slack
|
||||
source:
|
||||
url: ((slack-webhook-url))
|
||||
- name: github-pre-release
|
||||
type: github-release
|
||||
icon: briefcase-download-outline
|
||||
source:
|
||||
owner: spring-projects
|
||||
repository: spring-framework
|
||||
access_token: ((github-ci-release-token))
|
||||
pre_release: true
|
||||
release: false
|
||||
- name: github-release
|
||||
type: github-release
|
||||
icon: briefcase-download
|
||||
source:
|
||||
owner: spring-projects
|
||||
repository: spring-framework
|
||||
access_token: ((github-ci-release-token))
|
||||
pre_release: false
|
||||
jobs:
|
||||
- name: build-ci-images
|
||||
plan:
|
||||
- get: git-repo
|
||||
- get: ci-images-git-repo
|
||||
trigger: true
|
||||
- task: build-ci-image
|
||||
privileged: true
|
||||
file: git-repo/ci/tasks/build-ci-image.yml
|
||||
output_mapping:
|
||||
image: ci-image
|
||||
vars:
|
||||
ci-image-name: ci-image
|
||||
<<: *docker-resource-source
|
||||
- put: ci-image
|
||||
params:
|
||||
image: ci-image/image.tar
|
||||
- name: build
|
||||
serial: true
|
||||
public: true
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
trigger: true
|
||||
- put: repo-status-build
|
||||
params: { state: "pending", commit: "git-repo" }
|
||||
- do:
|
||||
- task: build-project
|
||||
image: ci-image
|
||||
file: git-repo/ci/tasks/build-project.yml
|
||||
privileged: true
|
||||
timeout: ((task-timeout))
|
||||
params:
|
||||
<<: *build-project-task-params
|
||||
on_failure:
|
||||
do:
|
||||
- put: repo-status-build
|
||||
params: { state: "failure", commit: "git-repo" }
|
||||
- put: slack-alert
|
||||
params:
|
||||
<<: *slack-fail-params
|
||||
- put: repo-status-build
|
||||
params: { state: "success", commit: "git-repo" }
|
||||
- put: artifactory-repo
|
||||
params: &artifactory-params
|
||||
signing_key: ((signing-key))
|
||||
signing_passphrase: ((signing-passphrase))
|
||||
repo: libs-snapshot-local
|
||||
folder: distribution-repository
|
||||
build_uri: "https://ci.spring.io/teams/${BUILD_TEAM_NAME}/pipelines/${BUILD_PIPELINE_NAME}/jobs/${BUILD_JOB_NAME}/builds/${BUILD_NAME}"
|
||||
build_number: "${BUILD_PIPELINE_NAME}-${BUILD_JOB_NAME}-${BUILD_NAME}"
|
||||
disable_checksum_uploads: true
|
||||
threads: 8
|
||||
artifact_set:
|
||||
- include:
|
||||
- "/**/framework-api-*.zip"
|
||||
properties:
|
||||
"zip.name": "spring-framework"
|
||||
"zip.displayname": "Spring Framework"
|
||||
"zip.deployed": "false"
|
||||
- include:
|
||||
- "/**/framework-api-*-docs.zip"
|
||||
properties:
|
||||
"zip.type": "docs"
|
||||
- include:
|
||||
- "/**/framework-api-*-schema.zip"
|
||||
properties:
|
||||
"zip.type": "schema"
|
||||
get_params:
|
||||
threads: 8
|
||||
- name: jdk21-build
|
||||
serial: true
|
||||
public: true
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
- get: every-morning
|
||||
trigger: true
|
||||
- put: repo-status-jdk21-build
|
||||
params: { state: "pending", commit: "git-repo" }
|
||||
- do:
|
||||
- task: check-project
|
||||
image: ci-image
|
||||
file: git-repo/ci/tasks/check-project.yml
|
||||
privileged: true
|
||||
timeout: ((task-timeout))
|
||||
params:
|
||||
TEST_TOOLCHAIN: 21
|
||||
<<: *build-project-task-params
|
||||
on_failure:
|
||||
do:
|
||||
- put: repo-status-jdk21-build
|
||||
params: { state: "failure", commit: "git-repo" }
|
||||
- put: slack-alert
|
||||
params:
|
||||
<<: *slack-fail-params
|
||||
- put: repo-status-jdk21-build
|
||||
params: { state: "success", commit: "git-repo" }
|
||||
- name: jdk22-build
|
||||
serial: true
|
||||
public: true
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
- put: repo-status-jdk22-build
|
||||
params: { state: "pending", commit: "git-repo" }
|
||||
- do:
|
||||
- task: check-project
|
||||
image: ci-image
|
||||
file: git-repo/ci/tasks/check-project.yml
|
||||
privileged: true
|
||||
timeout: ((task-timeout))
|
||||
params:
|
||||
TEST_TOOLCHAIN: 22
|
||||
<<: *build-project-task-params
|
||||
on_failure:
|
||||
do:
|
||||
- put: repo-status-jdk22-build
|
||||
params: { state: "failure", commit: "git-repo" }
|
||||
- put: slack-alert
|
||||
params:
|
||||
<<: *slack-fail-params
|
||||
- put: repo-status-jdk22-build
|
||||
params: { state: "success", commit: "git-repo" }
|
||||
- name: stage-milestone
|
||||
serial: true
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
trigger: false
|
||||
- task: stage
|
||||
image: ci-image
|
||||
file: git-repo/ci/tasks/stage-version.yml
|
||||
params:
|
||||
RELEASE_TYPE: M
|
||||
<<: *gradle-enterprise-task-params
|
||||
- put: artifactory-repo
|
||||
params:
|
||||
<<: *artifactory-params
|
||||
repo: libs-staging-local
|
||||
- put: git-repo
|
||||
params:
|
||||
repository: stage-git-repo
|
||||
- name: promote-milestone
|
||||
serial: true
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
trigger: false
|
||||
- get: artifactory-repo
|
||||
trigger: false
|
||||
passed: [stage-milestone]
|
||||
params:
|
||||
download_artifacts: false
|
||||
save_build_info: true
|
||||
- task: promote
|
||||
file: git-repo/ci/tasks/promote-version.yml
|
||||
params:
|
||||
RELEASE_TYPE: M
|
||||
<<: *artifactory-task-params
|
||||
- task: generate-changelog
|
||||
file: git-repo/ci/tasks/generate-changelog.yml
|
||||
params:
|
||||
RELEASE_TYPE: M
|
||||
<<: *github-task-params
|
||||
<<: *docker-resource-source
|
||||
- put: github-pre-release
|
||||
params:
|
||||
<<: *changelog-task-params
|
||||
- name: stage-rc
|
||||
serial: true
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
trigger: false
|
||||
- task: stage
|
||||
image: ci-image
|
||||
file: git-repo/ci/tasks/stage-version.yml
|
||||
params:
|
||||
RELEASE_TYPE: RC
|
||||
<<: *gradle-enterprise-task-params
|
||||
- put: artifactory-repo
|
||||
params:
|
||||
<<: *artifactory-params
|
||||
repo: libs-staging-local
|
||||
- put: git-repo
|
||||
params:
|
||||
repository: stage-git-repo
|
||||
- name: promote-rc
|
||||
serial: true
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
trigger: false
|
||||
- get: artifactory-repo
|
||||
trigger: false
|
||||
passed: [stage-rc]
|
||||
params:
|
||||
download_artifacts: false
|
||||
save_build_info: true
|
||||
- task: promote
|
||||
file: git-repo/ci/tasks/promote-version.yml
|
||||
params:
|
||||
RELEASE_TYPE: RC
|
||||
<<: *docker-resource-source
|
||||
<<: *artifactory-task-params
|
||||
- task: generate-changelog
|
||||
file: git-repo/ci/tasks/generate-changelog.yml
|
||||
params:
|
||||
RELEASE_TYPE: RC
|
||||
<<: *github-task-params
|
||||
- put: github-pre-release
|
||||
params:
|
||||
<<: *changelog-task-params
|
||||
- name: stage-release
|
||||
serial: true
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
trigger: false
|
||||
- task: stage
|
||||
image: ci-image
|
||||
file: git-repo/ci/tasks/stage-version.yml
|
||||
params:
|
||||
RELEASE_TYPE: RELEASE
|
||||
<<: *gradle-enterprise-task-params
|
||||
- put: artifactory-repo
|
||||
params:
|
||||
<<: *artifactory-params
|
||||
repo: libs-staging-local
|
||||
- put: git-repo
|
||||
params:
|
||||
repository: stage-git-repo
|
||||
- name: promote-release
|
||||
serial: true
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
trigger: false
|
||||
- get: artifactory-repo
|
||||
trigger: false
|
||||
passed: [stage-release]
|
||||
params:
|
||||
download_artifacts: true
|
||||
save_build_info: true
|
||||
- task: promote
|
||||
file: git-repo/ci/tasks/promote-version.yml
|
||||
params:
|
||||
RELEASE_TYPE: RELEASE
|
||||
<<: *docker-resource-source
|
||||
<<: *artifactory-task-params
|
||||
<<: *sonatype-task-params
|
||||
- name: create-github-release
|
||||
serial: true
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
- get: artifactory-repo
|
||||
trigger: true
|
||||
passed: [promote-release]
|
||||
params:
|
||||
download_artifacts: false
|
||||
save_build_info: true
|
||||
- task: generate-changelog
|
||||
file: git-repo/ci/tasks/generate-changelog.yml
|
||||
params:
|
||||
RELEASE_TYPE: RELEASE
|
||||
<<: *docker-resource-source
|
||||
<<: *github-task-params
|
||||
- put: github-release
|
||||
params:
|
||||
<<: *changelog-task-params
|
||||
|
||||
groups:
|
||||
- name: "builds"
|
||||
jobs: ["build", "jdk21-build", "jdk22-build"]
|
||||
- name: "releases"
|
||||
jobs: ["stage-milestone", "stage-rc", "stage-release", "promote-milestone", "promote-rc", "promote-release", "create-github-release"]
|
||||
- name: "ci-images"
|
||||
jobs: ["build-ci-images"]
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
source $(dirname $0)/common.sh
|
||||
|
||||
pushd git-repo > /dev/null
|
||||
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Porg.gradle.java.installations.fromEnv=JDK17,JDK21 \
|
||||
--no-daemon --max-workers=4 check
|
||||
popd > /dev/null
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
source $(dirname $0)/common.sh
|
||||
repository=$(pwd)/distribution-repository
|
||||
|
||||
pushd git-repo > /dev/null
|
||||
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Porg.gradle.java.installations.fromEnv=JDK17,JDK21,JDK22 \
|
||||
--no-daemon --max-workers=4 -PdeploymentRepository=${repository} build publishAllPublicationsToDeploymentRepository
|
||||
popd > /dev/null
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
source $(dirname $0)/common.sh
|
||||
|
||||
pushd git-repo > /dev/null
|
||||
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Porg.gradle.java.installations.fromEnv=JDK17,JDK21 \
|
||||
-PmainToolchain=${MAIN_TOOLCHAIN} -PtestToolchain=${TEST_TOOLCHAIN} --no-daemon --max-workers=4 check antora
|
||||
popd > /dev/null
|
||||
@@ -1,2 +0,0 @@
|
||||
source /opt/concourse-java.sh
|
||||
setup_symlinks
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
CONFIG_DIR=git-repo/ci/config
|
||||
version=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' )
|
||||
|
||||
java -jar /github-changelog-generator.jar \
|
||||
--spring.config.location=${CONFIG_DIR}/changelog-generator.yml \
|
||||
${version} generated-changelog/changelog.md
|
||||
|
||||
echo ${version} > generated-changelog/version
|
||||
echo v${version} > generated-changelog/tag
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
CONFIG_DIR=git-repo/ci/config
|
||||
|
||||
version=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' )
|
||||
export BUILD_INFO_LOCATION=$(pwd)/artifactory-repo/build-info.json
|
||||
|
||||
java -jar /concourse-release-scripts.jar \
|
||||
--spring.config.location=${CONFIG_DIR}/release-scripts.yml \
|
||||
publishToCentral $RELEASE_TYPE $BUILD_INFO_LOCATION artifactory-repo || { exit 1; }
|
||||
|
||||
java -jar /concourse-release-scripts.jar \
|
||||
--spring.config.location=${CONFIG_DIR}/release-scripts.yml \
|
||||
promote $RELEASE_TYPE $BUILD_INFO_LOCATION || { exit 1; }
|
||||
|
||||
echo "Promotion complete"
|
||||
echo $version > version/version
|
||||
@@ -1,51 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
source $(dirname $0)/common.sh
|
||||
repository=$(pwd)/distribution-repository
|
||||
|
||||
pushd git-repo > /dev/null
|
||||
git fetch --tags --all > /dev/null
|
||||
popd > /dev/null
|
||||
|
||||
git clone git-repo stage-git-repo > /dev/null
|
||||
|
||||
pushd stage-git-repo > /dev/null
|
||||
|
||||
snapshotVersion=$( awk -F '=' '$1 == "version" { print $2 }' gradle.properties )
|
||||
if [[ $RELEASE_TYPE = "M" ]]; then
|
||||
stageVersion=$( get_next_milestone_release $snapshotVersion)
|
||||
nextVersion=$snapshotVersion
|
||||
elif [[ $RELEASE_TYPE = "RC" ]]; then
|
||||
stageVersion=$( get_next_rc_release $snapshotVersion)
|
||||
nextVersion=$snapshotVersion
|
||||
elif [[ $RELEASE_TYPE = "RELEASE" ]]; then
|
||||
stageVersion=$( get_next_release $snapshotVersion)
|
||||
nextVersion=$( bump_version_number $snapshotVersion)
|
||||
else
|
||||
echo "Unknown release type $RELEASE_TYPE" >&2; exit 1;
|
||||
fi
|
||||
|
||||
echo "Staging $stageVersion (next version will be $nextVersion)"
|
||||
sed -i "s/version=$snapshotVersion/version=$stageVersion/" gradle.properties
|
||||
|
||||
git config user.name "Spring Builds" > /dev/null
|
||||
git config user.email "spring-builds@users.noreply.github.com" > /dev/null
|
||||
git add gradle.properties > /dev/null
|
||||
git commit -m"Release v$stageVersion" > /dev/null
|
||||
git tag -a "v$stageVersion" -m"Release v$stageVersion" > /dev/null
|
||||
|
||||
./gradlew --no-daemon --max-workers=4 -PdeploymentRepository=${repository} -Porg.gradle.java.installations.fromEnv=JDK17,JDK21 \
|
||||
build publishAllPublicationsToDeploymentRepository
|
||||
|
||||
git reset --hard HEAD^ > /dev/null
|
||||
if [[ $nextVersion != $snapshotVersion ]]; then
|
||||
echo "Setting next development version (v$nextVersion)"
|
||||
sed -i "s/version=$snapshotVersion/version=$nextVersion/" gradle.properties
|
||||
git add gradle.properties > /dev/null
|
||||
git commit -m"Next development version (v$nextVersion)" > /dev/null
|
||||
fi;
|
||||
|
||||
echo "Staging Complete"
|
||||
|
||||
popd > /dev/null
|
||||
@@ -1,30 +0,0 @@
|
||||
---
|
||||
platform: linux
|
||||
image_resource:
|
||||
type: registry-image
|
||||
source:
|
||||
repository: concourse/oci-build-task
|
||||
tag: 0.10.0
|
||||
username: ((docker-hub-username))
|
||||
password: ((docker-hub-password))
|
||||
inputs:
|
||||
- name: ci-images-git-repo
|
||||
outputs:
|
||||
- name: image
|
||||
caches:
|
||||
- path: ci-image-cache
|
||||
params:
|
||||
CONTEXT: ci-images-git-repo/ci/images
|
||||
DOCKERFILE: ci-images-git-repo/ci/images/ci-image/Dockerfile
|
||||
DOCKER_HUB_AUTH: ((docker-hub-auth))
|
||||
run:
|
||||
path: /bin/sh
|
||||
args:
|
||||
- "-c"
|
||||
- |
|
||||
mkdir -p /root/.docker
|
||||
cat > /root/.docker/config.json <<EOF
|
||||
{ "auths": { "https://index.docker.io/v1/": { "auth": "$DOCKER_HUB_AUTH" }}}
|
||||
EOF
|
||||
build
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
platform: linux
|
||||
inputs:
|
||||
- name: git-repo
|
||||
caches:
|
||||
- path: gradle
|
||||
params:
|
||||
BRANCH:
|
||||
CI: true
|
||||
GRADLE_ENTERPRISE_ACCESS_KEY:
|
||||
GRADLE_ENTERPRISE_CACHE_USERNAME:
|
||||
GRADLE_ENTERPRISE_CACHE_PASSWORD:
|
||||
GRADLE_ENTERPRISE_URL: https://ge.spring.io
|
||||
run:
|
||||
path: bash
|
||||
args:
|
||||
- -ec
|
||||
- |
|
||||
${PWD}/git-repo/ci/scripts/build-pr.sh
|
||||
@@ -1,22 +0,0 @@
|
||||
---
|
||||
platform: linux
|
||||
inputs:
|
||||
- name: git-repo
|
||||
outputs:
|
||||
- name: distribution-repository
|
||||
- name: git-repo
|
||||
caches:
|
||||
- path: gradle
|
||||
params:
|
||||
BRANCH:
|
||||
CI: true
|
||||
GRADLE_ENTERPRISE_ACCESS_KEY:
|
||||
GRADLE_ENTERPRISE_CACHE_USERNAME:
|
||||
GRADLE_ENTERPRISE_CACHE_PASSWORD:
|
||||
GRADLE_ENTERPRISE_URL: https://ge.spring.io
|
||||
run:
|
||||
path: bash
|
||||
args:
|
||||
- -ec
|
||||
- |
|
||||
${PWD}/git-repo/ci/scripts/build-project.sh
|
||||
@@ -1,24 +0,0 @@
|
||||
---
|
||||
platform: linux
|
||||
inputs:
|
||||
- name: git-repo
|
||||
outputs:
|
||||
- name: distribution-repository
|
||||
- name: git-repo
|
||||
caches:
|
||||
- path: gradle
|
||||
params:
|
||||
BRANCH:
|
||||
CI: true
|
||||
MAIN_TOOLCHAIN:
|
||||
TEST_TOOLCHAIN:
|
||||
GRADLE_ENTERPRISE_ACCESS_KEY:
|
||||
GRADLE_ENTERPRISE_CACHE_USERNAME:
|
||||
GRADLE_ENTERPRISE_CACHE_PASSWORD:
|
||||
GRADLE_ENTERPRISE_URL: https://ge.spring.io
|
||||
run:
|
||||
path: bash
|
||||
args:
|
||||
- -ec
|
||||
- |
|
||||
${PWD}/git-repo/ci/scripts/check-project.sh
|
||||
@@ -1,22 +0,0 @@
|
||||
---
|
||||
platform: linux
|
||||
image_resource:
|
||||
type: registry-image
|
||||
source:
|
||||
repository: springio/github-changelog-generator
|
||||
tag: '0.0.8'
|
||||
username: ((docker-hub-username))
|
||||
password: ((docker-hub-password))
|
||||
inputs:
|
||||
- name: git-repo
|
||||
- name: artifactory-repo
|
||||
outputs:
|
||||
- name: generated-changelog
|
||||
params:
|
||||
GITHUB_ORGANIZATION:
|
||||
GITHUB_REPO:
|
||||
GITHUB_USERNAME:
|
||||
GITHUB_TOKEN:
|
||||
RELEASE_TYPE:
|
||||
run:
|
||||
path: git-repo/ci/scripts/generate-changelog.sh
|
||||
@@ -1,25 +0,0 @@
|
||||
---
|
||||
platform: linux
|
||||
image_resource:
|
||||
type: registry-image
|
||||
source:
|
||||
repository: springio/concourse-release-scripts
|
||||
tag: '0.4.0'
|
||||
username: ((docker-hub-username))
|
||||
password: ((docker-hub-password))
|
||||
inputs:
|
||||
- name: git-repo
|
||||
- name: artifactory-repo
|
||||
outputs:
|
||||
- name: version
|
||||
params:
|
||||
RELEASE_TYPE:
|
||||
ARTIFACTORY_SERVER:
|
||||
ARTIFACTORY_USERNAME:
|
||||
ARTIFACTORY_PASSWORD:
|
||||
SONATYPE_USER:
|
||||
SONATYPE_PASSWORD:
|
||||
SONATYPE_URL:
|
||||
SONATYPE_STAGING_PROFILE:
|
||||
run:
|
||||
path: git-repo/ci/scripts/promote-version.sh
|
||||
@@ -1,17 +0,0 @@
|
||||
---
|
||||
platform: linux
|
||||
inputs:
|
||||
- name: git-repo
|
||||
outputs:
|
||||
- name: stage-git-repo
|
||||
- name: distribution-repository
|
||||
params:
|
||||
RELEASE_TYPE:
|
||||
CI: true
|
||||
GRADLE_ENTERPRISE_CACHE_USERNAME:
|
||||
GRADLE_ENTERPRISE_CACHE_PASSWORD:
|
||||
GRADLE_ENTERPRISE_URL: https://ge.spring.io
|
||||
caches:
|
||||
- path: gradle
|
||||
run:
|
||||
path: git-repo/ci/scripts/stage-version.sh
|
||||
@@ -0,0 +1,267 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<profiles version="11">
|
||||
<profile kind="CodeFormatterProfile" name="Spring" version="11">
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.source" value="1.5"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="120"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.5"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.5"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||
</profile>
|
||||
</profiles>
|
||||
@@ -1,119 +0,0 @@
|
||||
plugins {
|
||||
id 'java-platform'
|
||||
id 'io.freefair.aggregate-javadoc' version '8.3'
|
||||
}
|
||||
|
||||
description = "Spring Framework API Docs"
|
||||
|
||||
apply from: "${rootDir}/gradle/publications.gradle"
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url "https://repo.spring.io/release"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
moduleProjects.each { moduleProject ->
|
||||
javadoc moduleProject
|
||||
}
|
||||
}
|
||||
|
||||
javadoc {
|
||||
title = "${rootProject.description} ${version} API"
|
||||
options {
|
||||
encoding = "UTF-8"
|
||||
memberLevel = JavadocMemberLevel.PROTECTED
|
||||
author = true
|
||||
header = rootProject.description
|
||||
use = true
|
||||
overview = project.relativePath("$rootProject.rootDir/framework-docs/src/docs/api/overview.html")
|
||||
destinationDir = file("${project.buildDir}/docs/javadoc-api")
|
||||
splitIndex = true
|
||||
links(rootProject.ext.javadocLinks)
|
||||
addBooleanOption('Xdoclint:syntax,reference', true) // only check syntax and reference with doclint
|
||||
addBooleanOption('Werror', true) // fail build on Javadoc warnings
|
||||
}
|
||||
maxMemory = "1024m"
|
||||
doFirst {
|
||||
classpath += files(
|
||||
// ensure the javadoc process can resolve types compiled from .aj sources
|
||||
project(":spring-aspects").sourceSets.main.output
|
||||
)
|
||||
classpath += files(moduleProjects.collect { it.sourceSets.main.compileClasspath })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce KDoc for all Spring Framework modules in "build/docs/kdoc"
|
||||
*/
|
||||
rootProject.tasks.dokkaHtmlMultiModule.configure {
|
||||
dependsOn {
|
||||
tasks.named("javadoc")
|
||||
}
|
||||
moduleName.set("spring-framework")
|
||||
outputDirectory.set(project.file("$buildDir/docs/kdoc-api"))
|
||||
includes.from("$rootProject.rootDir/framework-docs/src/docs/api/dokka-overview.md")
|
||||
}
|
||||
|
||||
/**
|
||||
* Zip all Java docs (javadoc & kdoc) into a single archive
|
||||
*/
|
||||
tasks.register('docsZip', Zip) {
|
||||
dependsOn = ['javadoc', rootProject.tasks.dokkaHtmlMultiModule]
|
||||
group = "distribution"
|
||||
description = "Builds -${archiveClassifier} archive containing api and reference " +
|
||||
"for deployment at https://docs.spring.io/spring-framework/docs/."
|
||||
|
||||
archiveBaseName.set("spring-framework")
|
||||
archiveClassifier.set("docs")
|
||||
from("src/dist") {
|
||||
include "changelog.txt"
|
||||
}
|
||||
from(javadoc) {
|
||||
into "javadoc-api"
|
||||
}
|
||||
from(rootProject.tasks.dokkaHtmlMultiModule.outputDirectory) {
|
||||
into "kdoc-api"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Zip all Spring Framework schemas into a single archive
|
||||
*/
|
||||
tasks.register('schemaZip', Zip) {
|
||||
group = "distribution"
|
||||
archiveBaseName.set("spring-framework")
|
||||
archiveClassifier.set("schema")
|
||||
description = "Builds -${archiveClassifier} archive containing all " +
|
||||
"XSDs for deployment at https://springframework.org/schema."
|
||||
duplicatesStrategy DuplicatesStrategy.EXCLUDE
|
||||
moduleProjects.each { module ->
|
||||
def Properties schemas = new Properties();
|
||||
|
||||
module.sourceSets.main.resources.find {
|
||||
(it.path.endsWith("META-INF/spring.schemas") || it.path.endsWith("META-INF\\spring.schemas"))
|
||||
}?.withInputStream { schemas.load(it) }
|
||||
|
||||
for (def key : schemas.keySet()) {
|
||||
def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
|
||||
assert shortName != key
|
||||
File xsdFile = module.sourceSets.main.resources.find {
|
||||
(it.path.endsWith(schemas.get(key)) || it.path.endsWith(schemas.get(key).replaceAll('\\/', '\\\\')))
|
||||
}
|
||||
assert xsdFile != null
|
||||
into(shortName) {
|
||||
from xsdFile.path
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
artifact docsZip
|
||||
artifact schemaZip
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
description = "Spring Framework (Bill of Materials)"
|
||||
|
||||
apply plugin: 'java-platform'
|
||||
apply from: "$rootDir/gradle/publications.gradle"
|
||||
|
||||
group = "org.springframework"
|
||||
|
||||
dependencies {
|
||||
constraints {
|
||||
parent.moduleProjects.sort { "$it.name" }.each {
|
||||
api it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
artifactId = 'spring-framework-bom'
|
||||
from components.javaPlatform
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
name: framework
|
||||
version: true
|
||||
title: Spring Framework
|
||||
nav:
|
||||
- modules/ROOT/nav.adoc
|
||||
ext:
|
||||
collector:
|
||||
run:
|
||||
command: gradlew -q -PbuildSrc.skipTests=true "-Dorg.gradle.jvmargs=-Xmx3g -XX:+HeapDumpOnOutOfMemoryError" :framework-docs:generateAntoraResources
|
||||
local: true
|
||||
scan:
|
||||
dir: ./build/generated-antora-resources
|
||||
|
||||
asciidoc:
|
||||
attributes:
|
||||
attribute-missing: 'warn'
|
||||
# FIXME: the copyright is not removed
|
||||
# FIXME: The package is not renamed
|
||||
chomp: 'all'
|
||||
fold: 'all'
|
||||
include-java: 'example$docs-src/main/java/org/springframework/docs'
|
||||
spring-site: 'https://spring.io'
|
||||
spring-site-blog: '{spring-site}/blog'
|
||||
spring-site-cve: "{spring-site}/security"
|
||||
spring-site-guides: '{spring-site}/guides'
|
||||
spring-site-projects: '{spring-site}/projects'
|
||||
spring-site-tools: "{spring-site}/tools"
|
||||
spring-org: 'spring-projects'
|
||||
spring-github-org: "https://github.com/{spring-org}"
|
||||
spring-framework-github: "https://github.com/{spring-org}/spring-framework"
|
||||
spring-framework-code: '{spring-framework-github}/tree/main'
|
||||
spring-framework-issues: '{spring-framework-github}/issues'
|
||||
spring-framework-wiki: '{spring-framework-github}/wiki'
|
||||
# Docs
|
||||
docs-site: 'https://docs.spring.io'
|
||||
spring-framework-docs-root: '{docs-site}/spring-framework/docs'
|
||||
spring-framework-api: '{spring-framework-docs-root}/{spring-version}/javadoc-api/org/springframework'
|
||||
spring-framework-api-kdoc: '{spring-framework-docs-root}/{spring-version}/kdoc-api'
|
||||
spring-framework-reference: '{spring-framework-docs-root}/{spring-version}/reference'
|
||||
#
|
||||
# Other Spring portfolio projects
|
||||
spring-boot-docs: '{docs-site}/spring-boot/docs/current/reference/html'
|
||||
spring-boot-issues: '{spring-github-org}/spring-boot/issues'
|
||||
# TODO add more projects / links or just build up on {docs-site}?
|
||||
# TODO rename the below using new conventions
|
||||
docs-spring-gemfire: '{docs-site}/spring-gemfire/docs/current/reference'
|
||||
docs-spring-security: '{docs-site}/spring-security/reference'
|
||||
docs-spring-session: '{docs-site}/spring-session/reference'
|
||||
#
|
||||
# External projects URLs and related attributes
|
||||
aspectj-site: 'https://www.eclipse.org/aspectj'
|
||||
aspectj-docs: "{aspectj-site}/doc/released"
|
||||
aspectj-api: "{aspectj-docs}/runtime-api"
|
||||
aspectj-docs-devguide: "{aspectj-docs}/devguide"
|
||||
aspectj-docs-progguide: "{aspectj-docs}/progguide"
|
||||
assertj-docs: 'https://assertj.github.io/doc'
|
||||
baeldung-blog: 'https://www.baeldung.com'
|
||||
bean-validation-site: 'https://beanvalidation.org'
|
||||
graalvm-docs: 'https://www.graalvm.org/22.3/reference-manual'
|
||||
hibernate-validator-site: 'https://hibernate.org/validator/'
|
||||
jackson-docs: 'https://fasterxml.github.io'
|
||||
jackson-github-org: 'https://github.com/FasterXML'
|
||||
java-api: 'https://docs.oracle.com/en/java/javase/17/docs/api'
|
||||
java-tutorial: 'https://docs.oracle.com/javase/tutorial'
|
||||
JSR: 'https://www.jcp.org/en/jsr/detail?id='
|
||||
kotlin-site: 'https://kotlinlang.org'
|
||||
kotlin-docs: '{kotlin-site}/docs'
|
||||
kotlin-api: '{kotlin-site}/api/latest'
|
||||
kotlin-coroutines-api: '{kotlin-site}/api/kotlinx.coroutines'
|
||||
kotlin-github-org: 'https://github.com/Kotlin'
|
||||
kotlin-issues: 'https://youtrack.jetbrains.com/issue'
|
||||
reactive-streams-site: 'https://www.reactive-streams.org'
|
||||
reactive-streams-spec: 'https://github.com/reactive-streams/reactive-streams-jvm/blob/master/README.md#specification'
|
||||
reactor-github-org: 'https://github.com/reactor'
|
||||
reactor-site: 'https://projectreactor.io'
|
||||
rsocket-github-org: 'https://github.com/rsocket'
|
||||
rsocket-java: '{rsocket-github-org}/rsocket-java'
|
||||
rsocket-java-code: '{rsocket-java}/tree/master/'
|
||||
rsocket-protocol-extensions: '{rsocket-github-org}/rsocket/tree/master/Extensions'
|
||||
rsocket-site: 'https://rsocket.io'
|
||||
rfc-site: 'https://datatracker.ietf.org/doc/html'
|
||||
sockjs-client: 'https://github.com/sockjs/sockjs-client'
|
||||
sockjs-protocol: 'https://github.com/sockjs/sockjs-protocol'
|
||||
sockjs-protocol-site: "https://sockjs.github.io/sockjs-protocol"
|
||||
stackoverflow-site: 'https://stackoverflow.com'
|
||||
stackoverflow-questions: '{stackoverflow-site}/questions'
|
||||
stackoverflow-spring-tag: "{stackoverflow-questions}/tagged/spring"
|
||||
stackoverflow-spring-kotlin-tags: "{stackoverflow-spring-tag}+kotlin"
|
||||
testcontainers-site: 'https://www.testcontainers.org'
|
||||
@@ -1,70 +0,0 @@
|
||||
plugins {
|
||||
id 'kotlin'
|
||||
id 'io.spring.antora.generate-antora-yml' version '0.0.1'
|
||||
id 'org.antora' version '1.0.0'
|
||||
}
|
||||
|
||||
description = "Spring Framework Docs"
|
||||
|
||||
apply from: "${rootDir}/gradle/ide.gradle"
|
||||
apply from: "${rootDir}/gradle/publications.gradle"
|
||||
|
||||
antora {
|
||||
version = '3.2.0-alpha.2'
|
||||
playbook = 'cached-antora-playbook.yml'
|
||||
playbookProvider {
|
||||
repository = 'spring-projects/spring-framework'
|
||||
branch = 'docs-build'
|
||||
path = 'lib/antora/templates/per-branch-antora-playbook.yml'
|
||||
checkLocalBranch = true
|
||||
}
|
||||
options = ['--clean', '--stacktrace']
|
||||
environment = [
|
||||
'ALGOLIA_API_KEY': '82c7ead946afbac3cf98c32446154691',
|
||||
'ALGOLIA_APP_ID': '244V8V9FGG',
|
||||
'ALGOLIA_INDEX_NAME': 'framework-docs'
|
||||
]
|
||||
dependencies = [
|
||||
'@antora/atlas-extension': '1.0.0-alpha.1',
|
||||
'@antora/collector-extension': '1.0.0-alpha.3',
|
||||
'@asciidoctor/tabs': '1.0.0-beta.3',
|
||||
'@opendevise/antora-release-line-extension': '1.0.0-alpha.2',
|
||||
'@springio/antora-extensions': '1.3.0',
|
||||
'@springio/asciidoctor-extensions': '1.0.0-alpha.9'
|
||||
]
|
||||
}
|
||||
|
||||
tasks.named("generateAntoraYml") {
|
||||
asciidocAttributes = project.provider( {
|
||||
return ["spring-version": project.version ]
|
||||
} )
|
||||
}
|
||||
|
||||
tasks.register("generateAntoraResources") {
|
||||
dependsOn 'generateAntoraYml'
|
||||
}
|
||||
|
||||
jar {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
javadoc {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url "https://repo.spring.io/release"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":spring-context"))
|
||||
api(project(":spring-jms"))
|
||||
api(project(":spring-web"))
|
||||
api("jakarta.jms:jakarta.jms-api")
|
||||
api("jakarta.servlet:jakarta.servlet-api")
|
||||
|
||||
implementation(project(":spring-core-test"))
|
||||
implementation("org.assertj:assertj-core")
|
||||
}
|
||||
|
Before Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 63 KiB |
@@ -1,612 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generated by Microsoft Visio 11.0, SVG Export, v1.0 spring-overview.svg Page-1 -->
|
||||
|
||||
<svg
|
||||
xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="6.4728541in"
|
||||
height="5.9522467in"
|
||||
viewBox="0 0 466.04561 428.56238"
|
||||
xml:space="preserve"
|
||||
class="st5"
|
||||
id="svg5499"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="mvc-splitted-contexts.svg"
|
||||
style="font-size:12px;overflow:visible;color-interpolation-filters:sRGB;fill:none;fill-rule:evenodd;stroke-linecap:square;stroke-miterlimit:3"
|
||||
inkscape:export-filename="/Users/seb/Workspace/spring-framework/src/asciidoc/images/mvc-splitted-contexts.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90"><metadata
|
||||
id="metadata5713"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="https://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs5711"><marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible;"
|
||||
id="marker9162"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"><path
|
||||
transform="scale(0.6) rotate(180) translate(0,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
id="path9164" /></marker><marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible;"
|
||||
id="marker8834"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"><path
|
||||
transform="scale(0.6) rotate(180) translate(0,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
id="path8836" /></marker><marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible;"
|
||||
id="marker8518"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"><path
|
||||
transform="scale(0.6) rotate(180) translate(0,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
id="path8520" /></marker><marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible;"
|
||||
id="marker8214"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"><path
|
||||
transform="scale(0.6) rotate(180) translate(0,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
id="path8216" /></marker><marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible;"
|
||||
id="marker7922"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"><path
|
||||
transform="scale(0.6) rotate(180) translate(0,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
id="path7924" /></marker><marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible;"
|
||||
id="marker7641"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"><path
|
||||
transform="scale(0.6) rotate(180) translate(0,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
id="path7644" /></marker><marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible;"
|
||||
id="marker7373"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"><path
|
||||
transform="scale(0.6) rotate(180) translate(0,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
id="path7375" /></marker><marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible;"
|
||||
id="marker7117"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"><path
|
||||
transform="scale(0.6) rotate(180) translate(0,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
id="path7119" /></marker><marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible;"
|
||||
id="marker6873"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"><path
|
||||
transform="scale(0.6) rotate(180) translate(0,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
id="path6875" /></marker><marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible;"
|
||||
id="marker6641"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"><path
|
||||
transform="scale(0.6) rotate(180) translate(0,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
id="path6643" /></marker><marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible;"
|
||||
id="marker6421"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"><path
|
||||
transform="scale(0.6) rotate(180) translate(0,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
id="path6423" /></marker><marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible;"
|
||||
id="marker6213"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"><path
|
||||
transform="scale(0.6) rotate(180) translate(0,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
id="path6215" /></marker><marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible;"
|
||||
id="marker6017"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"><path
|
||||
transform="scale(0.6) rotate(180) translate(0,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
id="path6019" /></marker><marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible;"
|
||||
id="marker5833"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"><path
|
||||
transform="scale(0.6) rotate(180) translate(0,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
id="path5835" /></marker><marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible;"
|
||||
id="marker5661"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"><path
|
||||
transform="scale(0.6) rotate(180) translate(0,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
id="path5663" /></marker><marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible;"
|
||||
id="marker5501"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"><path
|
||||
transform="scale(0.6) rotate(180) translate(0,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
id="path5503" /></marker><marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible;"
|
||||
id="marker5353"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"><path
|
||||
transform="scale(0.6) rotate(180) translate(0,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
id="path5355" /></marker><marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible;"
|
||||
id="marker5217"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"><path
|
||||
transform="scale(0.6) rotate(180) translate(0,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
id="path5219" /></marker><marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible;"
|
||||
id="marker5093"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"><path
|
||||
transform="scale(0.6) rotate(180) translate(0,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
id="path5095" /></marker><marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible;"
|
||||
id="marker4981"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"><path
|
||||
transform="scale(0.6) rotate(180) translate(0,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
id="path4983" /></marker><marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow2Mend"
|
||||
style="overflow:visible;"
|
||||
inkscape:isstock="true"
|
||||
inkscape:collect="always"><path
|
||||
id="path7394"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
transform="scale(0.6) rotate(180) translate(0,0)" /></marker><marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="marker8121"
|
||||
style="overflow:visible;"
|
||||
inkscape:isstock="true"><path
|
||||
id="path8123"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
transform="scale(1.1) rotate(180) translate(1,0)" /></marker><marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="marker8033"
|
||||
style="overflow:visible;"
|
||||
inkscape:isstock="true"><path
|
||||
id="path8035"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
transform="scale(0.4) rotate(180) translate(10,0)" /></marker><marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="marker7957"
|
||||
style="overflow:visible;"
|
||||
inkscape:isstock="true"><path
|
||||
id="path7959"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
transform="scale(0.4) rotate(180) translate(10,0)" /></marker><marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible;"
|
||||
inkscape:isstock="true"><path
|
||||
id="path7376"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
transform="scale(0.4) rotate(180) translate(10,0)" /></marker><marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible;"
|
||||
inkscape:isstock="true"><path
|
||||
id="path7388"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
transform="scale(1.1) rotate(180) translate(1,0)" /></marker><marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible;"
|
||||
inkscape:isstock="true"><path
|
||||
id="path7370"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
transform="scale(0.8) rotate(180) translate(12.5,0)" /></marker></defs><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1680"
|
||||
inkscape:window-height="1005"
|
||||
id="namedview5709"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.1640492"
|
||||
inkscape:cx="134.86698"
|
||||
inkscape:cy="203.59898"
|
||||
inkscape:window-x="84"
|
||||
inkscape:window-y="176"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="g5503"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" /><v:documentProperties
|
||||
v:langID="1033"
|
||||
v:viewMarkup="false" /><style
|
||||
type="text/css"
|
||||
id="style5501"><![CDATA[
|
||||
.st1 {fill:#969696;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
|
||||
.st2 {fill:#dde2cd;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
|
||||
.st3 {fill:#000000;font-family:Arial;font-size:2.50001em;font-weight:bold}
|
||||
.st4 {font-size:0.333333em;font-weight:normal}
|
||||
.st5 {fill:none;fill-rule:evenodd;font-size:12;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
|
||||
]]></style><g
|
||||
v:mID="0"
|
||||
v:index="1"
|
||||
v:groupContext="foregroundPage"
|
||||
id="g5503"
|
||||
transform="matrix(0.99998201,0,0,1.0824094,-40.812382,-98.908648)"><rect
|
||||
style="fill:#dde2cd;fill-opacity:1;stroke:#000000;stroke-width:1.53790233;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect6599"
|
||||
width="382.68423"
|
||||
height="146.09897"
|
||||
x="87.884865"
|
||||
y="148.26482" /><v:userDefs><v:ud
|
||||
v:nameU="SchemeName"
|
||||
v:val="VT4(Default)" /></v:userDefs><rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.53790233;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect5725"
|
||||
width="464.31128"
|
||||
height="374.11411"
|
||||
x="41.684383"
|
||||
y="112.3262" /><title
|
||||
id="title5505">Page-1</title><v:pageProperties
|
||||
v:drawingScale="0.0393701"
|
||||
v:pageScale="0.0393701"
|
||||
v:drawingUnits="24"
|
||||
v:shadowOffsetX="8.50394"
|
||||
v:shadowOffsetY="-8.50394" /><v:layer
|
||||
v:name="Connector"
|
||||
v:index="0" /><rect
|
||||
style="fill:#dde2cd;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.53790233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect5715"
|
||||
width="322.8194"
|
||||
height="43.63184"
|
||||
x="119.95335"
|
||||
y="-135.66222"
|
||||
transform="scale(1,-1)" /><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:30.7580471px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="168.843"
|
||||
y="124.32391"
|
||||
id="text5717"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="scale(1.0403984,0.96117025)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5719"
|
||||
x="168.843"
|
||||
y="124.32391"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:23.06853676px;font-family:sans-serif;-inkscape-font-specification:sans-serif">DispatcherServlet</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="89.770851"
|
||||
y="181.20923"
|
||||
id="text6589"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="scale(1.0403984,0.96117025)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6591"
|
||||
x="89.770851"
|
||||
y="181.20923"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:23.06853676px;font-family:sans-serif;-inkscape-font-specification:sans-serif">Servlet WebApplicationContext</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="260.00443"
|
||||
y="198.41273"
|
||||
id="text6593"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="scale(1.0403984,0.96117025)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6595"
|
||||
x="260.00443"
|
||||
y="198.41273"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.53426838px;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle">(containing controllers, view resolvers,</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="260.00443"
|
||||
y="212.83057"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.53426838px;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle"
|
||||
id="tspan6597">and other web-related beans)</tspan></text>
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.86203903;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect6620"
|
||||
width="82.040657"
|
||||
height="36.72575"
|
||||
x="114.52653"
|
||||
y="-259.43161"
|
||||
transform="scale(1,-1)" /><rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.89166164;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect6622"
|
||||
width="87.843979"
|
||||
height="36.697304"
|
||||
x="223.39864"
|
||||
y="-287.19809"
|
||||
transform="scale(1,-1)" /><rect
|
||||
transform="scale(1,-1)"
|
||||
y="-264.81918"
|
||||
x="117.92834"
|
||||
height="36.72575"
|
||||
width="82.040657"
|
||||
id="rect6614"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.86203903;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1" /><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="121.24728"
|
||||
y="260.14957"
|
||||
id="text6616"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="scale(1.0403984,0.96117025)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6618"
|
||||
x="121.24728"
|
||||
y="260.14957"
|
||||
style="font-size:11.53426838px">Controllers</tspan></text>
|
||||
<text
|
||||
transform="scale(1.0403984,0.96117025)"
|
||||
sodipodi:linespacing="125%"
|
||||
id="text6624"
|
||||
y="282.70709"
|
||||
x="219.61203"
|
||||
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:11.53426838px"
|
||||
y="282.70709"
|
||||
x="219.61203"
|
||||
id="tspan6626"
|
||||
sodipodi:role="line">ViewResolver</tspan></text>
|
||||
<rect
|
||||
transform="scale(1,-1)"
|
||||
y="-259.30249"
|
||||
x="332.5405"
|
||||
height="36.577778"
|
||||
width="114.4539"
|
||||
id="rect6628"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.0161339;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1" /><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="327.51276"
|
||||
y="255.28464"
|
||||
id="text6630"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="scale(1.0403984,0.96117025)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6632"
|
||||
x="327.51276"
|
||||
y="255.28464"
|
||||
style="font-size:11.53426838px">HandlerMapping</tspan></text>
|
||||
<rect
|
||||
y="338.69724"
|
||||
x="87.803261"
|
||||
height="121.5683"
|
||||
width="382.84744"
|
||||
id="rect6634"
|
||||
style="fill:#dde2cd;fill-opacity:1;stroke:#000000;stroke-width:1.53790233;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1" /><text
|
||||
transform="scale(1.0403984,0.96117025)"
|
||||
sodipodi:linespacing="125%"
|
||||
id="text6636"
|
||||
y="376.61673"
|
||||
x="108.61351"
|
||||
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:23.06853676px;font-family:sans-serif;-inkscape-font-specification:sans-serif"
|
||||
y="376.61673"
|
||||
x="108.61351"
|
||||
id="tspan6638"
|
||||
sodipodi:role="line">Root WebApplicationContext</tspan></text>
|
||||
<text
|
||||
transform="scale(1.0403984,0.96117025)"
|
||||
sodipodi:linespacing="125%"
|
||||
id="text6640"
|
||||
y="395.35812"
|
||||
x="260.93863"
|
||||
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan6644"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.53426838px;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle"
|
||||
y="395.35812"
|
||||
x="260.93863"
|
||||
sodipodi:role="line">(containing middle-tier services, datasources, etc.)</tspan></text>
|
||||
<rect
|
||||
transform="scale(1,-1)"
|
||||
y="-440.06805"
|
||||
x="164.32933"
|
||||
height="36.72575"
|
||||
width="82.040657"
|
||||
id="rect6648"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.86203903;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1" /><rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.86203903;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect6650"
|
||||
width="82.040657"
|
||||
height="36.72575"
|
||||
x="167.73116"
|
||||
y="-445.45563"
|
||||
transform="scale(1,-1)" /><text
|
||||
transform="scale(1.0403984,0.96117025)"
|
||||
sodipodi:linespacing="125%"
|
||||
id="text6652"
|
||||
y="448.55054"
|
||||
x="175.87148"
|
||||
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:11.53426838px"
|
||||
y="448.55054"
|
||||
x="175.87148"
|
||||
id="tspan6654"
|
||||
sodipodi:role="line">Services</tspan></text>
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.88435173;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect6656"
|
||||
width="86.393044"
|
||||
height="36.704323"
|
||||
x="306.86328"
|
||||
y="-439.60837"
|
||||
transform="scale(1,-1)" /><rect
|
||||
transform="scale(1,-1)"
|
||||
y="-444.99475"
|
||||
x="310.26624"
|
||||
height="36.701977"
|
||||
width="86.876686"
|
||||
id="rect6658"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.88679528;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1" /><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="305.30771"
|
||||
y="448.55054"
|
||||
id="text6660"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="scale(1.0403984,0.96117025)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6662"
|
||||
x="305.30771"
|
||||
y="448.55054"
|
||||
style="font-size:11.53426838px">Repositories</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.76895118px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 265.33234,295.60379 c 0,42.65169 0,42.65169 0,0 z"
|
||||
id="path7643"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.46028023;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Mend)"
|
||||
d="m 270.43505,294.70585 c 0,39.4721 0,39.87903 0,39.87903"
|
||||
id="path7645"
|
||||
inkscape:connector-curvature="0" /><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="352.55331"
|
||||
y="333.03622"
|
||||
id="text4963"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="scale(1.0403984,0.96117025)"><tspan
|
||||
sodipodi:role="line"
|
||||
x="352.55331"
|
||||
y="333.03622"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.53426838px;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle"
|
||||
id="tspan4965">Delegates if no bean found</tspan></text>
|
||||
</g></svg>
|
||||
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 102 KiB |
@@ -1 +0,0 @@
|
||||
../../../src
|
||||
@@ -1,442 +0,0 @@
|
||||
* xref:overview.adoc[Overview]
|
||||
* xref:core.adoc[]
|
||||
** xref:core/beans.adoc[]
|
||||
*** xref:core/beans/introduction.adoc[]
|
||||
*** xref:core/beans/basics.adoc[]
|
||||
*** xref:core/beans/definition.adoc[]
|
||||
*** xref:core/beans/dependencies.adoc[]
|
||||
**** xref:core/beans/dependencies/factory-collaborators.adoc[]
|
||||
**** xref:core/beans/dependencies/factory-properties-detailed.adoc[]
|
||||
**** xref:core/beans/dependencies/factory-dependson.adoc[]
|
||||
**** xref:core/beans/dependencies/factory-lazy-init.adoc[]
|
||||
**** xref:core/beans/dependencies/factory-autowire.adoc[]
|
||||
**** xref:core/beans/dependencies/factory-method-injection.adoc[]
|
||||
*** xref:core/beans/factory-scopes.adoc[]
|
||||
*** xref:core/beans/factory-nature.adoc[]
|
||||
*** xref:core/beans/child-bean-definitions.adoc[]
|
||||
*** xref:core/beans/factory-extension.adoc[]
|
||||
*** xref:core/beans/annotation-config.adoc[]
|
||||
**** xref:core/beans/annotation-config/autowired.adoc[]
|
||||
**** xref:core/beans/annotation-config/autowired-primary.adoc[]
|
||||
**** xref:core/beans/annotation-config/autowired-qualifiers.adoc[]
|
||||
**** xref:core/beans/annotation-config/generics-as-qualifiers.adoc[]
|
||||
**** xref:core/beans/annotation-config/custom-autowire-configurer.adoc[]
|
||||
**** xref:core/beans/annotation-config/resource.adoc[]
|
||||
**** xref:core/beans/annotation-config/value-annotations.adoc[]
|
||||
**** xref:core/beans/annotation-config/postconstruct-and-predestroy-annotations.adoc[]
|
||||
*** xref:core/beans/classpath-scanning.adoc[]
|
||||
*** xref:core/beans/standard-annotations.adoc[]
|
||||
*** xref:core/beans/java.adoc[]
|
||||
**** xref:core/beans/java/basic-concepts.adoc[]
|
||||
**** xref:core/beans/java/instantiating-container.adoc[]
|
||||
**** xref:core/beans/java/bean-annotation.adoc[]
|
||||
**** xref:core/beans/java/configuration-annotation.adoc[]
|
||||
**** xref:core/beans/java/composing-configuration-classes.adoc[]
|
||||
*** xref:core/beans/environment.adoc[]
|
||||
*** xref:core/beans/context-load-time-weaver.adoc[]
|
||||
*** xref:core/beans/context-introduction.adoc[]
|
||||
*** xref:core/beans/beanfactory.adoc[]
|
||||
** xref:core/resources.adoc[]
|
||||
** xref:core/validation.adoc[]
|
||||
*** xref:core/validation/validator.adoc[]
|
||||
*** xref:core/validation/conversion.adoc[]
|
||||
*** xref:core/validation/beans-beans.adoc[]
|
||||
*** xref:core/validation/convert.adoc[]
|
||||
*** xref:core/validation/format.adoc[]
|
||||
*** xref:core/validation/format-configuring-formatting-globaldatetimeformat.adoc[]
|
||||
*** xref:core/validation/beanvalidation.adoc[]
|
||||
** xref:core/expressions.adoc[]
|
||||
*** xref:core/expressions/evaluation.adoc[]
|
||||
*** xref:core/expressions/beandef.adoc[]
|
||||
*** xref:core/expressions/language-ref.adoc[]
|
||||
**** xref:core/expressions/language-ref/literal.adoc[]
|
||||
**** xref:core/expressions/language-ref/properties-arrays.adoc[]
|
||||
**** xref:core/expressions/language-ref/inline-lists.adoc[]
|
||||
**** xref:core/expressions/language-ref/inline-maps.adoc[]
|
||||
**** xref:core/expressions/language-ref/array-construction.adoc[]
|
||||
**** xref:core/expressions/language-ref/methods.adoc[]
|
||||
**** xref:core/expressions/language-ref/operators.adoc[]
|
||||
**** xref:core/expressions/language-ref/types.adoc[]
|
||||
**** xref:core/expressions/language-ref/constructors.adoc[]
|
||||
**** xref:core/expressions/language-ref/variables.adoc[]
|
||||
**** xref:core/expressions/language-ref/functions.adoc[]
|
||||
**** xref:core/expressions/language-ref/bean-references.adoc[]
|
||||
**** xref:core/expressions/language-ref/operator-ternary.adoc[]
|
||||
**** xref:core/expressions/language-ref/operator-elvis.adoc[]
|
||||
**** xref:core/expressions/language-ref/operator-safe-navigation.adoc[]
|
||||
**** xref:core/expressions/language-ref/collection-selection.adoc[]
|
||||
**** xref:core/expressions/language-ref/collection-projection.adoc[]
|
||||
**** xref:core/expressions/language-ref/templating.adoc[]
|
||||
*** xref:core/expressions/example-classes.adoc[]
|
||||
** xref:core/aop.adoc[]
|
||||
*** xref:core/aop/introduction-defn.adoc[]
|
||||
*** xref:core/aop/introduction-spring-defn.adoc[]
|
||||
*** xref:core/aop/introduction-proxies.adoc[]
|
||||
*** xref:core/aop/ataspectj.adoc[]
|
||||
**** xref:core/aop/ataspectj/aspectj-support.adoc[]
|
||||
**** xref:core/aop/ataspectj/at-aspectj.adoc[]
|
||||
**** xref:core/aop/ataspectj/pointcuts.adoc[]
|
||||
**** xref:core/aop/ataspectj/advice.adoc[]
|
||||
**** xref:core/aop/ataspectj/introductions.adoc[]
|
||||
**** xref:core/aop/ataspectj/instantiation-models.adoc[]
|
||||
**** xref:core/aop/ataspectj/example.adoc[]
|
||||
*** xref:core/aop/schema.adoc[]
|
||||
*** xref:core/aop/choosing.adoc[]
|
||||
*** xref:core/aop/mixing-styles.adoc[]
|
||||
*** xref:core/aop/proxying.adoc[]
|
||||
*** xref:core/aop/aspectj-programmatic.adoc[]
|
||||
*** xref:core/aop/using-aspectj.adoc[]
|
||||
*** xref:core/aop/resources.adoc[]
|
||||
** xref:core/aop-api.adoc[]
|
||||
*** xref:core/aop-api/pointcuts.adoc[]
|
||||
*** xref:core/aop-api/advice.adoc[]
|
||||
*** xref:core/aop-api/advisor.adoc[]
|
||||
*** xref:core/aop-api/pfb.adoc[]
|
||||
*** xref:core/aop-api/concise-proxy.adoc[]
|
||||
*** xref:core/aop-api/prog.adoc[]
|
||||
*** xref:core/aop-api/advised.adoc[]
|
||||
*** xref:core/aop-api/autoproxy.adoc[]
|
||||
*** xref:core/aop-api/targetsource.adoc[]
|
||||
*** xref:core/aop-api/extensibility.adoc[]
|
||||
** xref:core/null-safety.adoc[]
|
||||
** xref:core/databuffer-codec.adoc[]
|
||||
** xref:core/spring-jcl.adoc[]
|
||||
** xref:core/aot.adoc[]
|
||||
** xref:core/appendix.adoc[]
|
||||
*** xref:core/appendix/xsd-schemas.adoc[]
|
||||
*** xref:core/appendix/xml-custom.adoc[]
|
||||
*** xref:core/appendix/application-startup-steps.adoc[]
|
||||
* xref:testing.adoc[]
|
||||
** xref:testing/introduction.adoc[]
|
||||
** xref:testing/unit.adoc[]
|
||||
** xref:testing/integration.adoc[]
|
||||
** xref:testing/support-jdbc.adoc[]
|
||||
** xref:testing/testcontext-framework.adoc[]
|
||||
*** xref:testing/testcontext-framework/key-abstractions.adoc[]
|
||||
*** xref:testing/testcontext-framework/bootstrapping.adoc[]
|
||||
*** xref:testing/testcontext-framework/tel-config.adoc[]
|
||||
*** 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/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[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/inheritance.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/env-profiles.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/property-sources.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/dynamic-property-sources.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/web.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/web-mocks.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/caching.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/failure-threshold.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/hierarchies.adoc[]
|
||||
*** xref:testing/testcontext-framework/fixture-di.adoc[]
|
||||
*** xref:testing/testcontext-framework/web-scoped-beans.adoc[]
|
||||
*** xref:testing/testcontext-framework/tx.adoc[]
|
||||
*** xref:testing/testcontext-framework/executing-sql.adoc[]
|
||||
*** xref:testing/testcontext-framework/parallel-test-execution.adoc[]
|
||||
*** xref:testing/testcontext-framework/support-classes.adoc[]
|
||||
*** xref:testing/testcontext-framework/aot.adoc[]
|
||||
** xref:testing/webtestclient.adoc[]
|
||||
** xref:testing/spring-mvc-test-framework.adoc[]
|
||||
*** xref:testing/spring-mvc-test-framework/server.adoc[]
|
||||
*** xref:testing/spring-mvc-test-framework/server-static-imports.adoc[]
|
||||
*** xref:testing/spring-mvc-test-framework/server-setup-options.adoc[]
|
||||
*** xref:testing/spring-mvc-test-framework/server-setup-steps.adoc[]
|
||||
*** xref:testing/spring-mvc-test-framework/server-performing-requests.adoc[]
|
||||
*** xref:testing/spring-mvc-test-framework/server-defining-expectations.adoc[]
|
||||
*** xref:testing/spring-mvc-test-framework/async-requests.adoc[]
|
||||
*** xref:testing/spring-mvc-test-framework/vs-streaming-response.adoc[]
|
||||
*** xref:testing/spring-mvc-test-framework/server-filters.adoc[]
|
||||
*** xref:testing/spring-mvc-test-framework/vs-end-to-end-integration-tests.adoc[]
|
||||
*** xref:testing/spring-mvc-test-framework/server-resources.adoc[]
|
||||
*** xref:testing/spring-mvc-test-framework/server-htmlunit.adoc[]
|
||||
**** xref:testing/spring-mvc-test-framework/server-htmlunit/why.adoc[]
|
||||
**** xref:testing/spring-mvc-test-framework/server-htmlunit/mah.adoc[]
|
||||
**** xref:testing/spring-mvc-test-framework/server-htmlunit/webdriver.adoc[]
|
||||
**** xref:testing/spring-mvc-test-framework/server-htmlunit/geb.adoc[]
|
||||
** xref:testing/spring-mvc-test-client.adoc[]
|
||||
** xref:testing/appendix.adoc[]
|
||||
*** xref:testing/annotations.adoc[]
|
||||
**** xref:testing/annotations/integration-standard.adoc[]
|
||||
**** xref:testing/annotations/integration-spring.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-bootstrapwith.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-contextconfiguration.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-webappconfiguration.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-contexthierarchy.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-contextcustomizerfactories.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-activeprofiles.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-testpropertysource.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-dynamicpropertysource.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-dirtiescontext.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-testexecutionlisteners.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-recordapplicationevents.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-commit.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-rollback.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-beforetransaction.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-aftertransaction.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-sql.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-sqlconfig.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-sqlmergemode.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-sqlgroup.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-disabledinaotmode.adoc[]
|
||||
**** xref:testing/annotations/integration-junit4.adoc[]
|
||||
**** xref:testing/annotations/integration-junit-jupiter.adoc[]
|
||||
**** xref:testing/annotations/integration-meta.adoc[]
|
||||
*** xref:testing/resources.adoc[]
|
||||
* xref:data-access.adoc[]
|
||||
** xref:data-access/transaction.adoc[]
|
||||
*** xref:data-access/transaction/motivation.adoc[]
|
||||
*** xref:data-access/transaction/strategies.adoc[]
|
||||
*** xref:data-access/transaction/tx-resource-synchronization.adoc[]
|
||||
*** xref:data-access/transaction/declarative.adoc[]
|
||||
**** xref:data-access/transaction/declarative/tx-decl-explained.adoc[]
|
||||
**** xref:data-access/transaction/declarative/first-example.adoc[]
|
||||
**** xref:data-access/transaction/declarative/rolling-back.adoc[]
|
||||
**** xref:data-access/transaction/declarative/diff-tx.adoc[]
|
||||
**** xref:data-access/transaction/declarative/txadvice-settings.adoc[]
|
||||
**** xref:data-access/transaction/declarative/annotations.adoc[]
|
||||
**** xref:data-access/transaction/declarative/tx-propagation.adoc[]
|
||||
**** xref:data-access/transaction/declarative/applying-more-than-just-tx-advice.adoc[]
|
||||
**** xref:data-access/transaction/declarative/aspectj.adoc[]
|
||||
*** xref:data-access/transaction/programmatic.adoc[]
|
||||
*** xref:data-access/transaction/tx-decl-vs-prog.adoc[]
|
||||
*** xref:data-access/transaction/event.adoc[]
|
||||
*** xref:data-access/transaction/application-server-integration.adoc[]
|
||||
*** xref:data-access/transaction/solutions-to-common-problems.adoc[]
|
||||
*** xref:data-access/transaction/resources.adoc[]
|
||||
** xref:data-access/dao.adoc[]
|
||||
** xref:data-access/jdbc.adoc[]
|
||||
*** xref:data-access/jdbc/choose-style.adoc[]
|
||||
*** xref:data-access/jdbc/packages.adoc[]
|
||||
*** xref:data-access/jdbc/core.adoc[]
|
||||
*** xref:data-access/jdbc/connections.adoc[]
|
||||
*** xref:data-access/jdbc/advanced.adoc[]
|
||||
*** xref:data-access/jdbc/simple.adoc[]
|
||||
*** xref:data-access/jdbc/object.adoc[]
|
||||
*** xref:data-access/jdbc/parameter-handling.adoc[]
|
||||
*** xref:data-access/jdbc/embedded-database-support.adoc[]
|
||||
*** xref:data-access/jdbc/initializing-datasource.adoc[]
|
||||
** xref:data-access/r2dbc.adoc[]
|
||||
** xref:data-access/orm.adoc[]
|
||||
*** xref:data-access/orm/introduction.adoc[]
|
||||
*** xref:data-access/orm/general.adoc[]
|
||||
*** xref:data-access/orm/hibernate.adoc[]
|
||||
*** xref:data-access/orm/jpa.adoc[]
|
||||
** xref:data-access/oxm.adoc[]
|
||||
** xref:data-access/appendix.adoc[]
|
||||
* xref:web.adoc[]
|
||||
** xref:web/webmvc.adoc[]
|
||||
*** xref:web/webmvc/mvc-servlet.adoc[]
|
||||
**** xref:web/webmvc/mvc-servlet/context-hierarchy.adoc[]
|
||||
**** xref:web/webmvc/mvc-servlet/special-bean-types.adoc[]
|
||||
**** xref:web/webmvc/mvc-servlet/config.adoc[]
|
||||
**** xref:web/webmvc/mvc-servlet/container-config.adoc[]
|
||||
**** xref:web/webmvc/mvc-servlet/sequence.adoc[]
|
||||
**** xref:web/webmvc/mvc-servlet/handlermapping-path.adoc[]
|
||||
**** xref:web/webmvc/mvc-servlet/handlermapping-interceptor.adoc[]
|
||||
**** xref:web/webmvc/mvc-servlet/exceptionhandlers.adoc[]
|
||||
**** xref:web/webmvc/mvc-servlet/viewresolver.adoc[]
|
||||
**** xref:web/webmvc/mvc-servlet/localeresolver.adoc[]
|
||||
**** xref:web/webmvc/mvc-servlet/themeresolver.adoc[]
|
||||
**** xref:web/webmvc/mvc-servlet/multipart.adoc[]
|
||||
**** xref:web/webmvc/mvc-servlet/logging.adoc[]
|
||||
*** xref:web/webmvc/filters.adoc[]
|
||||
*** xref:web/webmvc/mvc-controller.adoc[]
|
||||
**** xref:web/webmvc/mvc-controller/ann.adoc[]
|
||||
**** xref:web/webmvc/mvc-controller/ann-requestmapping.adoc[]
|
||||
**** xref:web/webmvc/mvc-controller/ann-methods.adoc[]
|
||||
***** xref:web/webmvc/mvc-controller/ann-methods/arguments.adoc[]
|
||||
***** xref:web/webmvc/mvc-controller/ann-methods/return-types.adoc[]
|
||||
***** xref:web/webmvc/mvc-controller/ann-methods/typeconversion.adoc[]
|
||||
***** xref:web/webmvc/mvc-controller/ann-methods/matrix-variables.adoc[]
|
||||
***** xref:web/webmvc/mvc-controller/ann-methods/requestparam.adoc[]
|
||||
***** xref:web/webmvc/mvc-controller/ann-methods/requestheader.adoc[]
|
||||
***** xref:web/webmvc/mvc-controller/ann-methods/cookievalue.adoc[]
|
||||
***** xref:web/webmvc/mvc-controller/ann-methods/modelattrib-method-args.adoc[]
|
||||
***** xref:web/webmvc/mvc-controller/ann-methods/sessionattributes.adoc[]
|
||||
***** xref:web/webmvc/mvc-controller/ann-methods/sessionattribute.adoc[]
|
||||
***** xref:web/webmvc/mvc-controller/ann-methods/requestattrib.adoc[]
|
||||
***** xref:web/webmvc/mvc-controller/ann-methods/redirecting-passing-data.adoc[]
|
||||
***** xref:web/webmvc/mvc-controller/ann-methods/flash-attributes.adoc[]
|
||||
***** xref:web/webmvc/mvc-controller/ann-methods/multipart-forms.adoc[]
|
||||
***** xref:web/webmvc/mvc-controller/ann-methods/requestbody.adoc[]
|
||||
***** xref:web/webmvc/mvc-controller/ann-methods/httpentity.adoc[]
|
||||
***** xref:web/webmvc/mvc-controller/ann-methods/responsebody.adoc[]
|
||||
***** xref:web/webmvc/mvc-controller/ann-methods/responseentity.adoc[]
|
||||
***** xref:web/webmvc/mvc-controller/ann-methods/jackson.adoc[]
|
||||
**** xref:web/webmvc/mvc-controller/ann-modelattrib-methods.adoc[]
|
||||
**** xref:web/webmvc/mvc-controller/ann-initbinder.adoc[]
|
||||
**** xref:web/webmvc/mvc-controller/ann-validation.adoc[]
|
||||
**** xref:web/webmvc/mvc-controller/ann-exceptionhandler.adoc[]
|
||||
**** xref:web/webmvc/mvc-controller/ann-advice.adoc[]
|
||||
*** xref:web/webmvc-functional.adoc[]
|
||||
*** xref:web/webmvc/mvc-uri-building.adoc[]
|
||||
*** xref:web/webmvc/mvc-ann-async.adoc[]
|
||||
*** xref:web/webmvc-cors.adoc[]
|
||||
*** xref:web/webmvc/mvc-ann-rest-exceptions.adoc[]
|
||||
*** xref:web/webmvc/mvc-security.adoc[]
|
||||
*** xref:web/webmvc/mvc-caching.adoc[]
|
||||
*** xref:web/webmvc-view.adoc[]
|
||||
**** xref:web/webmvc-view/mvc-thymeleaf.adoc[]
|
||||
**** xref:web/webmvc-view/mvc-freemarker.adoc[]
|
||||
**** xref:web/webmvc-view/mvc-groovymarkup.adoc[]
|
||||
**** xref:web/webmvc-view/mvc-script.adoc[]
|
||||
**** xref:web/webmvc-view/mvc-jsp.adoc[]
|
||||
**** xref:web/webmvc-view/mvc-feeds.adoc[]
|
||||
**** xref:web/webmvc-view/mvc-document.adoc[]
|
||||
**** xref:web/webmvc-view/mvc-jackson.adoc[]
|
||||
**** xref:web/webmvc-view/mvc-xml-marshalling.adoc[]
|
||||
**** xref:web/webmvc-view/mvc-xslt.adoc[]
|
||||
*** xref:web/webmvc/mvc-config.adoc[]
|
||||
**** xref:web/webmvc/mvc-config/enable.adoc[]
|
||||
**** xref:web/webmvc/mvc-config/customize.adoc[]
|
||||
**** xref:web/webmvc/mvc-config/conversion.adoc[]
|
||||
**** xref:web/webmvc/mvc-config/validation.adoc[]
|
||||
**** xref:web/webmvc/mvc-config/interceptors.adoc[]
|
||||
**** xref:web/webmvc/mvc-config/content-negotiation.adoc[]
|
||||
**** xref:web/webmvc/mvc-config/message-converters.adoc[]
|
||||
**** xref:web/webmvc/mvc-config/view-controller.adoc[]
|
||||
**** xref:web/webmvc/mvc-config/view-resolvers.adoc[]
|
||||
**** xref:web/webmvc/mvc-config/static-resources.adoc[]
|
||||
**** xref:web/webmvc/mvc-config/default-servlet-handler.adoc[]
|
||||
**** xref:web/webmvc/mvc-config/path-matching.adoc[]
|
||||
**** xref:web/webmvc/mvc-config/advanced-java.adoc[]
|
||||
**** xref:web/webmvc/mvc-config/advanced-xml.adoc[]
|
||||
*** xref:web/webmvc/mvc-http2.adoc[]
|
||||
** xref:web/webmvc-client.adoc[]
|
||||
** xref:web/webmvc-test.adoc[]
|
||||
** xref:web/websocket.adoc[]
|
||||
*** xref:web/websocket/server.adoc[]
|
||||
*** xref:web/websocket/fallback.adoc[]
|
||||
*** xref:web/websocket/stomp.adoc[]
|
||||
**** xref:web/websocket/stomp/overview.adoc[]
|
||||
**** xref:web/websocket/stomp/benefits.adoc[]
|
||||
**** xref:web/websocket/stomp/enable.adoc[]
|
||||
**** xref:web/websocket/stomp/server-config.adoc[]
|
||||
**** xref:web/websocket/stomp/message-flow.adoc[]
|
||||
**** xref:web/websocket/stomp/handle-annotations.adoc[]
|
||||
**** xref:web/websocket/stomp/handle-send.adoc[]
|
||||
**** xref:web/websocket/stomp/handle-simple-broker.adoc[]
|
||||
**** xref:web/websocket/stomp/handle-broker-relay.adoc[]
|
||||
**** xref:web/websocket/stomp/handle-broker-relay-configure.adoc[]
|
||||
**** xref:web/websocket/stomp/destination-separator.adoc[]
|
||||
**** xref:web/websocket/stomp/authentication.adoc[]
|
||||
**** xref:web/websocket/stomp/authentication-token-based.adoc[]
|
||||
**** xref:web/websocket/stomp/authorization.adoc[]
|
||||
**** xref:web/websocket/stomp/user-destination.adoc[]
|
||||
**** xref:web/websocket/stomp/ordered-messages.adoc[]
|
||||
**** xref:web/websocket/stomp/application-context-events.adoc[]
|
||||
**** xref:web/websocket/stomp/interceptors.adoc[]
|
||||
**** xref:web/websocket/stomp/client.adoc[]
|
||||
**** xref:web/websocket/stomp/scope.adoc[]
|
||||
**** xref:web/websocket/stomp/configuration-performance.adoc[]
|
||||
**** xref:web/websocket/stomp/stats.adoc[]
|
||||
**** xref:web/websocket/stomp/testing.adoc[]
|
||||
** xref:web/integration.adoc[]
|
||||
* xref:web-reactive.adoc[]
|
||||
** xref:web/webflux.adoc[]
|
||||
*** xref:web/webflux/new-framework.adoc[]
|
||||
*** xref:web/webflux/reactive-spring.adoc[]
|
||||
*** xref:web/webflux/dispatcher-handler.adoc[]
|
||||
*** xref:web/webflux/controller.adoc[]
|
||||
**** xref:web/webflux/controller/ann.adoc[]
|
||||
**** xref:web/webflux/controller/ann-requestmapping.adoc[]
|
||||
**** xref:web/webflux/controller/ann-methods.adoc[]
|
||||
***** xref:web/webflux/controller/ann-methods/arguments.adoc[]
|
||||
***** xref:web/webflux/controller/ann-methods/return-types.adoc[]
|
||||
***** xref:web/webflux/controller/ann-methods/typeconversion.adoc[]
|
||||
***** xref:web/webflux/controller/ann-methods/matrix-variables.adoc[]
|
||||
***** xref:web/webflux/controller/ann-methods/requestparam.adoc[]
|
||||
***** xref:web/webflux/controller/ann-methods/requestheader.adoc[]
|
||||
***** xref:web/webflux/controller/ann-methods/cookievalue.adoc[]
|
||||
***** xref:web/webflux/controller/ann-methods/modelattrib-method-args.adoc[]
|
||||
***** xref:web/webflux/controller/ann-methods/sessionattributes.adoc[]
|
||||
***** xref:web/webflux/controller/ann-methods/sessionattribute.adoc[]
|
||||
***** xref:web/webflux/controller/ann-methods/requestattrib.adoc[]
|
||||
***** xref:web/webflux/controller/ann-methods/multipart-forms.adoc[]
|
||||
***** xref:web/webflux/controller/ann-methods/requestbody.adoc[]
|
||||
***** xref:web/webflux/controller/ann-methods/httpentity.adoc[]
|
||||
***** xref:web/webflux/controller/ann-methods/responsebody.adoc[]
|
||||
***** xref:web/webflux/controller/ann-methods/responseentity.adoc[]
|
||||
***** xref:web/webflux/controller/ann-methods/jackson.adoc[]
|
||||
**** xref:web/webflux/controller/ann-modelattrib-methods.adoc[]
|
||||
**** xref:web/webflux/controller/ann-initbinder.adoc[]
|
||||
**** xref:web/webflux/controller/ann-validation.adoc[]
|
||||
**** xref:web/webflux/controller/ann-exceptions.adoc[]
|
||||
**** xref:web/webflux/controller/ann-advice.adoc[]
|
||||
*** xref:web/webflux-functional.adoc[]
|
||||
*** xref:web/webflux/uri-building.adoc[]
|
||||
*** xref:web/webflux-cors.adoc[]
|
||||
*** xref:web/webflux/ann-rest-exceptions.adoc[]
|
||||
*** xref:web/webflux/security.adoc[]
|
||||
*** xref:web/webflux/caching.adoc[]
|
||||
*** xref:web/webflux-view.adoc[]
|
||||
*** xref:web/webflux/config.adoc[]
|
||||
*** xref:web/webflux/http2.adoc[]
|
||||
** xref:web/webflux-webclient.adoc[]
|
||||
*** xref:web/webflux-webclient/client-builder.adoc[]
|
||||
*** xref:web/webflux-webclient/client-retrieve.adoc[]
|
||||
*** xref:web/webflux-webclient/client-exchange.adoc[]
|
||||
*** xref:web/webflux-webclient/client-body.adoc[]
|
||||
*** xref:web/webflux-webclient/client-filter.adoc[]
|
||||
*** xref:web/webflux-webclient/client-attributes.adoc[]
|
||||
*** xref:web/webflux-webclient/client-context.adoc[]
|
||||
*** xref:web/webflux-webclient/client-synchronous.adoc[]
|
||||
*** xref:web/webflux-webclient/client-testing.adoc[]
|
||||
** xref:web/webflux-http-interface-client.adoc[]
|
||||
** xref:web/webflux-websocket.adoc[]
|
||||
** xref:web/webflux-test.adoc[]
|
||||
** xref:rsocket.adoc[]
|
||||
** xref:web/webflux-reactive-libraries.adoc[]
|
||||
* xref:integration.adoc[]
|
||||
** xref:integration/rest-clients.adoc[]
|
||||
** xref:integration/jms.adoc[]
|
||||
*** xref:integration/jms/using.adoc[]
|
||||
*** xref:integration/jms/sending.adoc[]
|
||||
*** xref:integration/jms/receiving.adoc[]
|
||||
*** xref:integration/jms/jca-message-endpoint-manager.adoc[]
|
||||
*** xref:integration/jms/annotated.adoc[]
|
||||
*** xref:integration/jms/namespace.adoc[]
|
||||
** xref:integration/jmx.adoc[]
|
||||
*** xref:integration/jmx/exporting.adoc[]
|
||||
*** xref:integration/jmx/interface.adoc[]
|
||||
*** xref:integration/jmx/naming.adoc[]
|
||||
*** xref:integration/jmx/jsr160.adoc[]
|
||||
*** xref:integration/jmx/proxy.adoc[]
|
||||
*** xref:integration/jmx/notifications.adoc[]
|
||||
*** xref:integration/jmx/resources.adoc[]
|
||||
** xref:integration/email.adoc[]
|
||||
** xref:integration/scheduling.adoc[]
|
||||
** xref:integration/cache.adoc[]
|
||||
*** xref:integration/cache/strategies.adoc[]
|
||||
*** xref:integration/cache/annotations.adoc[]
|
||||
*** xref:integration/cache/jsr-107.adoc[]
|
||||
*** xref:integration/cache/declarative-xml.adoc[]
|
||||
*** xref:integration/cache/store-configuration.adoc[]
|
||||
*** xref:integration/cache/plug.adoc[]
|
||||
*** xref:integration/cache/specific-config.adoc[]
|
||||
** xref:integration/observability.adoc[]
|
||||
** xref:integration/checkpoint-restore.adoc[]
|
||||
** xref:integration/class-data-sharing.adoc[]
|
||||
** xref:integration/appendix.adoc[]
|
||||
* xref:languages.adoc[]
|
||||
** xref:languages/kotlin.adoc[]
|
||||
*** xref:languages/kotlin/requirements.adoc[]
|
||||
*** xref:languages/kotlin/extensions.adoc[]
|
||||
*** xref:languages/kotlin/null-safety.adoc[]
|
||||
*** xref:languages/kotlin/classes-interfaces.adoc[]
|
||||
*** xref:languages/kotlin/annotations.adoc[]
|
||||
*** xref:languages/kotlin/bean-definition-dsl.adoc[]
|
||||
*** xref:languages/kotlin/web.adoc[]
|
||||
*** xref:languages/kotlin/coroutines.adoc[]
|
||||
*** xref:languages/kotlin/spring-projects-in.adoc[]
|
||||
*** xref:languages/kotlin/getting-started.adoc[]
|
||||
*** xref:languages/kotlin/resources.adoc[]
|
||||
** xref:languages/groovy.adoc[]
|
||||
** xref:languages/dynamic.adoc[]
|
||||
* xref:appendix.adoc[]
|
||||
* {spring-framework-wiki}[Wiki]
|
||||
@@ -1,81 +0,0 @@
|
||||
[[appendix]]
|
||||
= Appendix
|
||||
|
||||
This part of the reference documentation covers topics that apply to multiple modules
|
||||
within the core Spring Framework.
|
||||
|
||||
|
||||
[[appendix-spring-properties]]
|
||||
== Spring Properties
|
||||
|
||||
{spring-framework-api}/core/SpringProperties.html[`SpringProperties`] is a static holder
|
||||
for properties that control certain low-level aspects of the Spring Framework. Users can
|
||||
configure these properties via JVM system properties or programmatically via the
|
||||
`SpringProperties.setProperty(String key, String value)` method. The latter may be
|
||||
necessary if the deployment environment disallows custom JVM system properties. As an
|
||||
alternative, these properties may be configured in a `spring.properties` file in the root
|
||||
of the classpath -- for example, deployed within the application's JAR file.
|
||||
|
||||
The following table lists all currently supported Spring properties.
|
||||
|
||||
.Supported Spring Properties
|
||||
|===
|
||||
| Name | Description
|
||||
|
||||
| `spring.beaninfo.ignore`
|
||||
| Instructs Spring to use the `Introspector.IGNORE_ALL_BEANINFO` mode when calling the
|
||||
JavaBeans `Introspector`. See
|
||||
{spring-framework-api}++/beans/StandardBeanInfoFactory.html#IGNORE_BEANINFO_PROPERTY_NAME++[`CachedIntrospectionResults`]
|
||||
for details.
|
||||
|
||||
| `spring.expression.compiler.mode`
|
||||
| The mode to use when compiling expressions for the
|
||||
xref:core/expressions/evaluation.adoc#expressions-compiler-configuration[Spring Expression Language].
|
||||
|
||||
| `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
|
||||
resolvable otherwise. See
|
||||
{spring-framework-api}++/core/env/AbstractEnvironment.html#IGNORE_GETENV_PROPERTY_NAME++[`AbstractEnvironment`]
|
||||
for details.
|
||||
|
||||
| `spring.jdbc.getParameterType.ignore`
|
||||
| Instructs Spring to ignore `java.sql.ParameterMetaData.getParameterType` completely.
|
||||
See the note in xref:data-access/jdbc/advanced.adoc#jdbc-batch-list[Batch Operations with a List of Objects].
|
||||
|
||||
| `spring.jndi.ignore`
|
||||
| Instructs Spring to ignore a default JNDI environment, as an optimization for scenarios
|
||||
where nothing is ever to be found for such JNDI fallback searches to begin with, avoiding
|
||||
the repeated JNDI lookup overhead. See
|
||||
{spring-framework-api}++/jndi/JndiLocatorDelegate.html#IGNORE_JNDI_PROPERTY_NAME++[`JndiLocatorDelegate`]
|
||||
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.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.
|
||||
See xref:testing/testcontext-framework/aot.adoc[Ahead of Time Support for Tests].
|
||||
|
||||
| `spring.test.constructor.autowire.mode`
|
||||
| The default _test constructor autowire mode_ to use if `@TestConstructor` is not present
|
||||
on a test class. See xref:testing/annotations/integration-junit-jupiter.adoc#integration-testing-annotations-testconstructor[Changing the default test constructor autowire mode].
|
||||
|
||||
| `spring.test.context.cache.maxSize`
|
||||
| The maximum size of the context cache in the _Spring TestContext Framework_. See
|
||||
xref:testing/testcontext-framework/ctx-management/caching.adoc[Context Caching].
|
||||
|
||||
| `spring.test.context.failure.threshold`
|
||||
| The failure threshold for errors encountered while attempting to load an `ApplicationContext`
|
||||
in the _Spring TestContext Framework_. See
|
||||
xref:testing/testcontext-framework/ctx-management/failure-threshold.adoc[Context Failure Threshold].
|
||||
|
||||
| `spring.test.enclosing.configuration`
|
||||
| The default _enclosing configuration inheritance mode_ to use if
|
||||
`@NestedTestConfiguration` is not present on a test class. See
|
||||
xref:testing/annotations/integration-junit-jupiter.adoc#integration-testing-annotations-nestedtestconfiguration[Changing the default enclosing configuration inheritance mode].
|
||||
|
||||
|===
|
||||
@@ -1,30 +0,0 @@
|
||||
[[spring-core]]
|
||||
= Core Technologies
|
||||
|
||||
This part of the reference documentation covers all the technologies that are
|
||||
absolutely integral to the Spring Framework.
|
||||
|
||||
Foremost amongst these is the Spring Framework's Inversion of Control (IoC) container.
|
||||
A thorough treatment of the Spring Framework's IoC container is closely followed by
|
||||
comprehensive coverage of Spring's Aspect-Oriented Programming (AOP) technologies.
|
||||
The Spring Framework has its own AOP framework, which is conceptually easy to
|
||||
understand and which successfully addresses the 80% sweet spot of AOP requirements
|
||||
in Java enterprise programming.
|
||||
|
||||
Coverage of Spring's integration with AspectJ (currently the richest -- in terms of
|
||||
features -- and certainly most mature AOP implementation in the Java enterprise space)
|
||||
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.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
[[aop-api]]
|
||||
= Spring AOP APIs
|
||||
:page-section-summary-toc: 1
|
||||
|
||||
The previous chapter described the Spring's support for AOP with @AspectJ and schema-based
|
||||
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.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,592 +0,0 @@
|
||||
[[aop-api-advice]]
|
||||
= Advice API in Spring
|
||||
|
||||
Now we can examine how Spring AOP handles advice.
|
||||
|
||||
|
||||
|
||||
[[aop-api-advice-lifecycle]]
|
||||
== Advice Lifecycles
|
||||
|
||||
Each advice is a Spring bean. An advice instance can be shared across all advised
|
||||
objects or be unique to each advised object. This corresponds to per-class or
|
||||
per-instance advice.
|
||||
|
||||
Per-class advice is used most often. It is appropriate for generic advice, such as
|
||||
transaction advisors. These do not depend on the state of the proxied object or add new
|
||||
state. They merely act on the method and arguments.
|
||||
|
||||
Per-instance advice is appropriate for introductions, to support mixins. In this case,
|
||||
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
|
||||
|
||||
The most fundamental advice type in Spring is interception around advice.
|
||||
|
||||
Spring is compliant with the AOP `Alliance` interface for around advice that uses method
|
||||
interception. Classes that implement `MethodInterceptor` and that implement around advice should also implement the
|
||||
following interface:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
public interface MethodInterceptor extends Interceptor {
|
||||
|
||||
Object invoke(MethodInvocation invocation) throws Throwable;
|
||||
}
|
||||
----
|
||||
|
||||
The `MethodInvocation` argument to the `invoke()` method exposes the method being
|
||||
invoked, the target join point, the AOP proxy, and the arguments to the method. The
|
||||
`invoke()` method should return the invocation's result: the return value of the join
|
||||
point.
|
||||
|
||||
The following example shows a simple `MethodInterceptor` implementation:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
public class DebugInterceptor implements MethodInterceptor {
|
||||
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
System.out.println("Before: invocation=[" + invocation + "]");
|
||||
Object rval = invocation.proceed();
|
||||
System.out.println("Invocation returned");
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
class DebugInterceptor : MethodInterceptor {
|
||||
|
||||
override fun invoke(invocation: MethodInvocation): Any {
|
||||
println("Before: invocation=[$invocation]")
|
||||
val rval = invocation.proceed()
|
||||
println("Invocation returned")
|
||||
return rval
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
Note the call to the `proceed()` method of `MethodInvocation`. This proceeds down the
|
||||
interceptor chain towards the join point. Most interceptors invoke this method and
|
||||
return its return value. However, a `MethodInterceptor`, like any around advice, can
|
||||
return a different value or throw an exception rather than invoke the proceed method.
|
||||
However, you do not want to do this without good reason.
|
||||
|
||||
NOTE: `MethodInterceptor` implementations offer interoperability with other AOP Alliance-compliant AOP
|
||||
implementations. The other advice types discussed in the remainder of this section
|
||||
implement common AOP concepts but in a Spring-specific way. While there is an advantage
|
||||
in using the most specific advice type, stick with `MethodInterceptor` around advice if
|
||||
you are likely to want to run the aspect in another AOP framework. Note that pointcuts
|
||||
are not currently interoperable between frameworks, and the AOP Alliance does not
|
||||
currently define pointcut interfaces.
|
||||
|
||||
|
||||
[[aop-api-advice-before]]
|
||||
=== Before Advice
|
||||
|
||||
A simpler advice type is a before advice. This does not need a `MethodInvocation`
|
||||
object, since it is called only before entering the method.
|
||||
|
||||
The main advantage of a before advice is that there is no need to invoke the `proceed()`
|
||||
method and, therefore, no possibility of inadvertently failing to proceed down the
|
||||
interceptor chain.
|
||||
|
||||
The following listing shows the `MethodBeforeAdvice` interface:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
public interface MethodBeforeAdvice extends BeforeAdvice {
|
||||
|
||||
void before(Method m, Object[] args, Object target) throws Throwable;
|
||||
}
|
||||
----
|
||||
|
||||
(Spring's API design would allow for
|
||||
field before advice, although the usual objects apply to field interception and it is
|
||||
unlikely for Spring to ever implement it.)
|
||||
|
||||
Note that the return type is `void`. Before advice can insert custom behavior before the join
|
||||
point runs but cannot change the return value. If a before advice throws an
|
||||
exception, it stops further execution of the interceptor chain. The exception
|
||||
propagates back up the interceptor chain. If it is unchecked or on the signature of
|
||||
the invoked method, it is passed directly to the client. Otherwise, it is
|
||||
wrapped in an unchecked exception by the AOP proxy.
|
||||
|
||||
The following example shows a before advice in Spring, which counts all method invocations:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
public class CountingBeforeAdvice implements MethodBeforeAdvice {
|
||||
|
||||
private int count;
|
||||
|
||||
public void before(Method m, Object[] args, Object target) throws Throwable {
|
||||
++count;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
class CountingBeforeAdvice : MethodBeforeAdvice {
|
||||
|
||||
var count: Int = 0
|
||||
|
||||
override fun before(m: Method, args: Array<Any>, target: Any?) {
|
||||
++count
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
TIP: Before advice can be used with any pointcut.
|
||||
|
||||
|
||||
[[aop-api-advice-throws]]
|
||||
=== Throws Advice
|
||||
|
||||
Throws advice is invoked after the return of the join point if the join point threw
|
||||
an exception. Spring offers typed throws advice. Note that this means that the
|
||||
`org.springframework.aop.ThrowsAdvice` interface does not contain any methods. It is a
|
||||
tag interface identifying that the given object implements one or more typed throws
|
||||
advice methods. These should be in the following form:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
afterThrowing([Method, args, target], subclassOfThrowable)
|
||||
----
|
||||
|
||||
Only the last argument is required. The method signatures may have either one or four
|
||||
arguments, depending on whether the advice method is interested in the method and
|
||||
arguments. The next two listing show classes that are examples of throws advice.
|
||||
|
||||
The following advice is invoked if a `RemoteException` is thrown (including from subclasses):
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
public class RemoteThrowsAdvice implements ThrowsAdvice {
|
||||
|
||||
public void afterThrowing(RemoteException ex) throws Throwable {
|
||||
// Do something with remote exception
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
class RemoteThrowsAdvice : ThrowsAdvice {
|
||||
|
||||
fun afterThrowing(ex: RemoteException) {
|
||||
// Do something with remote exception
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
Unlike the preceding
|
||||
advice, the next example declares four arguments, so that it has access to the invoked method, method
|
||||
arguments, and target object. The following advice is invoked if a `ServletException` is thrown:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
public class ServletThrowsAdviceWithArguments implements ThrowsAdvice {
|
||||
|
||||
public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) {
|
||||
// Do something with all arguments
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
class ServletThrowsAdviceWithArguments : ThrowsAdvice {
|
||||
|
||||
fun afterThrowing(m: Method, args: Array<Any>, target: Any, ex: ServletException) {
|
||||
// Do something with all arguments
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The final example illustrates how these two methods could be used in a single class
|
||||
that handles both `RemoteException` and `ServletException`. Any number of throws advice
|
||||
methods can be combined in a single class. The following listing shows the final example:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
public static class CombinedThrowsAdvice implements ThrowsAdvice {
|
||||
|
||||
public void afterThrowing(RemoteException ex) throws Throwable {
|
||||
// Do something with remote exception
|
||||
}
|
||||
|
||||
public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) {
|
||||
// Do something with all arguments
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
class CombinedThrowsAdvice : ThrowsAdvice {
|
||||
|
||||
fun afterThrowing(ex: RemoteException) {
|
||||
// Do something with remote exception
|
||||
}
|
||||
|
||||
fun afterThrowing(m: Method, args: Array<Any>, target: Any, ex: ServletException) {
|
||||
// Do something with all arguments
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
NOTE: If a throws-advice method throws an exception itself, it overrides the
|
||||
original exception (that is, it changes the exception thrown to the user). The overriding
|
||||
exception is typically a RuntimeException, which is compatible with any method
|
||||
signature. However, if a throws-advice method throws a checked exception, it must
|
||||
match the declared exceptions of the target method and is, hence, to some degree
|
||||
coupled to specific target method signatures. _Do not throw an undeclared checked
|
||||
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
|
||||
|
||||
An after returning advice in Spring must implement the
|
||||
`org.springframework.aop.AfterReturningAdvice` interface, which the following listing shows:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
public interface AfterReturningAdvice extends Advice {
|
||||
|
||||
void afterReturning(Object returnValue, Method m, Object[] args, Object target)
|
||||
throws Throwable;
|
||||
}
|
||||
----
|
||||
|
||||
An after returning advice has access to the return value (which it cannot modify),
|
||||
the invoked method, the method's arguments, and the target.
|
||||
|
||||
The following after returning advice counts all successful method invocations that have
|
||||
not thrown exceptions:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
public class CountingAfterReturningAdvice implements AfterReturningAdvice {
|
||||
|
||||
private int count;
|
||||
|
||||
public void afterReturning(Object returnValue, Method m, Object[] args, Object target)
|
||||
throws Throwable {
|
||||
++count;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
class CountingAfterReturningAdvice : AfterReturningAdvice {
|
||||
|
||||
var count: Int = 0
|
||||
private set
|
||||
|
||||
override fun afterReturning(returnValue: Any?, m: Method, args: Array<Any>, target: Any?) {
|
||||
++count
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
This advice does not change the execution path. If it throws an exception, it is
|
||||
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
|
||||
|
||||
Spring treats introduction advice as a special kind of interception advice.
|
||||
|
||||
Introduction requires an `IntroductionAdvisor` and an `IntroductionInterceptor` that
|
||||
implement the following interface:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
public interface IntroductionInterceptor extends MethodInterceptor {
|
||||
|
||||
boolean implementsInterface(Class intf);
|
||||
}
|
||||
----
|
||||
|
||||
The `invoke()` method inherited from the AOP Alliance `MethodInterceptor` interface must
|
||||
implement the introduction. That is, if the invoked method is on an introduced
|
||||
interface, the introduction interceptor is responsible for handling the method call -- it
|
||||
cannot invoke `proceed()`.
|
||||
|
||||
Introduction advice cannot be used with any pointcut, as it applies only at the class,
|
||||
rather than the method, level. You can only use introduction advice with the
|
||||
`IntroductionAdvisor`, which has the following methods:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
public interface IntroductionAdvisor extends Advisor, IntroductionInfo {
|
||||
|
||||
ClassFilter getClassFilter();
|
||||
|
||||
void validateInterfaces() throws IllegalArgumentException;
|
||||
}
|
||||
|
||||
public interface IntroductionInfo {
|
||||
|
||||
Class<?>[] getInterfaces();
|
||||
}
|
||||
----
|
||||
|
||||
There is no `MethodMatcher` and, hence, no `Pointcut` associated with introduction
|
||||
advice. Only class filtering is logical.
|
||||
|
||||
The `getInterfaces()` method returns the interfaces introduced by this advisor.
|
||||
|
||||
The `validateInterfaces()` method is used internally to see whether or not the
|
||||
introduced interfaces can be implemented by the configured `IntroductionInterceptor`.
|
||||
|
||||
Consider an example from the Spring test suite and suppose we want to
|
||||
introduce the following interface to one or more objects:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
public interface Lockable {
|
||||
void lock();
|
||||
void unlock();
|
||||
boolean locked();
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
interface Lockable {
|
||||
fun lock()
|
||||
fun unlock()
|
||||
fun locked(): Boolean
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
This illustrates a mixin. We want to be able to cast advised objects to `Lockable`,
|
||||
whatever their type and call lock and unlock methods. If we call the `lock()` method, we
|
||||
want all setter methods to throw a `LockedException`. Thus, we can add an aspect that
|
||||
provides the ability to make objects immutable without them having any knowledge of it:
|
||||
a good example of AOP.
|
||||
|
||||
First, we need an `IntroductionInterceptor` that does the heavy lifting. In this
|
||||
case, we extend the `org.springframework.aop.support.DelegatingIntroductionInterceptor`
|
||||
convenience class. We could implement `IntroductionInterceptor` directly, but using
|
||||
`DelegatingIntroductionInterceptor` is best for most cases.
|
||||
|
||||
The `DelegatingIntroductionInterceptor` is designed to delegate an introduction to an
|
||||
actual implementation of the introduced interfaces, concealing the use of interception
|
||||
to do so. You can set the delegate to any object using a constructor argument. The
|
||||
default delegate (when the no-argument constructor is used) is `this`. Thus, in the next example,
|
||||
the delegate is the `LockMixin` subclass of `DelegatingIntroductionInterceptor`.
|
||||
Given a delegate (by default, itself), a `DelegatingIntroductionInterceptor` instance
|
||||
looks for all interfaces implemented by the delegate (other than
|
||||
`IntroductionInterceptor`) and supports introductions against any of them.
|
||||
Subclasses such as `LockMixin` can call the `suppressInterface(Class intf)`
|
||||
method to suppress interfaces that should not be exposed. However, no matter how many
|
||||
interfaces an `IntroductionInterceptor` is prepared to support, the
|
||||
`IntroductionAdvisor` used controls which interfaces are actually exposed. An
|
||||
introduced interface conceals any implementation of the same interface by the target.
|
||||
|
||||
Thus, `LockMixin` extends `DelegatingIntroductionInterceptor` and implements `Lockable`
|
||||
itself. The superclass automatically picks up that `Lockable` can be supported for
|
||||
introduction, so we do not need to specify that. We could introduce any number of
|
||||
interfaces in this way.
|
||||
|
||||
Note the use of the `locked` instance variable. This effectively adds additional state
|
||||
to that held in the target object.
|
||||
|
||||
The following example shows the example `LockMixin` class:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
public class LockMixin extends DelegatingIntroductionInterceptor implements Lockable {
|
||||
|
||||
private boolean locked;
|
||||
|
||||
public void lock() {
|
||||
this.locked = true;
|
||||
}
|
||||
|
||||
public void unlock() {
|
||||
this.locked = false;
|
||||
}
|
||||
|
||||
public boolean locked() {
|
||||
return this.locked;
|
||||
}
|
||||
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
if (locked() && invocation.getMethod().getName().indexOf("set") == 0) {
|
||||
throw new LockedException();
|
||||
}
|
||||
return super.invoke(invocation);
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
class LockMixin : DelegatingIntroductionInterceptor(), Lockable {
|
||||
|
||||
private var locked: Boolean = false
|
||||
|
||||
fun lock() {
|
||||
this.locked = true
|
||||
}
|
||||
|
||||
fun unlock() {
|
||||
this.locked = false
|
||||
}
|
||||
|
||||
fun locked(): Boolean {
|
||||
return this.locked
|
||||
}
|
||||
|
||||
override fun invoke(invocation: MethodInvocation): Any? {
|
||||
if (locked() && invocation.method.name.indexOf("set") == 0) {
|
||||
throw LockedException()
|
||||
}
|
||||
return super.invoke(invocation)
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
Often, you need not override the `invoke()` method. The
|
||||
`DelegatingIntroductionInterceptor` implementation (which calls the `delegate` method if
|
||||
the method is introduced, otherwise proceeds towards the join point) usually
|
||||
suffices. In the present case, we need to add a check: no setter method can be invoked
|
||||
if in locked mode.
|
||||
|
||||
The required introduction only needs to hold a distinct
|
||||
`LockMixin` instance and specify the introduced interfaces (in this case, only
|
||||
`Lockable`). A more complex example might take a reference to the introduction
|
||||
interceptor (which would be defined as a prototype). In this case, there is no
|
||||
configuration relevant for a `LockMixin`, so we create it by using `new`.
|
||||
The following example shows our `LockMixinAdvisor` class:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
public class LockMixinAdvisor extends DefaultIntroductionAdvisor {
|
||||
|
||||
public LockMixinAdvisor() {
|
||||
super(new LockMixin(), Lockable.class);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
class LockMixinAdvisor : DefaultIntroductionAdvisor(LockMixin(), Lockable::class.java)
|
||||
----
|
||||
======
|
||||
|
||||
We can apply this advisor very simply, because it requires no configuration. (However, it
|
||||
is impossible to use an `IntroductionInterceptor` without an
|
||||
`IntroductionAdvisor`.) As usual with introductions, the advisor must be per-instance,
|
||||
as it is stateful. We need a different instance of `LockMixinAdvisor`, and hence
|
||||
`LockMixin`, for each advised object. The advisor comprises part of the advised object's
|
||||
state.
|
||||
|
||||
We can apply this advisor programmatically by using the `Advised.addAdvisor()` method or
|
||||
(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.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
[[aop-api-advised]]
|
||||
= Manipulating Advised Objects
|
||||
|
||||
However you create AOP proxies, you can manipulate them BY using the
|
||||
`org.springframework.aop.framework.Advised` interface. Any AOP proxy can be cast to this
|
||||
interface, no matter which other interfaces it implements. This interface includes the
|
||||
following methods:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
Advisor[] getAdvisors();
|
||||
|
||||
void addAdvice(Advice advice) throws AopConfigException;
|
||||
|
||||
void addAdvice(int pos, Advice advice) throws AopConfigException;
|
||||
|
||||
void addAdvisor(Advisor advisor) throws AopConfigException;
|
||||
|
||||
void addAdvisor(int pos, Advisor advisor) throws AopConfigException;
|
||||
|
||||
int indexOf(Advisor advisor);
|
||||
|
||||
boolean removeAdvisor(Advisor advisor) throws AopConfigException;
|
||||
|
||||
void removeAdvisor(int index) throws AopConfigException;
|
||||
|
||||
boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;
|
||||
|
||||
boolean isFrozen();
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
fun getAdvisors(): Array<Advisor>
|
||||
|
||||
@Throws(AopConfigException::class)
|
||||
fun addAdvice(advice: Advice)
|
||||
|
||||
@Throws(AopConfigException::class)
|
||||
fun addAdvice(pos: Int, advice: Advice)
|
||||
|
||||
@Throws(AopConfigException::class)
|
||||
fun addAdvisor(advisor: Advisor)
|
||||
|
||||
@Throws(AopConfigException::class)
|
||||
fun addAdvisor(pos: Int, advisor: Advisor)
|
||||
|
||||
fun indexOf(advisor: Advisor): Int
|
||||
|
||||
@Throws(AopConfigException::class)
|
||||
fun removeAdvisor(advisor: Advisor): Boolean
|
||||
|
||||
@Throws(AopConfigException::class)
|
||||
fun removeAdvisor(index: Int)
|
||||
|
||||
@Throws(AopConfigException::class)
|
||||
fun replaceAdvisor(a: Advisor, b: Advisor): Boolean
|
||||
|
||||
fun isFrozen(): Boolean
|
||||
----
|
||||
======
|
||||
|
||||
The `getAdvisors()` method returns an `Advisor` for every advisor, interceptor, or
|
||||
other advice type that has been added to the factory. If you added an `Advisor`, the
|
||||
returned advisor at this index is the object that you added. If you added an
|
||||
interceptor or other advice type, Spring wrapped this in an advisor with a
|
||||
pointcut that always returns `true`. Thus, if you added a `MethodInterceptor`, the advisor
|
||||
returned for this index is a `DefaultPointcutAdvisor` that returns your
|
||||
`MethodInterceptor` and a pointcut that matches all classes and methods.
|
||||
|
||||
The `addAdvisor()` methods can be used to add any `Advisor`. Usually, the advisor holding
|
||||
pointcut and advice is the generic `DefaultPointcutAdvisor`, which you can use with
|
||||
any advice or pointcut (but not for introductions).
|
||||
|
||||
By default, it is possible to add or remove advisors or interceptors even once a proxy
|
||||
has been created. The only restriction is that it is impossible to add or remove an
|
||||
introduction advisor, as existing proxies from the factory do not show the interface
|
||||
change. (You can obtain a new proxy from the factory to avoid this problem.)
|
||||
|
||||
The following example shows casting an AOP proxy to the `Advised` interface and examining and
|
||||
manipulating its advice:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
Advised advised = (Advised) myObject;
|
||||
Advisor[] advisors = advised.getAdvisors();
|
||||
int oldAdvisorCount = advisors.length;
|
||||
System.out.println(oldAdvisorCount + " advisors");
|
||||
|
||||
// Add an advice like an interceptor without a pointcut
|
||||
// Will match all proxied methods
|
||||
// Can use for interceptors, before, after returning or throws advice
|
||||
advised.addAdvice(new DebugInterceptor());
|
||||
|
||||
// Add selective advice using a pointcut
|
||||
advised.addAdvisor(new DefaultPointcutAdvisor(mySpecialPointcut, myAdvice));
|
||||
|
||||
assertEquals("Added two advisors", oldAdvisorCount + 2, advised.getAdvisors().length);
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
val advised = myObject as Advised
|
||||
val advisors = advised.advisors
|
||||
val oldAdvisorCount = advisors.size
|
||||
println("$oldAdvisorCount advisors")
|
||||
|
||||
// Add an advice like an interceptor without a pointcut
|
||||
// Will match all proxied methods
|
||||
// Can use for interceptors, before, after returning or throws advice
|
||||
advised.addAdvice(DebugInterceptor())
|
||||
|
||||
// Add selective advice using a pointcut
|
||||
advised.addAdvisor(DefaultPointcutAdvisor(mySpecialPointcut, myAdvice))
|
||||
|
||||
assertEquals("Added two advisors", oldAdvisorCount + 2, advised.advisors.size)
|
||||
----
|
||||
======
|
||||
|
||||
NOTE: It is questionable whether it is advisable (no pun intended) to modify advice on a
|
||||
business object in production, although there are, no doubt, legitimate usage cases.
|
||||
However, it can be very useful in development (for example, in tests). We have sometimes
|
||||
found it very useful to be able to add test code in the form of an interceptor or other
|
||||
advice, getting inside a method invocation that we want to test. (For example, the advice can
|
||||
get inside a transaction created for that method, perhaps to run SQL to check that
|
||||
a database was correctly updated, before marking the transaction for roll back.)
|
||||
|
||||
Depending on how you created the proxy, you can usually set a `frozen` flag. In that
|
||||
case, the `Advised` `isFrozen()` method returns `true`, and any attempts to modify
|
||||
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).
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
[[aop-api-advisor]]
|
||||
= The Advisor API in Spring
|
||||
:page-section-summary-toc: 1
|
||||
|
||||
In Spring, an Advisor is an aspect that contains only a single advice object associated
|
||||
with a pointcut expression.
|
||||
|
||||
Apart from the special case of introductions, any advisor can be used with any advice.
|
||||
`org.springframework.aop.support.DefaultPointcutAdvisor` is the most commonly used
|
||||
advisor class. It can be used with a `MethodInterceptor`, `BeforeAdvice`, or
|
||||
`ThrowsAdvice`.
|
||||
|
||||
It is possible to mix advisor and advice types in Spring in the same AOP proxy. For
|
||||
example, you could use an interception around advice, throws advice, and before advice in
|
||||
one proxy configuration. Spring automatically creates the necessary interceptor
|
||||
chain.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
[[aop-autoproxy]]
|
||||
= Using the "auto-proxy" facility
|
||||
|
||||
So far, we have considered explicit creation of AOP proxies by using a `ProxyFactoryBean` or
|
||||
similar factory bean.
|
||||
|
||||
Spring also lets us use "`auto-proxy`" bean definitions, which can automatically
|
||||
proxy selected bean definitions. This is built on Spring's "`bean post processor`"
|
||||
infrastructure, which enables modification of any bean definition as the container loads.
|
||||
|
||||
In this model, you set up some special bean definitions in your XML bean definition file
|
||||
to configure the auto-proxy infrastructure. This lets you declare the targets
|
||||
eligible for auto-proxying. You need not use `ProxyFactoryBean`.
|
||||
|
||||
There are two ways to do this:
|
||||
|
||||
* By using an auto-proxy creator that refers to specific beans in the current context.
|
||||
* A special case of auto-proxy creation that deserves to be considered separately:
|
||||
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`
|
||||
|
||||
The `BeanNameAutoProxyCreator` class is a `BeanPostProcessor` that automatically creates
|
||||
AOP proxies for beans with names that match literal values or wildcards. The following
|
||||
example shows how to create a `BeanNameAutoProxyCreator` bean:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
|
||||
<property name="beanNames" value="jdk*,onlyJdk"/>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<value>myInterceptor</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
|
||||
As with `ProxyFactoryBean`, there is an `interceptorNames` property rather than a list
|
||||
of interceptors, to allow correct behavior for prototype advisors. Named "`interceptors`"
|
||||
can be advisors or any advice type.
|
||||
|
||||
As with auto-proxying in general, the main point of using `BeanNameAutoProxyCreator` is
|
||||
to apply the same configuration consistently to multiple objects, with minimal volume of
|
||||
configuration. It is a popular choice for applying declarative transactions to multiple
|
||||
objects.
|
||||
|
||||
Bean definitions whose names match, such as `jdkMyBean` and `onlyJdk` in the preceding
|
||||
example, are plain old bean definitions with the target class. An AOP proxy is
|
||||
automatically created by the `BeanNameAutoProxyCreator`. The same advice is applied
|
||||
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`
|
||||
|
||||
A more general and extremely powerful auto-proxy creator is
|
||||
`DefaultAdvisorAutoProxyCreator`. This automagically applies eligible advisors in the
|
||||
current context, without the need to include specific bean names in the auto-proxy
|
||||
advisor's bean definition. It offers the same merit of consistent configuration and
|
||||
avoidance of duplication as `BeanNameAutoProxyCreator`.
|
||||
|
||||
Using this mechanism involves:
|
||||
|
||||
* Specifying a `DefaultAdvisorAutoProxyCreator` bean definition.
|
||||
* Specifying any number of advisors in the same or related contexts. Note that these
|
||||
must be advisors, not interceptors or other advice. This is necessary,
|
||||
because there must be a pointcut to evaluate, to check the eligibility of each advice
|
||||
to candidate bean definitions.
|
||||
|
||||
The `DefaultAdvisorAutoProxyCreator` automatically evaluates the pointcut contained
|
||||
in each advisor, to see what (if any) advice it should apply to each business object
|
||||
(such as `businessObject1` and `businessObject2` in the example).
|
||||
|
||||
This means that any number of advisors can be applied automatically to each business
|
||||
object. If no pointcut in any of the advisors matches any method in a business object,
|
||||
the object is not proxied. As bean definitions are added for new business objects,
|
||||
they are automatically proxied if necessary.
|
||||
|
||||
Auto-proxying in general has the advantage of making it impossible for callers or
|
||||
dependencies to obtain an un-advised object. Calling `getBean("businessObject1")` on this
|
||||
`ApplicationContext` returns an AOP proxy, not the target business object. (The "`inner
|
||||
bean`" idiom shown earlier also offers this benefit.)
|
||||
|
||||
The following example creates a `DefaultAdvisorAutoProxyCreator` bean and the other
|
||||
elements discussed in this section:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
|
||||
|
||||
<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
|
||||
<property name="transactionInterceptor" ref="transactionInterceptor"/>
|
||||
</bean>
|
||||
|
||||
<bean id="customAdvisor" class="com.mycompany.MyAdvisor"/>
|
||||
|
||||
<bean id="businessObject1" class="com.mycompany.BusinessObject1">
|
||||
<!-- Properties omitted -->
|
||||
</bean>
|
||||
|
||||
<bean id="businessObject2" class="com.mycompany.BusinessObject2"/>
|
||||
----
|
||||
|
||||
The `DefaultAdvisorAutoProxyCreator` is very useful if you want to apply the same advice
|
||||
consistently to many business objects. Once the infrastructure definitions are in place,
|
||||
you can add new business objects without including specific proxy configuration.
|
||||
You can also easily drop in additional aspects (for example, tracing or
|
||||
performance monitoring aspects) with minimal change to configuration.
|
||||
|
||||
The `DefaultAdvisorAutoProxyCreator` offers support for filtering (by using a naming
|
||||
convention so that only certain advisors are evaluated, which allows the use of multiple,
|
||||
differently configured, AdvisorAutoProxyCreators in the same factory) and ordering.
|
||||
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.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
[[aop-concise-proxy]]
|
||||
= Concise Proxy Definitions
|
||||
|
||||
Especially when defining transactional proxies, you may end up with many similar proxy
|
||||
definitions. The use of parent and child bean definitions, along with inner bean
|
||||
definitions, can result in much cleaner and more concise proxy definitions.
|
||||
|
||||
First, we create a parent, template, bean definition for the proxy, as follows:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<bean id="txProxyTemplate" abstract="true"
|
||||
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
|
||||
<property name="transactionManager" ref="transactionManager"/>
|
||||
<property name="transactionAttributes">
|
||||
<props>
|
||||
<prop key="*">PROPAGATION_REQUIRED</prop>
|
||||
</props>
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
|
||||
This is never instantiated itself, so it can actually be incomplete. Then, each proxy
|
||||
that needs to be created is a child bean definition, which wraps the target of the
|
||||
proxy as an inner bean definition, since the target is never used on its own anyway.
|
||||
The following example shows such a child bean:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<bean id="myService" parent="txProxyTemplate">
|
||||
<property name="target">
|
||||
<bean class="org.springframework.samples.MyServiceImpl">
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
|
||||
You can override properties from the parent template. In the following example,
|
||||
we override the transaction propagation settings:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<bean id="mySpecialService" parent="txProxyTemplate">
|
||||
<property name="target">
|
||||
<bean class="org.springframework.samples.MySpecialServiceImpl">
|
||||
</bean>
|
||||
</property>
|
||||
<property name="transactionAttributes">
|
||||
<props>
|
||||
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
|
||||
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
|
||||
<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
|
||||
<prop key="store*">PROPAGATION_REQUIRED</prop>
|
||||
</props>
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
|
||||
Note that in the parent bean example, we explicitly marked the parent bean definition as
|
||||
being abstract by setting the `abstract` attribute to `true`, as described
|
||||
xref:core/beans/child-bean-definitions.adoc[previously], so that it may not actually ever be
|
||||
instantiated. Application contexts (but not simple bean factories), by default,
|
||||
pre-instantiate all singletons. Therefore, it is important (at least for singleton beans)
|
||||
that, if you have a (parent) bean definition that 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 actually tries to
|
||||
pre-instantiate it.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
[[aop-extensibility]]
|
||||
= Defining New Advice Types
|
||||
:page-section-summary-toc: 1
|
||||
|
||||
Spring AOP is designed to be extensible. While the interception implementation strategy
|
||||
is presently used internally, it is possible to support arbitrary advice types in
|
||||
addition to the interception around advice, before, throws advice, and
|
||||
after returning advice.
|
||||
|
||||
The `org.springframework.aop.framework.adapter` package is an SPI package that lets
|
||||
support for new custom advice types be added without changing the core framework.
|
||||
The only constraint on a custom `Advice` type is that it must implement the
|
||||
`org.aopalliance.aop.Advice` marker interface.
|
||||
|
||||
See the {spring-framework-api}/aop/framework/adapter/package-summary.html[`org.springframework.aop.framework.adapter`]
|
||||
javadoc for further information.
|
||||
@@ -1,329 +0,0 @@
|
||||
[[aop-pfb]]
|
||||
= Using the `ProxyFactoryBean` to Create AOP Proxies
|
||||
|
||||
If you use the Spring IoC container (an `ApplicationContext` or `BeanFactory`) for your
|
||||
business objects (and you should be!), you want to use one of Spring's AOP
|
||||
`FactoryBean` implementations. (Remember that a factory bean introduces a layer of indirection, letting
|
||||
it create objects of a different type.)
|
||||
|
||||
NOTE: The Spring AOP support also uses factory beans under the covers.
|
||||
|
||||
The basic way to create an AOP proxy in Spring is to use the
|
||||
`org.springframework.aop.framework.ProxyFactoryBean`. This gives complete control over
|
||||
the pointcuts, any advice that applies, and their ordering. However, there are simpler
|
||||
options that are preferable if you do not need such control.
|
||||
|
||||
|
||||
|
||||
[[aop-pfb-1]]
|
||||
== Basics
|
||||
|
||||
The `ProxyFactoryBean`, like other Spring `FactoryBean` implementations, introduces a
|
||||
level of indirection. If you define a `ProxyFactoryBean` named `foo`, objects that
|
||||
reference `foo` do not see the `ProxyFactoryBean` instance itself but an object
|
||||
created by the implementation of the `getObject()` method in the `ProxyFactoryBean` . This
|
||||
method creates an AOP proxy that wraps a target object.
|
||||
|
||||
One of the most important benefits of using a `ProxyFactoryBean` or another IoC-aware
|
||||
class to create AOP proxies is that advice and pointcuts can also be
|
||||
managed by IoC. This is a powerful feature, enabling certain approaches that are hard to
|
||||
achieve with other AOP frameworks. For example, an advice may itself reference
|
||||
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
|
||||
|
||||
In common with most `FactoryBean` implementations provided with Spring, the
|
||||
`ProxyFactoryBean` class is itself a JavaBean. Its properties are used to:
|
||||
|
||||
* Specify the target you want to proxy.
|
||||
* Specify whether to use CGLIB (described later and see also xref:core/aop-api/pfb.adoc#aop-pfb-proxy-types[JDK- and CGLIB-based proxies]).
|
||||
|
||||
Some key properties are inherited from `org.springframework.aop.framework.ProxyConfig`
|
||||
(the superclass for all AOP proxy factories in Spring). These key properties include
|
||||
the following:
|
||||
|
||||
* `proxyTargetClass`: `true` if the target class is to be proxied, rather than the
|
||||
target class's interfaces. If this property value is set to `true`, then CGLIB proxies
|
||||
are created (but see also xref:core/aop-api/pfb.adoc#aop-pfb-proxy-types[JDK- and CGLIB-based proxies]).
|
||||
* `optimize`: Controls whether or not aggressive optimizations are applied to proxies
|
||||
created through CGLIB. You should not blithely use this setting unless you fully
|
||||
understand how the relevant AOP proxy handles optimization. This is currently used
|
||||
only for CGLIB proxies. It has no effect with JDK dynamic proxies.
|
||||
* `frozen`: If a proxy configuration is `frozen`, changes to the configuration are
|
||||
no longer allowed. This is useful both as a slight optimization and for those cases
|
||||
when you do not want callers to be able to manipulate the proxy (through the `Advised`
|
||||
interface) after the proxy has been created. The default value of this property is
|
||||
`false`, so changes (such as adding additional advice) are allowed.
|
||||
* `exposeProxy`: Determines whether or not the current proxy should be exposed in a
|
||||
`ThreadLocal` so that it can be accessed by the target. If a target needs to obtain
|
||||
the proxy and the `exposeProxy` property is set to `true`, the target can use the
|
||||
`AopContext.currentProxy()` method.
|
||||
|
||||
Other properties specific to `ProxyFactoryBean` include the following:
|
||||
|
||||
* `proxyInterfaces`: An array of `String` interface names. If this is not supplied, a CGLIB
|
||||
proxy for the target class is used (but see also xref:core/aop-api/pfb.adoc#aop-pfb-proxy-types[JDK- and CGLIB-based proxies]).
|
||||
* `interceptorNames`: A `String` array of `Advisor`, interceptor, or other advice names to
|
||||
apply. Ordering is significant, on a first come-first served basis. That is to say
|
||||
that the first interceptor in the list is the first to be able to intercept the
|
||||
invocation.
|
||||
+
|
||||
The names are bean names in the current factory, including bean names from ancestor
|
||||
factories. You cannot mention bean references here, since doing so results in the
|
||||
`ProxyFactoryBean` ignoring the singleton setting of the advice.
|
||||
+
|
||||
You can append an interceptor name with an asterisk (`*`). Doing so results in the
|
||||
application of all advisor beans with names that start with the part before the asterisk
|
||||
to be applied. You can find an example of using this feature in xref:core/aop-api/pfb.adoc#aop-global-advisors[Using "`Global`" Advisors].
|
||||
|
||||
* singleton: Whether or not the factory should return a single object, no matter how
|
||||
often the `getObject()` method is called. Several `FactoryBean` implementations offer
|
||||
such a method. The default value is `true`. If you want to use stateful advice - for
|
||||
example, for stateful mixins - use prototype advice along with a singleton value of
|
||||
`false`.
|
||||
|
||||
|
||||
|
||||
[[aop-pfb-proxy-types]]
|
||||
== JDK- and CGLIB-based proxies
|
||||
|
||||
This section serves as the definitive documentation on how the `ProxyFactoryBean`
|
||||
chooses to create either a JDK-based proxy or a CGLIB-based proxy for a particular target
|
||||
object (which is to be proxied).
|
||||
|
||||
NOTE: The behavior of the `ProxyFactoryBean` with regard to creating JDK- or CGLIB-based
|
||||
proxies changed between versions 1.2.x and 2.0 of Spring. The `ProxyFactoryBean` now
|
||||
exhibits similar semantics with regard to auto-detecting interfaces as those of the
|
||||
`TransactionProxyFactoryBean` class.
|
||||
|
||||
If the class of a target object that is to be proxied (hereafter simply referred to as
|
||||
the target class) does not implement any interfaces, a CGLIB-based proxy is
|
||||
created. This is the easiest scenario, because JDK proxies are interface-based, and no
|
||||
interfaces means JDK proxying is not even possible. You can plug in the target bean
|
||||
and specify the list of interceptors by setting the `interceptorNames` property. Note that a
|
||||
CGLIB-based proxy is created even if the `proxyTargetClass` property of the
|
||||
`ProxyFactoryBean` has been set to `false`. (Doing so makes no sense and is best
|
||||
removed from the bean definition, because it is, at best, redundant, and, at worst
|
||||
confusing.)
|
||||
|
||||
If the target class implements one (or more) interfaces, the type of proxy that is
|
||||
created depends on the configuration of the `ProxyFactoryBean`.
|
||||
|
||||
If the `proxyTargetClass` property of the `ProxyFactoryBean` has been set to `true`,
|
||||
a CGLIB-based proxy is created. This makes sense and is in keeping with the
|
||||
principle of least surprise. Even if the `proxyInterfaces` property of the
|
||||
`ProxyFactoryBean` has been set to one or more fully qualified interface names, the fact
|
||||
that the `proxyTargetClass` property is set to `true` causes CGLIB-based
|
||||
proxying to be in effect.
|
||||
|
||||
If the `proxyInterfaces` property of the `ProxyFactoryBean` has been set to one or more
|
||||
fully qualified interface names, a JDK-based proxy is created. The created
|
||||
proxy implements all of the interfaces that were specified in the `proxyInterfaces`
|
||||
property. If the target class happens to implement a whole lot more interfaces than
|
||||
those specified in the `proxyInterfaces` property, that is all well and good, but those
|
||||
additional interfaces are not implemented by the returned proxy.
|
||||
|
||||
If the `proxyInterfaces` property of the `ProxyFactoryBean` has not been set, but
|
||||
the target class does implement one (or more) interfaces, the
|
||||
`ProxyFactoryBean` auto-detects the fact that the target class does actually
|
||||
implement at least one interface, and a JDK-based proxy is created. The interfaces
|
||||
that are actually proxied are all of the interfaces that the target class
|
||||
implements. In effect, this is the same as supplying a list of each and every
|
||||
interface that the target class implements to the `proxyInterfaces` property. However,
|
||||
it is significantly less work and less prone to typographical errors.
|
||||
|
||||
|
||||
|
||||
[[aop-api-proxying-intf]]
|
||||
== Proxying Interfaces
|
||||
|
||||
Consider a simple example of `ProxyFactoryBean` in action. This example involves:
|
||||
|
||||
* A target bean that is proxied. This is the `personTarget` bean definition in
|
||||
the example.
|
||||
* An `Advisor` and an `Interceptor` used to provide advice.
|
||||
* An AOP proxy bean definition to specify the target object (the `personTarget` bean),
|
||||
the interfaces to proxy, and the advice to apply.
|
||||
|
||||
The following listing shows the example:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<bean id="personTarget" class="com.mycompany.PersonImpl">
|
||||
<property name="name" value="Tony"/>
|
||||
<property name="age" value="51"/>
|
||||
</bean>
|
||||
|
||||
<bean id="myAdvisor" class="com.mycompany.MyAdvisor">
|
||||
<property name="someProperty" value="Custom string property value"/>
|
||||
</bean>
|
||||
|
||||
<bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor">
|
||||
</bean>
|
||||
|
||||
<bean id="person"
|
||||
class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces" value="com.mycompany.Person"/>
|
||||
|
||||
<property name="target" ref="personTarget"/>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<value>myAdvisor</value>
|
||||
<value>debugInterceptor</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
|
||||
Note that the `interceptorNames` property takes a list of `String`, which holds the bean names of the
|
||||
interceptors or advisors in the current factory. You can use advisors, interceptors, before, after
|
||||
returning, and throws advice objects. The ordering of advisors is significant.
|
||||
|
||||
NOTE: You might be wondering why the list does not hold bean references. The reason for this is
|
||||
that, if the singleton property of the `ProxyFactoryBean` is set to `false`, it must be able to
|
||||
return independent proxy instances. If any of the advisors is itself a prototype, an
|
||||
independent instance would need to be returned, so it is necessary to be able to obtain
|
||||
an instance of the prototype from the factory. Holding a reference is not sufficient.
|
||||
|
||||
The `person` bean definition shown earlier can be used in place of a `Person` implementation, as
|
||||
follows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
Person person = (Person) factory.getBean("person");
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
val person = factory.getBean("person") as Person;
|
||||
----
|
||||
======
|
||||
|
||||
Other beans in the same IoC context can express a strongly typed dependency on it, as
|
||||
with an ordinary Java object. The following example shows how to do so:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<bean id="personUser" class="com.mycompany.PersonUser">
|
||||
<property name="person"><ref bean="person"/></property>
|
||||
</bean>
|
||||
----
|
||||
|
||||
The `PersonUser` class in this example exposes a property of type `Person`. As far as
|
||||
it is concerned, the AOP proxy can be used transparently in place of a "`real`" person
|
||||
implementation. However, its class would be a dynamic proxy class. It would be possible
|
||||
to cast it to the `Advised` interface (discussed later).
|
||||
|
||||
You can conceal the distinction between target and proxy by using an anonymous
|
||||
inner bean. Only the `ProxyFactoryBean` definition is different. The
|
||||
advice is included only for completeness. The following example shows how to use an
|
||||
anonymous inner bean:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<bean id="myAdvisor" class="com.mycompany.MyAdvisor">
|
||||
<property name="someProperty" value="Custom string property value"/>
|
||||
</bean>
|
||||
|
||||
<bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor"/>
|
||||
|
||||
<bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces" value="com.mycompany.Person"/>
|
||||
<!-- Use inner bean, not local reference to target -->
|
||||
<property name="target">
|
||||
<bean class="com.mycompany.PersonImpl">
|
||||
<property name="name" value="Tony"/>
|
||||
<property name="age" value="51"/>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<value>myAdvisor</value>
|
||||
<value>debugInterceptor</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
|
||||
Using an anonymous inner bean has the advantage that there is only one object of type `Person`. This is useful if we want
|
||||
to prevent users of the application context from obtaining a reference to the un-advised
|
||||
object or need to avoid any ambiguity with Spring IoC autowiring. There is also,
|
||||
arguably, an advantage in that the `ProxyFactoryBean` definition is self-contained.
|
||||
However, there are times when being able to obtain the un-advised target from the
|
||||
factory might actually be an advantage (for example, in certain test scenarios).
|
||||
|
||||
|
||||
|
||||
[[aop-api-proxying-class]]
|
||||
== Proxying Classes
|
||||
|
||||
What if you need to proxy a class, rather than one or more interfaces?
|
||||
|
||||
Imagine that in our earlier example, there was no `Person` interface. We needed to advise
|
||||
a class called `Person` that did not implement any business interface. In this case, you
|
||||
can configure Spring to use CGLIB proxying rather than dynamic proxies. To do so, set the
|
||||
`proxyTargetClass` property on the `ProxyFactoryBean` shown earlier to `true`. While it is best to
|
||||
program to interfaces rather than classes, the ability to advise classes that do not
|
||||
implement interfaces can be useful when working with legacy code. (In general, Spring
|
||||
is not prescriptive. While it makes it easy to apply good practices, it avoids forcing a
|
||||
particular approach.)
|
||||
|
||||
If you want to, you can force the use of CGLIB in any case, even if you do have
|
||||
interfaces.
|
||||
|
||||
CGLIB proxying works by generating a subclass of the target class at runtime. Spring
|
||||
configures this generated subclass to delegate method calls to the original target. The
|
||||
subclass is used to implement the Decorator pattern, weaving in the advice.
|
||||
|
||||
CGLIB proxying should generally be transparent to users. However, there are some issues
|
||||
to consider:
|
||||
|
||||
* `final` classes cannot be proxied, because they cannot be extended.
|
||||
* `final` methods cannot be advised, because they cannot be overridden.
|
||||
* `private` methods cannot be advised, because they cannot be overridden.
|
||||
|
||||
NOTE: There is no need to add CGLIB to your classpath. CGLIB is repackaged and included
|
||||
in the `spring-core` JAR. In other words, CGLIB-based AOP works "out of the box", as do
|
||||
JDK dynamic proxies.
|
||||
|
||||
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
|
||||
|
||||
By appending an asterisk to an interceptor name, all advisors with bean names that match
|
||||
the part before the asterisk are added to the advisor chain. This can come in handy
|
||||
if you need to add a standard set of "`global`" advisors. The following example defines
|
||||
two global advisors:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="target" ref="service"/>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<value>global*</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="global_debug" class="org.springframework.aop.interceptor.DebugInterceptor"/>
|
||||
<bean id="global_performance" class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor"/>
|
||||
----
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,256 +0,0 @@
|
||||
[[aop-api-pointcuts]]
|
||||
= Pointcut API in Spring
|
||||
|
||||
This section describes how Spring handles the crucial pointcut concept.
|
||||
|
||||
|
||||
|
||||
[[aop-api-concepts]]
|
||||
== Concepts
|
||||
|
||||
Spring's pointcut model enables pointcut reuse independent of advice types. You can
|
||||
target different advice with the same pointcut.
|
||||
|
||||
The `org.springframework.aop.Pointcut` interface is the central interface, used to
|
||||
target advice to particular classes and methods. The complete interface follows:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
public interface Pointcut {
|
||||
|
||||
ClassFilter getClassFilter();
|
||||
|
||||
MethodMatcher getMethodMatcher();
|
||||
}
|
||||
----
|
||||
|
||||
Splitting the `Pointcut` interface into two parts allows reuse of class and method
|
||||
matching parts and fine-grained composition operations (such as performing a "`union`"
|
||||
with another method matcher).
|
||||
|
||||
The `ClassFilter` interface is used to restrict the pointcut to a given set of target
|
||||
classes. If the `matches()` method always returns true, all target classes are
|
||||
matched. The following listing shows the `ClassFilter` interface definition:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
public interface ClassFilter {
|
||||
|
||||
boolean matches(Class clazz);
|
||||
}
|
||||
----
|
||||
|
||||
The `MethodMatcher` interface is normally more important. The complete interface follows:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
public interface MethodMatcher {
|
||||
|
||||
boolean matches(Method m, Class<?> targetClass);
|
||||
|
||||
boolean isRuntime();
|
||||
|
||||
boolean matches(Method m, Class<?> targetClass, Object... args);
|
||||
}
|
||||
----
|
||||
|
||||
The `matches(Method, Class)` method is used to test whether this pointcut ever
|
||||
matches a given method on a target class. This evaluation can be performed when an AOP
|
||||
proxy is created to avoid the need for a test on every method invocation. If the
|
||||
two-argument `matches` method returns `true` for a given method, and the `isRuntime()`
|
||||
method for the MethodMatcher returns `true`, the three-argument matches method is
|
||||
invoked on every method invocation. This lets a pointcut look at the arguments passed
|
||||
to the method invocation immediately before the target advice starts.
|
||||
|
||||
Most `MethodMatcher` implementations are static, meaning that their `isRuntime()` method
|
||||
returns `false`. In this case, the three-argument `matches` method is never invoked.
|
||||
|
||||
TIP: If possible, try to make pointcuts static, allowing the AOP framework to cache the
|
||||
results of pointcut evaluation when an AOP proxy is created.
|
||||
|
||||
|
||||
|
||||
[[aop-api-pointcut-ops]]
|
||||
== Operations on Pointcuts
|
||||
|
||||
Spring supports operations (notably, union and intersection) on pointcuts.
|
||||
|
||||
Union means the methods that either pointcut matches.
|
||||
Intersection means the methods that both pointcuts match.
|
||||
Union is usually more useful.
|
||||
You can compose pointcuts by using the static methods in the
|
||||
`org.springframework.aop.support.Pointcuts` class or by using the
|
||||
`ComposablePointcut` class in the same package. However, using AspectJ pointcut
|
||||
expressions is usually a simpler approach.
|
||||
|
||||
|
||||
|
||||
[[aop-api-pointcuts-aspectj]]
|
||||
== AspectJ Expression Pointcuts
|
||||
|
||||
Since 2.0, the most important type of pointcut used by Spring is
|
||||
`org.springframework.aop.aspectj.AspectJExpressionPointcut`. This is a pointcut that
|
||||
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
|
||||
|
||||
Static pointcuts are based on the method and the target class and cannot take into account
|
||||
the method's arguments. Static pointcuts suffice -- and are best -- for most usages.
|
||||
Spring can evaluate a static pointcut only once, when a method is first invoked.
|
||||
After that, there is no need to evaluate the pointcut again with each method invocation.
|
||||
|
||||
The rest of this section describes some of the static pointcut implementations that are
|
||||
included with Spring.
|
||||
|
||||
[[aop-api-pointcuts-regex]]
|
||||
==== Regular Expression Pointcuts
|
||||
|
||||
One obvious way to specify static pointcuts is regular expressions. Several AOP
|
||||
frameworks besides Spring make this possible.
|
||||
`org.springframework.aop.support.JdkRegexpMethodPointcut` is a generic regular
|
||||
expression pointcut that uses the regular expression support in the JDK.
|
||||
|
||||
With the `JdkRegexpMethodPointcut` class, you can provide a list of pattern strings.
|
||||
If any of these is a match, the pointcut evaluates to `true`. (As a consequence,
|
||||
the resulting pointcut is effectively the union of the specified patterns.)
|
||||
|
||||
The following example shows how to use `JdkRegexpMethodPointcut`:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
----
|
||||
<bean id="settersAndAbsquatulatePointcut"
|
||||
class="org.springframework.aop.support.JdkRegexpMethodPointcut">
|
||||
<property name="patterns">
|
||||
<list>
|
||||
<value>.*set.*</value>
|
||||
<value>.*absquatulate</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
|
||||
Spring provides a convenience class named `RegexpMethodPointcutAdvisor`, which lets us
|
||||
also reference an `Advice` (remember that an `Advice` can be an interceptor, before advice,
|
||||
throws advice, and others). Behind the scenes, Spring uses a `JdkRegexpMethodPointcut`.
|
||||
Using `RegexpMethodPointcutAdvisor` simplifies wiring, as the one bean encapsulates both
|
||||
pointcut and advice, as the following example shows:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
----
|
||||
<bean id="settersAndAbsquatulateAdvisor"
|
||||
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
|
||||
<property name="advice">
|
||||
<ref bean="beanNameOfAopAllianceInterceptor"/>
|
||||
</property>
|
||||
<property name="patterns">
|
||||
<list>
|
||||
<value>.*set.*</value>
|
||||
<value>.*absquatulate</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
|
||||
You can use `RegexpMethodPointcutAdvisor` with any `Advice` type.
|
||||
|
||||
[[aop-api-pointcuts-attribute-driven]]
|
||||
==== Attribute-driven Pointcuts
|
||||
|
||||
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
|
||||
|
||||
Dynamic pointcuts are costlier to evaluate than static pointcuts. They take into account
|
||||
method arguments as well as static information. This means that they must be
|
||||
evaluated with every method invocation and that the result cannot be cached, as arguments will
|
||||
vary.
|
||||
|
||||
The main example is the `control flow` pointcut.
|
||||
|
||||
[[aop-api-pointcuts-cflow]]
|
||||
==== Control Flow Pointcuts
|
||||
|
||||
Spring control flow pointcuts are conceptually similar to AspectJ `cflow` pointcuts,
|
||||
although less powerful. (There is currently no way to specify that a pointcut runs
|
||||
below a join point matched by another pointcut.) A control flow pointcut matches the
|
||||
current call stack. For example, it might fire if the join point was invoked by a method
|
||||
in the `com.mycompany.web` package or by the `SomeCaller` class. Control flow pointcuts
|
||||
are specified by using the `org.springframework.aop.support.ControlFlowPointcut` class.
|
||||
|
||||
NOTE: Control flow pointcuts are significantly more expensive to evaluate at runtime than even
|
||||
other dynamic pointcuts. In Java 1.4, the cost is about five times that of other dynamic
|
||||
pointcuts.
|
||||
|
||||
|
||||
|
||||
[[aop-api-pointcuts-superclasses]]
|
||||
== Pointcut Superclasses
|
||||
|
||||
Spring provides useful pointcut superclasses to help you to implement your own pointcuts.
|
||||
|
||||
Because static pointcuts are most useful, you should probably subclass
|
||||
`StaticMethodMatcherPointcut`. This requires implementing only one
|
||||
abstract method (although you can override other methods to customize behavior). The
|
||||
following example shows how to subclass `StaticMethodMatcherPointcut`:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
class TestStaticPointcut extends StaticMethodMatcherPointcut {
|
||||
|
||||
public boolean matches(Method m, Class targetClass) {
|
||||
// return true if custom criteria match
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
class TestStaticPointcut : StaticMethodMatcherPointcut() {
|
||||
|
||||
override fun matches(method: Method, targetClass: Class<*>): Boolean {
|
||||
// return true if custom criteria match
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
There are also superclasses for dynamic pointcuts.
|
||||
You can use custom pointcuts with any advice type.
|
||||
|
||||
|
||||
|
||||
[[aop-api-pointcuts-custom]]
|
||||
== Custom Pointcuts
|
||||
|
||||
Because pointcuts in Spring AOP are Java classes rather than language features (as in
|
||||
AspectJ), you can declare custom pointcuts, whether static or dynamic. Custom
|
||||
pointcuts in Spring can be arbitrarily complex. However, we recommend using the AspectJ pointcut
|
||||
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.`"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
[[aop-prog]]
|
||||
= Creating AOP Proxies Programmatically with the `ProxyFactory`
|
||||
|
||||
It is easy to create AOP proxies programmatically with Spring. This lets you use
|
||||
Spring AOP without dependency on Spring IoC.
|
||||
|
||||
The interfaces implemented by the target object are
|
||||
automatically proxied. The following listing shows creation of a proxy for a target object, with one
|
||||
interceptor and one advisor:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
ProxyFactory factory = new ProxyFactory(myBusinessInterfaceImpl);
|
||||
factory.addAdvice(myMethodInterceptor);
|
||||
factory.addAdvisor(myAdvisor);
|
||||
MyBusinessInterface tb = (MyBusinessInterface) factory.getProxy();
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
val factory = ProxyFactory(myBusinessInterfaceImpl)
|
||||
factory.addAdvice(myMethodInterceptor)
|
||||
factory.addAdvisor(myAdvisor)
|
||||
val tb = factory.proxy as MyBusinessInterface
|
||||
----
|
||||
======
|
||||
|
||||
The first step is to construct an object of type
|
||||
`org.springframework.aop.framework.ProxyFactory`. You can create this with a target
|
||||
object, as in the preceding example, or specify the interfaces to be proxied in an alternate
|
||||
constructor.
|
||||
|
||||
You can add advice (with interceptors as a specialized kind of advice), advisors, or both
|
||||
and manipulate them for the life of the `ProxyFactory`. If you add an
|
||||
`IntroductionInterceptionAroundAdvisor`, you can cause the proxy to implement additional
|
||||
interfaces.
|
||||
|
||||
There are also convenience methods on `ProxyFactory` (inherited from `AdvisedSupport`)
|
||||
that let you add other advice types, such as before and throws advice.
|
||||
`AdvisedSupport` is the superclass of both `ProxyFactory` and `ProxyFactoryBean`.
|
||||
|
||||
TIP: Integrating AOP proxy creation with the IoC framework is best practice in most
|
||||
applications. We recommend that you externalize configuration from Java code with AOP,
|
||||
as you should in general.
|
||||
|
||||
|
||||
|
||||
|
||||