mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
76 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ed3d91b929 | |||
| 731ceb8aca | |||
| 6f213fb6a0 | |||
| 131ae59724 | |||
| dd3b3a7c69 | |||
| cbe79a9241 | |||
| ef4a5fb54c | |||
| 8ffaec5d72 | |||
| 578cdb5f7e | |||
| 305a512a55 | |||
| cf036eeaa3 | |||
| fa8a30f753 | |||
| f63ae425bf | |||
| fa20dd820d | |||
| 01cebc85b4 | |||
| 6cf89a1e58 | |||
| e5e8574466 | |||
| a2cabcbb90 | |||
| 9b3625b39e | |||
| 7232e83807 | |||
| 91afab7723 | |||
| e19a8e58fc | |||
| 5f2707a7e3 | |||
| 92ecef74ec | |||
| 11c9373439 | |||
| 6f8db2cfd3 | |||
| bff8cff03b | |||
| c55979b8a9 | |||
| 097c773b91 | |||
| 431cce0b1e | |||
| 0ed87a350c | |||
| 1a43d698d1 | |||
| 94c5481e9e | |||
| 41675587ea | |||
| b14a20161f | |||
| 10e5029e88 | |||
| 4b2552f498 | |||
| 554f15262d | |||
| 9fc8046728 | |||
| 9b60075085 | |||
| aa2ea2055d | |||
| f9c1e6053c | |||
| 2362a142c1 | |||
| b656bb4855 | |||
| c6eb4c0eae | |||
| 57c6cc83da | |||
| 1943aad216 | |||
| 57b9a57452 | |||
| 35f3e5d664 | |||
| d88eccc837 | |||
| 3f8db79e1c | |||
| e30e453bb4 | |||
| edc01f4957 | |||
| a53a17c01a | |||
| 6c95ee2334 | |||
| 6236ed56e4 | |||
| 6455960cf1 | |||
| 3771743082 | |||
| 1e3b4cdc34 | |||
| 889c9c7de4 | |||
| da97ab1dea | |||
| 9ac9cd15fb | |||
| 621f0a6568 | |||
| 6fb9e4a9ea | |||
| 3881954125 | |||
| 42a4409c73 | |||
| 6c5ef6db1e | |||
| f4ccf68458 | |||
| 4aa824d456 | |||
| 6a68b4d299 | |||
| 28cc8b7a08 | |||
| 317eee83ac | |||
| 81e9a8a26d | |||
| a2337b73e0 | |||
| 8422f0f5b7 | |||
| dc3c016712 |
@@ -0,0 +1,57 @@
|
||||
name: Build and Deploy Documentation
|
||||
run-name: ${{ format('{0} ({1})', github.workflow, github.event.inputs.build-refname || 'all') }}
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build-refname:
|
||||
description: Enter git refname to build (e.g., 5.7.x).
|
||||
required: false
|
||||
push:
|
||||
branches: docs-build
|
||||
env:
|
||||
GRADLE_ENTERPRISE_SECRET_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_SECRET_ACCESS_KEY }}
|
||||
permissions: read-all
|
||||
jobs:
|
||||
build-and-deploy-docs:
|
||||
name: Build and Deploy Documentation
|
||||
if: github.repository_owner == 'spring-projects'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check Out
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 5
|
||||
- name: Set Up Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'liberica'
|
||||
java-version: |
|
||||
25
|
||||
17
|
||||
- name: Set Up Gradle
|
||||
uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
with:
|
||||
cache-read-only: false
|
||||
- name: Set up refname build
|
||||
if: github.event.inputs.build-refname
|
||||
run: |
|
||||
git fetch --depth 1 https://github.com/$GITHUB_REPOSITORY ${{ github.event.inputs.build-refname }}
|
||||
echo BUILD_REFNAME=${{ github.event.inputs.build-refname }} >> $GITHUB_ENV
|
||||
echo BUILD_VERSION=$(git cat-file --textconv FETCH_HEAD:gradle.properties | sed -n '/^version=/ { s/^version=//;p }') >> $GITHUB_ENV
|
||||
- name: Run Antora
|
||||
run: ./gradlew antora
|
||||
- name: Copy the cache to be included in the site
|
||||
run: cp -rf build/antora/inject-collector-cache-config-extension/.cache build/site/
|
||||
- name: Publish Docs
|
||||
uses: spring-io/spring-doc-actions/rsync-antora-reference@v0.0.22
|
||||
with:
|
||||
docs-username: ${{ secrets.DOCS_USERNAME }}
|
||||
docs-host: ${{ secrets.DOCS_HOST }}
|
||||
docs-ssh-key: ${{ secrets.DOCS_SSH_KEY }}
|
||||
docs-ssh-host-key: ${{ secrets.DOCS_SSH_HOST_KEY }}
|
||||
- name: Bust Cloudflare Cache
|
||||
uses: spring-io/spring-doc-actions/bust-cloudflare-antora-cache@v0.0.22
|
||||
with:
|
||||
context-root: spring-framework
|
||||
cloudflare-zone-id: ${{ secrets.CLOUDFLARE_ZONE_ID }}
|
||||
cloudflare-cache-token: ${{ secrets.CLOUDFLARE_CACHE_TOKEN }}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
# 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-bom/build
|
||||
/framework-docs/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
|
||||
|
||||
node_modules
|
||||
@@ -0,0 +1,3 @@
|
||||
# Enable auto-env through the sdkman_auto_env config
|
||||
# Add key=value pairs of SDKs to use below
|
||||
java=17.0.12-librca
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
= Spring Framework Docs Build
|
||||
|
||||
You're currently viewing the Antora playbook branch.
|
||||
The playbook branch hosts the docs build that is used to build and publish the production docs site.
|
||||
|
||||
The Spring Framework reference docs are built using https://antora.org[Antora].
|
||||
This README covers how to build the docs in a software branch as well as how to build the production docs site locally.
|
||||
|
||||
== Overview
|
||||
|
||||
To prepare your system for building the documentation, <<prerequisites,install the prerequisites>> and then <<build-main,create your workspace and build the main branch documentation>>.
|
||||
Once you've completed those steps, follow the instructions in <<build-branch,Build the 6.0.x branch documentation>> to learn how to build the documentation for a version branch you haven't previously checked out.
|
||||
|
||||
To build the production site documentation on your computer, follow the instructions in <<prerequisites,Prerequisites>>, <<build-main,Build the main branch documentation>>, and then <<build-production,Build the production documentation site>>.
|
||||
|
||||
.Branch checkout instead of worktrees
|
||||
[NOTE]
|
||||
====
|
||||
If you prefer to set up your workspace without worktrees, complete the steps in <<prerequisites,Prerequisites>> and clone the project repository onto your computer.
|
||||
Then follow the instructions in each section starting from the `sdk env || sdk env install` step once you've checked out the desired branch.
|
||||
====
|
||||
|
||||
[#prerequisites]
|
||||
== Prerequisites (everyone)
|
||||
|
||||
These instructions assume you already have basic tools on your system, including bash, zip, unzip, git, and curl.
|
||||
In addition to these basic tools, you need https://sdkman.io/install[SDKMAN!] installed so that the correct JDK is set for each branch.
|
||||
|
||||
. Open your terminal and enter the following command:
|
||||
+
|
||||
--
|
||||
$ curl -s "https://get.sdkman.io" | bash
|
||||
|
||||
This command downloads and installs SDKMAN!
|
||||
Once installation is complete, you should see a command displayed in your terminal that will initiate SDKMAN.
|
||||
--
|
||||
|
||||
. Copy the command displayed in your terminal and run it.
|
||||
`$HOME` is the path unique to your computer (e.g., _home/my-jam/.sdkman/bin/sdkman-init.sh_).
|
||||
|
||||
$ source "$HOME/.sdkman/bin/sdkman-init.sh"
|
||||
|
||||
You'll use SDKMAN in the next sections to install and switch to the JDK required for each branch.
|
||||
Now you're ready to <<build-main,create your workspace>>.
|
||||
|
||||
[#build-main]
|
||||
== Build the main branch documentation (writers)
|
||||
|
||||
Your workspace will be the folder that contains the git worktrees of the project.
|
||||
|
||||
. In your terminal, create a directory for the project and then change into that directory.
|
||||
|
||||
$ mkdir spring-framework
|
||||
$ cd spring-framework
|
||||
|
||||
. Clone the project repository and create the primary worktree for the main branch.
|
||||
Then change into the new _main_ folder.
|
||||
|
||||
$ git clone https://github.com/spring-projects/spring-framework main
|
||||
$ cd main
|
||||
|
||||
. Switch to the required JDK using SDKMAN by running the following command:
|
||||
+
|
||||
--
|
||||
$ sdk env || sdk env install
|
||||
|
||||
SDKMAN will switch to the required JDK or install it if it isn't present.
|
||||
--
|
||||
|
||||
. Generate the documentation with Antora using the following command:
|
||||
+
|
||||
--
|
||||
$ ./gradlew -PbuildSrc.skipTests=true :framework-docs:antora
|
||||
|
||||
This command will build the documentation, including any generated attributes, for the main branch.
|
||||
--
|
||||
|
||||
. Navigate to _$HOME/spring-framework/main/framework-docs/build/site/index.html_ to view the generated documentation.
|
||||
|
||||
[#build-branch]
|
||||
== Build the 6.0.x branch documentation (writers)
|
||||
|
||||
NOTE: The instructions in this section assume you've completed the steps in the <<build-main,previous section>>.
|
||||
|
||||
After creating the worktree for the main branch, you can set up a worktree for any other branches you'll work on in the future.
|
||||
In this section, you'll create a worktree for the 6.0.x branch in your project workspace.
|
||||
|
||||
. To add a worktree, you have to be in a worktree.
|
||||
In your terminal, change to the _main_ folder if you aren't already in it, e.g., _$HOME/spring-framework/main_.
|
||||
Set up a worktree for the 6.0.x branch and then change into the new directory by running the following commands:
|
||||
|
||||
$ git worktree add ../6.0.x 6.0.x --track
|
||||
$ cd ../6.0.x
|
||||
|
||||
. Switch to the required JDK or install it.
|
||||
|
||||
$ sdk env || sdk env install
|
||||
|
||||
. Generate the documentation with the following command:
|
||||
+
|
||||
--
|
||||
$ ./gradlew -PbuildSrc.skipTests=true :framework-docs:antora
|
||||
|
||||
This command will build the documentation, including any generated attributes, for the 6.0.x branch.
|
||||
--
|
||||
|
||||
. Navigate to _$HOME/spring-framework/6.0.x/docs/build/site/index.html_ to view the generated documentation.
|
||||
|
||||
[#build-production]
|
||||
== Build the production documentation site (docs manager)
|
||||
|
||||
NOTE: The instructions in this section assume you've <<build-main,prepared your workspace and created the worktree for the main branch>>.
|
||||
|
||||
To build the project's production site, you'll set up a worktree for the docs-build branch of the repository.
|
||||
|
||||
. To add a worktree, you have to be in a worktree.
|
||||
In your terminal, change to the _main_ folder if you aren't already in it, e.g., _$HOME/spring-framework/main_.
|
||||
Run the following command to set up the worktree for the _docs-build_ branch.
|
||||
Then change into the new _docs-build_ directory.
|
||||
|
||||
$ git worktree add ../docs-build docs-build --track
|
||||
$ cd ../docs-build
|
||||
|
||||
. Switch to the required JDK or install it.
|
||||
|
||||
$ sdk env || sdk env install
|
||||
|
||||
. Generate the documentation for the project's production site using the following command:
|
||||
+
|
||||
--
|
||||
$ ./gradlew antora
|
||||
|
||||
This command will build all of the documentation included in the project's production site from the repository on GitHub.
|
||||
|
||||
To build the documentation from the current clone, using any worktrees that are available, use the following command instead:
|
||||
|
||||
$ ./gradlew antora --playbook local-antora-playbook.yml
|
||||
--
|
||||
|
||||
. Navigate to _$HOME/spring-framework/docs-site/build/site/index.html_ to view the generated documentation.
|
||||
@@ -0,0 +1,41 @@
|
||||
antora:
|
||||
extensions:
|
||||
- require: '@springio/antora-extensions'
|
||||
root_component_name: 'framework'
|
||||
site:
|
||||
title: Spring Framework
|
||||
url: https://docs.spring.io/spring-framework/reference
|
||||
robots: allow
|
||||
git:
|
||||
ensure_git_suffix: false
|
||||
content:
|
||||
sources:
|
||||
- url: https://github.com/spring-projects/spring-framework
|
||||
# Refname matching:
|
||||
# https://docs.antora.org/antora/latest/playbook/content-refname-matching/
|
||||
# branches: We include snapshots for main, 6.2.x, and 7.0.x to 9.*.x.
|
||||
branches: ['main', '6.2.x', '{7..9}.+({0..9}).x']
|
||||
# tags: include all releases from 6.2.0 to 9.*.*.
|
||||
tags: ['v6.2.+({0..9})', 'v{7..9}.+({0..9}).+({0..9})?(-{RC,M}*)']
|
||||
start_path: framework-docs
|
||||
asciidoc:
|
||||
extensions:
|
||||
- '@asciidoctor/tabs'
|
||||
- '@springio/asciidoctor-extensions'
|
||||
- '@springio/asciidoctor-extensions/include-code-extension'
|
||||
attributes:
|
||||
page-stackoverflow-url: https://stackoverflow.com/questions/tagged/spring
|
||||
page-pagination: ''
|
||||
hide-uri-scheme: '@'
|
||||
tabs-sync-option: '@'
|
||||
include-java: 'example$docs-src/main/java/org/springframework/docs'
|
||||
urls:
|
||||
latest_version_segment_strategy: redirect:to
|
||||
latest_version_segment: ''
|
||||
redirect_facility: httpd
|
||||
runtime:
|
||||
log:
|
||||
failure_level: warn
|
||||
ui:
|
||||
bundle:
|
||||
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.26/ui-bundle.zip
|
||||
@@ -1,12 +0,0 @@
|
||||
<?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>
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
<?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.classloading"/>
|
||||
<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.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"/>
|
||||
|
||||
</project>
|
||||
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="package-bundle">
|
||||
|
||||
<target name="package" depends="ivy.init">
|
||||
<dist-jar/>
|
||||
<src-jar/>
|
||||
</target>
|
||||
|
||||
</project>
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="package-library">
|
||||
|
||||
<target name="package" depends="ivy.init">
|
||||
<dist-jar/>
|
||||
</target>
|
||||
|
||||
</project>
|
||||
@@ -1,73 +0,0 @@
|
||||
<?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>
|
||||
|
||||
<!--ant dir="../spring-framework-reference" target="doc" inheritAll="false">
|
||||
<property name="package.output.dir" value="${package.output.dir}"/>
|
||||
<propertyset>
|
||||
<propertyref builtin="commandline"/>
|
||||
</propertyset>
|
||||
<property name="timestamp" value="${timestamp}"/>
|
||||
</ant>
|
||||
|
||||
<subant target="package" verbose="true" buildpath="../spring-framework-reference">
|
||||
<property name="package.output.dir" value="${package.output.dir}"/>
|
||||
<propertyset>
|
||||
<propertyref builtin="commandline"/>
|
||||
</propertyset>
|
||||
<property name="timestamp" value="${timestamp}"/>
|
||||
</subant-->
|
||||
|
||||
<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="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>
|
||||
@@ -1,48 +0,0 @@
|
||||
<?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>
|
||||
@@ -1,44 +0,0 @@
|
||||
<?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>
|
||||
@@ -1,27 +0,0 @@
|
||||
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
|
||||
@@ -1,102 +0,0 @@
|
||||
SPRING FRAMEWORK CHANGELOG
|
||||
==========================
|
||||
http://www.springsource.org
|
||||
|
||||
|
||||
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
|
||||
@@ -1,201 +0,0 @@
|
||||
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.
|
||||
@@ -1,22 +0,0 @@
|
||||
======================================================================
|
||||
== NOTICE file corresponding to section 4 d of the Apache License, ==
|
||||
== Version 2.0, for the Spring Web Flow 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 rod.johnson@interface21.com or juergen.hoeller@interface21.com.
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
SPRING FRAMEWORK 3.0 M2 (February 2009)
|
||||
---------------------------------------
|
||||
http://www.springframework.org
|
||||
|
||||
1. INTRODUCTION
|
||||
---------------
|
||||
|
||||
This is the second milestone of Spring 3.0 which is scheduled for final release in Q2 2009.
|
||||
This release features a codebase that has been fully updated for Java 5+, introduces
|
||||
Portlet 2.0 and early JPA 2.0 support, and provides even more comprehensive REST support.
|
||||
|
||||
2. RELEASE NOTES
|
||||
----------------
|
||||
|
||||
This release comes without reference documentation. For the time being, please consult
|
||||
the provided javadoc for details on the new features.
|
||||
|
||||
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. Furthermore, the jar file
|
||||
names follow bundle repository conventions now.
|
||||
|
||||
4. GETTING STARTED
|
||||
------------------
|
||||
|
||||
Check out the provided PetClinic sample application. It has been fully updated for
|
||||
Spring 3.0 already.
|
||||
@@ -0,0 +1,12 @@
|
||||
plugins {
|
||||
id 'base'
|
||||
id 'org.antora' version '1.0.0'
|
||||
}
|
||||
|
||||
antora {
|
||||
options = [clean: true, fetch: true, stacktrace: true]
|
||||
}
|
||||
|
||||
node {
|
||||
version = '24.15.0'
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
version=3.0.0
|
||||
build.stamp=M2
|
||||
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=-XX:MaxPermSize=128M
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
# 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
|
||||
@@ -0,0 +1,2 @@
|
||||
group=org.springframework
|
||||
description=Spring Framework Docs Site
|
||||
Vendored
BIN
Binary file not shown.
+7
@@ -0,0 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -0,0 +1,251 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original 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.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH="\\\"\\\""
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
Vendored
+94
@@ -0,0 +1,94 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src/main/java"/>
|
||||
<classpathentry kind="src" path="src/main/resources"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-1.0.0.jar" sourcepath="/IVY_CACHE/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-sources-1.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-sources-1.1.1.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.easymock/com.springsource.org.easymock/2.3.0/com.springsource.org.easymock-2.3.0.jar" sourcepath="/IVY_CACHE/org.easymock/com.springsource.org.easymock/2.3.0/com.springsource.org.easymock-sources-2.3.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/com.jamonapi/com.springsource.com.jamonapi/2.4.0/com.springsource.com.jamonapi-2.4.0.jar" sourcepath="/IVY_CACHE/com.jamonapi/com.springsource.com.jamonapi/2.4.0/com.springsource.com.jamonapi-sources-2.4.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.1.3/com.springsource.net.sf.cglib-2.1.3.jar" sourcepath="/IVY_CACHE/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.1.3/com.springsource.net.sf.cglib-sources-2.1.3.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.jar" sourcepath="/IVY_CACHE/org.apache.log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-sources-1.2.15.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.junit/com.springsource.org.junit/4.5.0/com.springsource.org.junit-4.5.0.jar" sourcepath="/IVY_CACHE/org.junit/com.springsource.org.junit/4.5.0/com.springsource.org.junit-sources-4.5.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.objectweb.asm/com.springsource.org.objectweb.asm/2.2.3/com.springsource.org.objectweb.asm-2.2.3.jar" sourcepath="/IVY_CACHE/org.objectweb.asm/com.springsource.org.objectweb.asm/2.2.3/com.springsource.org.objectweb.asm-sources-2.2.3.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.objectweb.asm/com.springsource.org.objectweb.asm.commons/2.2.3/com.springsource.org.objectweb.asm.commons-2.2.3.jar" sourcepath="/IVY_CACHE/org.objectweb.asm/com.springsource.org.objectweb.asm.commons/2.2.3/com.springsource.org.objectweb.asm.commons-sources-2.2.3.jar"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.beans"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.core"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.pool/1.3.0/com.springsource.org.apache.commons.pool-1.3.0.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.pool/1.3.0/com.springsource.org.apache.commons.pool-sources-1.3.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.aspectj/com.springsource.org.aspectj.weaver/1.6.2.RELEASE/com.springsource.org.aspectj.weaver-1.6.2.RELEASE.jar" sourcepath="IVY_CACHE/org.aspectj/com.springsource.org.aspectj.weaver/1.6.2.RELEASE/com.springsource.org.aspectj.weaver-sources-1.6.2.RELEASE.jar"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.springframework.aop</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -1,268 +0,0 @@
|
||||
#Fri Dec 12 11:37:26 PST 2008
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
|
||||
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
|
||||
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
|
||||
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
|
||||
org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_after_package=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_field=0
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_method=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_package=0
|
||||
org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
|
||||
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
|
||||
org.eclipse.jdt.core.formatter.comment.format_block_comments=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_header=false
|
||||
org.eclipse.jdt.core.formatter.comment.format_html=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_line_comments=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_source_code=true
|
||||
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
|
||||
org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
|
||||
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
|
||||
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
|
||||
org.eclipse.jdt.core.formatter.comment.line_length=80
|
||||
org.eclipse.jdt.core.formatter.compact_else_if=true
|
||||
org.eclipse.jdt.core.formatter.continuation_indentation=2
|
||||
org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
|
||||
org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
|
||||
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
|
||||
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
|
||||
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
|
||||
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
|
||||
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
|
||||
org.eclipse.jdt.core.formatter.indent_empty_lines=false
|
||||
org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
|
||||
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
|
||||
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
|
||||
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
|
||||
org.eclipse.jdt.core.formatter.indentation.size=4
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
|
||||
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
|
||||
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
|
||||
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
|
||||
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
|
||||
org.eclipse.jdt.core.formatter.lineSplit=80
|
||||
org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
|
||||
org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
|
||||
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
|
||||
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
|
||||
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
|
||||
org.eclipse.jdt.core.formatter.tabulation.char=tab
|
||||
org.eclipse.jdt.core.formatter.tabulation.size=4
|
||||
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
|
||||
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
|
||||
@@ -1,4 +0,0 @@
|
||||
#Fri Dec 12 11:37:26 PST 2008
|
||||
eclipse.preferences.version=1
|
||||
formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile
|
||||
formatter_settings_version=11
|
||||
@@ -1,122 +0,0 @@
|
||||
<?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$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||
</content>
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="module" module-name="beans" />
|
||||
<orderEntry type="module" module-name="core" />
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$IVY_CACHE$/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-1.0.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$IVY_CACHE$/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-sources-1.0.0.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$IVY_CACHE$/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$IVY_CACHE$/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-sources-1.1.1.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$IVY_CACHE$/org.apache.commons/com.springsource.org.apache.commons.pool/1.4.0/com.springsource.org.apache.commons.pool-1.4.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$IVY_CACHE$/org.apache.commons/com.springsource.org.apache.commons.pool/1.4.0/com.springsource.org.apache.commons.pool-sources-1.4.0.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$IVY_CACHE$/org.aspectj/com.springsource.org.aspectj.weaver/1.6.2.RELEASE/com.springsource.org.aspectj.weaver-1.6.2.RELEASE.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$IVY_CACHE$/org.aspectj/com.springsource.org.aspectj.weaver/1.6.2.RELEASE/com.springsource.org.aspectj.weaver-sources-1.6.2.RELEASE.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$IVY_CACHE$/com.jamonapi/com.springsource.com.jamonapi/2.4.0/com.springsource.com.jamonapi-2.4.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$IVY_CACHE$/com.jamonapi/com.springsource.com.jamonapi/2.4.0/com.springsource.com.jamonapi-sources-2.4.0.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$IVY_CACHE$/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.1.3/com.springsource.net.sf.cglib-2.1.3.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$IVY_CACHE$/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.1.3/com.springsource.net.sf.cglib-sources-2.1.3.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$IVY_CACHE$/org.apache.log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$IVY_CACHE$/org.apache.log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-sources-1.2.15.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$IVY_CACHE$/org.junit/com.springsource.org.junit/4.5.0/com.springsource.org.junit-4.5.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$IVY_CACHE$/org.junit/com.springsource.org.junit/4.5.0/com.springsource.org.junit-sources-4.5.0.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$IVY_CACHE$/org.easymock/com.springsource.org.easymock/2.3.0/com.springsource.org.easymock-2.3.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$IVY_CACHE$/org.easymock/com.springsource.org.easymock/2.3.0/com.springsource.org.easymock-sources-2.3.0.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</orderEntry>
|
||||
</component>
|
||||
<component name="copyright">
|
||||
<Base>
|
||||
<setting name="state" value="2" />
|
||||
</Base>
|
||||
</component>
|
||||
</module>
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="org.springframework.aop">
|
||||
<property file="${basedir}/../build.properties"/>
|
||||
<import file="${basedir}/../build-spring-framework/package-bundle.xml"/>
|
||||
<import file="${basedir}/../spring-build/standard/default.xml"/>
|
||||
</project>
|
||||
@@ -1,42 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml-stylesheet type="text/xsl" href="http://ivyrep.jayasoft.org/ivy-doc.xsl"?>
|
||||
<ivy-module
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="http://incubator.apache.org/ivy/schemas/ivy.xsd"
|
||||
version="1.3">
|
||||
|
||||
<info organisation="org.springframework" module="${ant.project.name}">
|
||||
<license name="Apache 2.0" url="http://www.apache.org/licenses/LICENSE-2.0"/>
|
||||
</info>
|
||||
|
||||
<configurations>
|
||||
<include file="${spring.build.dir}/common/default-ivy-configurations.xml"/>
|
||||
<conf name="aspectj" extends="runtime" description="JARs needed to run with AspectJ"/>
|
||||
<conf name="bytecode-proxy" extends="runtime" description="JARs needed to run with CGLIB bytecode proxies"/>
|
||||
<conf name="jamon" extends="runtime" description="JARs needed to run with JamonAPI"/>
|
||||
<conf name="pooling" extends="runtime" description="JARs needed to run the pooling target source"/>
|
||||
</configurations>
|
||||
|
||||
<publications>
|
||||
<artifact name="${ant.project.name}"/>
|
||||
<artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
|
||||
</publications>
|
||||
|
||||
<dependencies>
|
||||
<dependency org="com.jamonapi" name="com.springsource.com.jamonapi" rev="2.4.0" conf="optional, jamon->compile"/>
|
||||
<dependency org="net.sourceforge.cglib" name="com.springsource.net.sf.cglib" rev="2.1.3" conf="optional, bytecode-proxy->compile"/>
|
||||
<dependency org="org.aopalliance" name="com.springsource.org.aopalliance" rev="1.0.0" conf="compile->compile"/>
|
||||
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.logging" rev="1.1.1" conf="compile->compile"/>
|
||||
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.pool" rev="1.4.0" conf="optional, pooling->compile"/>
|
||||
<dependency org="org.aspectj" name="com.springsource.org.aspectj.weaver" rev="1.6.2.RELEASE" conf="optional, aspectj->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.beans" rev="latest.integration" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.core" rev="latest.integration" conf="compile->compile"/>
|
||||
<!-- test dependencies -->
|
||||
<dependency org="org.apache.log4j" name="com.springsource.org.apache.log4j" rev="1.2.15" conf="test->runtime"/>
|
||||
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="2.3.0" conf="test->compile"/>
|
||||
<dependency org="org.junit" name="com.springsource.org.junit" rev="4.5.0" conf="test->runtime"/>
|
||||
<dependency org="org.objectweb.asm" name="com.springsource.org.objectweb.asm" rev="2.2.3" conf="test->runtime"/>
|
||||
<dependency org="org.objectweb.asm" name="com.springsource.org.objectweb.asm.commons" rev="2.2.3" conf="test->runtime"/>
|
||||
</dependencies>
|
||||
|
||||
</ivy-module>
|
||||
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>org.springframework.aop</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Spring Core Abstractions and Utilities</name>
|
||||
<version>3.0.0.M1</version>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>com.springsource.repository.bundles.external</id>
|
||||
<name>SpringSource Enterprise Bundle Repository - External Bundle Releases</name>
|
||||
<url>http://repository.springsource.com/maven/bundles/external</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.5</source>
|
||||
<target>1.5</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<version>1.1.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aopalliance</groupId>
|
||||
<artifactId>com.springsource.org.aopalliance</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>com.springsource.org.apache.commons.pool</artifactId>
|
||||
<version>1.4.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
|
||||
/**
|
||||
* Base interface holding AOP <b>advice</b> (action to take at a joinpoint)
|
||||
* and a filter determining the applicability of the advice (such as
|
||||
* a pointcut). <i>This interface is not for use by Spring users, but to
|
||||
* allow for commonality in support for different types of advice.</i>
|
||||
*
|
||||
* <p>Spring AOP is based around <b>around advice</b> delivered via method
|
||||
* <b>interception</b>, compliant with the AOP Alliance interception API.
|
||||
* The Advisor interface allows support for different types of advice,
|
||||
* such as <b>before</b> and <b>after</b> advice, which need not be
|
||||
* implemented using interception.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public interface Advisor {
|
||||
|
||||
/**
|
||||
* Return the advice part of this aspect. An advice may be an
|
||||
* interceptor, a before advice, a throws advice, etc.
|
||||
* @return the advice that should apply if the pointcut matches
|
||||
* @see org.aopalliance.intercept.MethodInterceptor
|
||||
* @see BeforeAdvice
|
||||
* @see ThrowsAdvice
|
||||
* @see AfterReturningAdvice
|
||||
*/
|
||||
Advice getAdvice();
|
||||
|
||||
/**
|
||||
* Return whether this advice is associated with a particular instance
|
||||
* (for example, creating a mixin) or shared with all instances of
|
||||
* the advised class obtained from the same Spring bean factory.
|
||||
* <p><b>Note that this method is not currently used by the framework.</b>
|
||||
* Typical Advisor implementations always return <code>true</code>.
|
||||
* Use singleton/prototype bean definitions or appropriate programmatic
|
||||
* proxy creation to ensure that Advisors have the correct lifecycle model.
|
||||
* @return whether this advice is associated with a particular target instance
|
||||
*/
|
||||
boolean isPerInstance();
|
||||
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
|
||||
/**
|
||||
* Common marker interface for after advice,
|
||||
* such as {@link AfterReturningAdvice} and {@link ThrowsAdvice}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0.3
|
||||
* @see BeforeAdvice
|
||||
*/
|
||||
public interface AfterAdvice extends Advice {
|
||||
|
||||
}
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* After returning advice is invoked only on normal method return, not if an
|
||||
* exception is thrown. Such advice can see the return value, but cannot change it.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @see MethodBeforeAdvice
|
||||
* @see ThrowsAdvice
|
||||
*/
|
||||
public interface AfterReturningAdvice extends AfterAdvice {
|
||||
|
||||
/**
|
||||
* Callback after a given method successfully returned.
|
||||
* @param returnValue the value returned by the method, if any
|
||||
* @param method method being invoked
|
||||
* @param args arguments to the method
|
||||
* @param target target of the method invocation. May be <code>null</code>.
|
||||
* @throws Throwable if this object wishes to abort the call.
|
||||
* Any exception thrown will be returned to the caller if it's
|
||||
* allowed by the method signature. Otherwise the exception
|
||||
* will be wrapped as a runtime exception.
|
||||
*/
|
||||
void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable;
|
||||
|
||||
}
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
import org.springframework.core.NestedRuntimeException;
|
||||
|
||||
/**
|
||||
* Exception that gets thrown when an AOP invocation failed
|
||||
* because of misconfiguration or unexpected runtime issues.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AopInvocationException extends NestedRuntimeException {
|
||||
|
||||
/**
|
||||
* Constructor for AopInvocationException.
|
||||
* @param msg the detail message
|
||||
*/
|
||||
public AopInvocationException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for AopInvocationException.
|
||||
* @param msg the detail message
|
||||
* @param cause the root cause
|
||||
*/
|
||||
public AopInvocationException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
|
||||
/**
|
||||
* Common marker interface for before advice, such as {@link MethodBeforeAdvice}.
|
||||
*
|
||||
* <p>Spring supports only method before advice. Although this is unlikely to change,
|
||||
* this API is designed to allow field advice in future if desired.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @see AfterAdvice
|
||||
*/
|
||||
public interface BeforeAdvice extends Advice {
|
||||
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
/**
|
||||
* Filter that restricts matching of a pointcut or introduction to
|
||||
* a given set of target classes.
|
||||
*
|
||||
* <p>Can be used as part of a {@link Pointcut} or for the entire
|
||||
* targeting of an {@link IntroductionAdvisor}.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @see Pointcut
|
||||
* @see MethodMatcher
|
||||
*/
|
||||
public interface ClassFilter {
|
||||
|
||||
/**
|
||||
* Should the pointcut apply to the given interface or target class?
|
||||
* @param clazz the candidate target class
|
||||
* @return whether the advice should apply to the given target class
|
||||
*/
|
||||
boolean matches(Class<?> clazz);
|
||||
|
||||
|
||||
/**
|
||||
* Canonical instance of a ClassFilter that matches all classes.
|
||||
*/
|
||||
ClassFilter TRUE = TrueClassFilter.INSTANCE;
|
||||
|
||||
}
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
|
||||
/**
|
||||
* Subinterface of AOP Alliance Advice that allows additional interfaces
|
||||
* to be implemented by an Advice, and available via a proxy using that
|
||||
* interceptor. This is a fundamental AOP concept called <b>introduction</b>.
|
||||
*
|
||||
* <p>Introductions are often <b>mixins</b>, enabling the building of composite
|
||||
* objects that can achieve many of the goals of multiple inheritance in Java.
|
||||
*
|
||||
* <p>Compared to {qlink IntroductionInfo}, this interface allows an advice to
|
||||
* implement a range of interfaces that is not necessarily known in advance.
|
||||
* Thus an {@link IntroductionAdvisor} can be used to specify which interfaces
|
||||
* will be exposed in an advised object.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 1.1.1
|
||||
* @see IntroductionInfo
|
||||
* @see IntroductionAdvisor
|
||||
*/
|
||||
public interface DynamicIntroductionAdvice extends Advice {
|
||||
|
||||
/**
|
||||
* Does this introduction advice implement the given interface?
|
||||
* @param intf the interface to check
|
||||
* @return whether the advice implements the specified interface
|
||||
*/
|
||||
boolean implementsInterface(Class<?> intf);
|
||||
|
||||
}
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
/**
|
||||
* Superinterface for advisors that perform one or more AOP <b>introductions</b>.
|
||||
*
|
||||
* <p>This interface cannot be implemented directly; subinterfaces must
|
||||
* provide the advice type implementing the introduction.
|
||||
*
|
||||
* <p>Introduction is the implementation of additional interfaces
|
||||
* (not implemented by a target) via AOP advice.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 04.04.2003
|
||||
* @see IntroductionInterceptor
|
||||
*/
|
||||
public interface IntroductionAdvisor extends Advisor, IntroductionInfo {
|
||||
|
||||
/**
|
||||
* Return the filter determining which target classes this introduction
|
||||
* should apply to.
|
||||
* <p>This represents the class part of a pointcut. Note that method
|
||||
* matching doesn't make sense to introductions.
|
||||
* @return the class filter
|
||||
*/
|
||||
ClassFilter getClassFilter();
|
||||
|
||||
/**
|
||||
* Can the advised interfaces be implemented by the introduction advice?
|
||||
* Invoked before adding an IntroductionAdvisor.
|
||||
* @throws IllegalArgumentException if the advised interfaces can't be
|
||||
* implemented by the introduction advice
|
||||
*/
|
||||
void validateInterfaces() throws IllegalArgumentException;
|
||||
|
||||
}
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* A specialized type of MethodMatcher that takes into account introductions when
|
||||
* matching methods. If there are no introductions on the target class, a method
|
||||
* matcher may be able to optimize matching more effectively for example.
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface IntroductionAwareMethodMatcher extends MethodMatcher {
|
||||
|
||||
/**
|
||||
* Perform static checking whether the given method matches. This may be invoked
|
||||
* instead of the 2-arg {@link #matches(java.lang.reflect.Method, Class)} method
|
||||
* if the caller supports the extended IntroductionAwareMethodMatcher interface.
|
||||
* @param method the candidate method
|
||||
* @param targetClass the target class (may be <code>null</code>, in which case
|
||||
* the candidate class must be taken to be the method's declaring class)
|
||||
* @param hasIntroductions <code>true</code> if the object on whose behalf we are
|
||||
* asking is the subject on one or more introductions; <code>false</code> otherwise
|
||||
* @return whether or not this method matches statically
|
||||
*/
|
||||
boolean matches(Method method, Class targetClass, boolean hasIntroductions);
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
/**
|
||||
* Interface supplying the information necessary to describe an introduction.
|
||||
*
|
||||
* <p>{@link IntroductionAdvisor IntroductionAdvisors} must implement this
|
||||
* interface. If an {@link org.aopalliance.aop.Advice} implements this,
|
||||
* it may be used as an introduction without an {@link IntroductionAdvisor}.
|
||||
* In this case, the advice is self-describing, providing not only the
|
||||
* necessary behavior, but describing the interfaces it introduces.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 1.1.1
|
||||
*/
|
||||
public interface IntroductionInfo {
|
||||
|
||||
/**
|
||||
* Return the additional interfaces introduced by this Advisor or Advice.
|
||||
* @return the introduced interfaces
|
||||
*/
|
||||
Class[] getInterfaces();
|
||||
|
||||
}
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
|
||||
/**
|
||||
* Subinterface of AOP Alliance MethodInterceptor that allows additional interfaces
|
||||
* to be implemented by the interceptor, and available via a proxy using that
|
||||
* interceptor. This is a fundamental AOP concept called <b>introduction</b>.
|
||||
*
|
||||
* <p>Introductions are often <b>mixins</b>, enabling the building of composite
|
||||
* objects that can achieve many of the goals of multiple inheritance in Java.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @see DynamicIntroductionAdvice
|
||||
*/
|
||||
public interface IntroductionInterceptor extends MethodInterceptor, DynamicIntroductionAdvice {
|
||||
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2005 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Advice invoked before a method is invoked. Such advices cannot
|
||||
* prevent the method call proceeding, unless they throw a Throwable.
|
||||
*
|
||||
* @see AfterReturningAdvice
|
||||
* @see ThrowsAdvice
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public interface MethodBeforeAdvice extends BeforeAdvice {
|
||||
|
||||
/**
|
||||
* Callback before a given method is invoked.
|
||||
* @param method method being invoked
|
||||
* @param args arguments to the method
|
||||
* @param target target of the method invocation. May be <code>null</code>.
|
||||
* @throws Throwable if this object wishes to abort the call.
|
||||
* Any exception thrown will be returned to the caller if it's
|
||||
* allowed by the method signature. Otherwise the exception
|
||||
* will be wrapped as a runtime exception.
|
||||
*/
|
||||
void before(Method method, Object[] args, Object target) throws Throwable;
|
||||
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Part of a {@link Pointcut}: Checks whether the target method is eligible for advice.
|
||||
*
|
||||
* <p>A MethodMatcher may be evaluated <b>statically</b> or at <b>runtime</b> (dynamically).
|
||||
* Static matching involves method and (possibly) method attributes. Dynamic matching
|
||||
* also makes arguments for a particular call available, and any effects of running
|
||||
* previous advice applying to the joinpoint.
|
||||
*
|
||||
* <p>If an implementation returns <code>false</code> from its {@link #isRuntime()}
|
||||
* method, evaluation can be performed statically, and the result will be the same
|
||||
* for all invocations of this method, whatever their arguments. This means that
|
||||
* if the {@link #isRuntime()} method returns <code>false</code>, the 3-arg
|
||||
* {@link #matches(java.lang.reflect.Method, Class, Object[])} method will never be invoked.
|
||||
*
|
||||
* <p>If an implementation returns <code>true</code> from its 2-arg
|
||||
* {@link #matches(java.lang.reflect.Method, Class)} method and its {@link #isRuntime()} method
|
||||
* returns <code>true</code>, the 3-arg {@link #matches(java.lang.reflect.Method, Class, Object[])}
|
||||
* method will be invoked <i>immediately before each potential execution of the related advice</i>,
|
||||
* to decide whether the advice should run. All previous advice, such as earlier interceptors
|
||||
* in an interceptor chain, will have run, so any state changes they have produced in
|
||||
* parameters or ThreadLocal state will be available at the time of evaluation.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 11.11.2003
|
||||
* @see Pointcut
|
||||
* @see ClassFilter
|
||||
*/
|
||||
public interface MethodMatcher {
|
||||
|
||||
/**
|
||||
* Perform static checking whether the given method matches. If this
|
||||
* returns <code>false</code> or if the {@link #isRuntime()} method
|
||||
* returns <code>false</code>, no runtime check (i.e. no.
|
||||
* {@link #matches(java.lang.reflect.Method, Class, Object[])} call) will be made.
|
||||
* @param method the candidate method
|
||||
* @param targetClass the target class (may be <code>null</code>, in which case
|
||||
* the candidate class must be taken to be the method's declaring class)
|
||||
* @return whether or not this method matches statically
|
||||
*/
|
||||
boolean matches(Method method, Class<?> targetClass);
|
||||
|
||||
/**
|
||||
* Is this MethodMatcher dynamic, that is, must a final call be made on the
|
||||
* {@link #matches(java.lang.reflect.Method, Class, Object[])} method at
|
||||
* runtime even if the 2-arg matches method returns <code>true</code>?
|
||||
* <p>Can be invoked when an AOP proxy is created, and need not be invoked
|
||||
* again before each method invocation,
|
||||
* @return whether or not a runtime match via the 3-arg
|
||||
* {@link #matches(java.lang.reflect.Method, Class, Object[])} method
|
||||
* is required if static matching passed
|
||||
*/
|
||||
boolean isRuntime();
|
||||
|
||||
/**
|
||||
* Check whether there a runtime (dynamic) match for this method,
|
||||
* which must have matched statically.
|
||||
* <p>This method is invoked only if the 2-arg matches method returns
|
||||
* <code>true</code> for the given method and target class, and if the
|
||||
* {@link #isRuntime()} method returns <code>true</code>. Invoked
|
||||
* immediately before potential running of the advice, after any
|
||||
* advice earlier in the advice chain has run.
|
||||
* @param method the candidate method
|
||||
* @param targetClass the target class (may be <code>null</code>, in which case
|
||||
* the candidate class must be taken to be the method's declaring class)
|
||||
* @param args arguments to the method
|
||||
* @return whether there's a runtime match
|
||||
* @see MethodMatcher#matches(Method, Class)
|
||||
*/
|
||||
boolean matches(Method method, Class<?> targetClass, Object[] args);
|
||||
|
||||
|
||||
/**
|
||||
* Canonical instance that matches all methods.
|
||||
*/
|
||||
MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
/**
|
||||
* Core Spring pointcut abstraction.
|
||||
*
|
||||
* <p>A pointcut is composed of a {@link ClassFilter} and a {@link MethodMatcher}.
|
||||
* Both these basic terms and a Pointcut itself can be combined to build up combinations
|
||||
* (e.g. through {@link org.springframework.aop.support.ComposablePointcut}).
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @see ClassFilter
|
||||
* @see MethodMatcher
|
||||
* @see org.springframework.aop.support.Pointcuts
|
||||
* @see org.springframework.aop.support.ClassFilters
|
||||
* @see org.springframework.aop.support.MethodMatchers
|
||||
*/
|
||||
public interface Pointcut {
|
||||
|
||||
/**
|
||||
* Return the ClassFilter for this pointcut.
|
||||
* @return the ClassFilter (never <code>null</code>)
|
||||
*/
|
||||
ClassFilter getClassFilter();
|
||||
|
||||
/**
|
||||
* Return the MethodMatcher for this pointcut.
|
||||
* @return the MethodMatcher (never <code>null</code>)
|
||||
*/
|
||||
MethodMatcher getMethodMatcher();
|
||||
|
||||
|
||||
/**
|
||||
* Canonical Pointcut instance that always matches.
|
||||
*/
|
||||
Pointcut TRUE = TruePointcut.INSTANCE;
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2005 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
/**
|
||||
* Superinterface for all Advisors that are driven by a pointcut.
|
||||
* This covers nearly all advisors except introduction advisors,
|
||||
* for which method-level matching doesn't apply.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public interface PointcutAdvisor extends Advisor {
|
||||
|
||||
/**
|
||||
* Get the Pointcut that drives this advisor.
|
||||
*/
|
||||
Pointcut getPointcut();
|
||||
|
||||
}
|
||||
-86
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
/**
|
||||
* Extension of the AOP Alliance {@link org.aopalliance.intercept.MethodInvocation}
|
||||
* interface, allowing access to the proxy that the method invocation was made through.
|
||||
*
|
||||
* <p>Useful to be able to substitute return values with the proxy,
|
||||
* if necessary, for example if the invocation target returned itself.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Adrian Colyer
|
||||
* @since 1.1.3
|
||||
* @see org.springframework.aop.framework.ReflectiveMethodInvocation
|
||||
* @see org.springframework.aop.support.DelegatingIntroductionInterceptor
|
||||
*/
|
||||
public interface ProxyMethodInvocation extends MethodInvocation {
|
||||
|
||||
/**
|
||||
* Return the proxy that this method invocation was made through.
|
||||
* @return the original proxy object
|
||||
*/
|
||||
Object getProxy();
|
||||
|
||||
/**
|
||||
* Create a clone of this object. If cloning is done before <code>proceed()</code>
|
||||
* is invoked on this object, <code>proceed()</code> can be invoked once per clone
|
||||
* to invoke the joinpoint (and the rest of the advice chain) more than once.
|
||||
* @return an invocable clone of this invocation.
|
||||
* <code>proceed()</code> can be called once per clone.
|
||||
*/
|
||||
MethodInvocation invocableClone();
|
||||
|
||||
/**
|
||||
* Create a clone of this object. If cloning is done before <code>proceed()</code>
|
||||
* is invoked on this object, <code>proceed()</code> can be invoked once per clone
|
||||
* to invoke the joinpoint (and the rest of the advice chain) more than once.
|
||||
* @param arguments the arguments that the cloned invocation is supposed to use,
|
||||
* overriding the original arguments
|
||||
* @return an invocable clone of this invocation.
|
||||
* <code>proceed()</code> can be called once per clone.
|
||||
*/
|
||||
MethodInvocation invocableClone(Object[] arguments);
|
||||
|
||||
/**
|
||||
* Set the arguments to be used on subsequent invocations in the any advice
|
||||
* in this chain.
|
||||
* @param arguments the argument array
|
||||
*/
|
||||
void setArguments(Object[] arguments);
|
||||
|
||||
/**
|
||||
* Add the specified user attribute with the given value to this invocation.
|
||||
* <p>Such attributes are not used within the AOP framework itself. They are
|
||||
* just kept as part of the invocation object, for use in special interceptors.
|
||||
* @param key the name of the attribute
|
||||
* @param value the value of the attribute, or <code>null</code> to reset it
|
||||
*/
|
||||
void setUserAttribute(String key, Object value);
|
||||
|
||||
/**
|
||||
* Return the value of the specified user attribute.
|
||||
* @param key the name of the attribute
|
||||
* @return the value of the attribute, or <code>null</code> if not set
|
||||
* @see #setUserAttribute
|
||||
*/
|
||||
Object getUserAttribute(String key);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
/**
|
||||
* Marker for AOP proxy interfaces (in particular: introduction interfaces)
|
||||
* that explicitly intend to return the raw target object (which would normally
|
||||
* get replaced with the proxy object when returned from a method invocation).
|
||||
*
|
||||
* <p>Note that this is a marker interface in the style of {@link java.io.Serializable},
|
||||
* semantically applying to a declared interface rather than to the full class
|
||||
* of a concrete object. In other words, this marker applies to a particular
|
||||
* interface only (typically an introduction interface that does not serve
|
||||
* as the primary interface of an AOP proxy), and hence does not affect
|
||||
* other interfaces that a concrete AOP proxy may implement.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0.5
|
||||
* @see org.springframework.aop.scope.ScopedObject
|
||||
*/
|
||||
public interface RawTargetAccess {
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
/**
|
||||
* Marker interface implemented by all AOP proxies. Used to detect
|
||||
* whether or not objects are Spring-generated proxies.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @since 2.0.1
|
||||
* @see org.springframework.aop.support.AopUtils#isAopProxy(Object)
|
||||
*/
|
||||
public interface SpringProxy {
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
/**
|
||||
* Minimal interface for exposing the target class behind a proxy.
|
||||
*
|
||||
* <p>Implemented by AOP proxy objects and proxy factories
|
||||
* (via {@link org.springframework.aop.framework.Advised}}
|
||||
* as well as by {@link TargetSource TargetSources}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0.3
|
||||
* @see org.springframework.aop.support.AopUtils#getTargetClass(Object)
|
||||
*/
|
||||
public interface TargetClassAware {
|
||||
|
||||
/**
|
||||
* Return the target class behind the implementing object
|
||||
* (typically a proxy configuration or an actual proxy).
|
||||
* @return the target Class, or <code>null</code> if not known
|
||||
*/
|
||||
Class getTargetClass();
|
||||
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*<
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
/**
|
||||
* A <code>TargetSource</code> is used to obtain the current "target" of
|
||||
* an AOP invocation, which will be invoked via reflection if no around
|
||||
* advice chooses to end the interceptor chain itself.
|
||||
*
|
||||
* <p>If a <code>TargetSource</code> is "static", it will always return
|
||||
* the same target, allowing optimizations in the AOP framework. Dynamic
|
||||
* target sources can support pooling, hot swapping, etc.
|
||||
*
|
||||
* <p>Application developers don't usually need to work with
|
||||
* <code>TargetSources</code> directly: this is an AOP framework interface.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public interface TargetSource extends TargetClassAware {
|
||||
|
||||
/**
|
||||
* Return the type of targets returned by this {@link TargetSource}.
|
||||
* <p>Can return <code>null</code>, although certain usages of a
|
||||
* <code>TargetSource</code> might just work with a predetermined
|
||||
* target class.
|
||||
* @return the type of targets returned by this {@link TargetSource}
|
||||
*/
|
||||
Class getTargetClass();
|
||||
|
||||
/**
|
||||
* Will all calls to {@link #getTarget()} return the same object?
|
||||
* <p>In that case, there will be no need to invoke
|
||||
* {@link #releaseTarget(Object)}, and the AOP framework can cache
|
||||
* the return value of {@link #getTarget()}.
|
||||
* @return <code>true</code> if the target is immutable
|
||||
* @see #getTarget
|
||||
*/
|
||||
boolean isStatic();
|
||||
|
||||
/**
|
||||
* Return a target instance. Invoked immediately before the
|
||||
* AOP framework calls the "target" of an AOP method invocation.
|
||||
* @return the target object, which contains the joinpoint
|
||||
* @throws Exception if the target object can't be resolved
|
||||
*/
|
||||
Object getTarget() throws Exception;
|
||||
|
||||
/**
|
||||
* Release the given target object obtained from the
|
||||
* {@link #getTarget()} method.
|
||||
* @param target object obtained from a call to {@link #getTarget()}
|
||||
* @throws Exception if the object can't be released
|
||||
*/
|
||||
void releaseTarget(Object target) throws Exception;
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
/**
|
||||
* Tag interface for throws advice.
|
||||
*
|
||||
* <p>There are not any methods on this interface, as methods are invoked by
|
||||
* reflection. Implementing classes must implement methods of the form:
|
||||
*
|
||||
* <pre class="code">void afterThrowing([Method, args, target], ThrowableSubclass);</pre>
|
||||
*
|
||||
* <p>Some examples of valid methods would be:
|
||||
*
|
||||
* <pre class="code">public void afterThrowing(Exception ex)</pre>
|
||||
* <pre class="code">public void afterThrowing(RemoteException)</pre>
|
||||
* <pre class="code">public void afterThrowing(Method method, Object[] args, Object target, Exception ex)</pre>
|
||||
* <pre class="code">public void afterThrowing(Method method, Object[] args, Object target, ServletException ex)</pre>
|
||||
*
|
||||
* The first three arguments are optional, and only useful if we want further
|
||||
* information about the joinpoint, as in AspectJ <b>after-throwing</b> advice.
|
||||
*
|
||||
* <p><b>Note:</b> If a throws-advice method throws an exception itself, it will
|
||||
* override the original exception (i.e. change the exception thrown to the user).
|
||||
* The overriding exception will typically be a RuntimeException; this is compatible
|
||||
* with any method signature. However, if a throws-advice method throws a checked
|
||||
* exception, it will have to match the declared exceptions of the target method
|
||||
* and is hence to some degree coupled to specific target method signatures.
|
||||
* <b>Do not throw an undeclared checked exception that is incompatible with
|
||||
* the target method's signature!</b>
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @see AfterReturningAdvice
|
||||
* @see MethodBeforeAdvice
|
||||
*/
|
||||
public interface ThrowsAdvice extends AfterAdvice {
|
||||
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Canonical ClassFilter instance that matches all classes.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
class TrueClassFilter implements ClassFilter, Serializable {
|
||||
|
||||
public static final TrueClassFilter INSTANCE = new TrueClassFilter();
|
||||
|
||||
/**
|
||||
* Enforce Singleton pattern.
|
||||
*/
|
||||
private TrueClassFilter() {
|
||||
}
|
||||
|
||||
public boolean matches(Class clazz) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Required to support serialization. Replaces with canonical
|
||||
* instance on deserialization, protecting Singleton pattern.
|
||||
* Alternative to overriding <code>equals()</code>.
|
||||
*/
|
||||
private Object readResolve() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ClassFilter.TRUE";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Canonical MethodMatcher instance that matches all methods.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
class TrueMethodMatcher implements MethodMatcher, Serializable {
|
||||
|
||||
public static final TrueMethodMatcher INSTANCE = new TrueMethodMatcher();
|
||||
|
||||
/**
|
||||
* Enforce Singleton pattern.
|
||||
*/
|
||||
private TrueMethodMatcher() {
|
||||
}
|
||||
|
||||
public boolean isRuntime() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean matches(Method method, Class targetClass) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean matches(Method method, Class targetClass, Object[] args) {
|
||||
// Should never be invoked as isRuntime returns false.
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Required to support serialization. Replaces with canonical
|
||||
* instance on deserialization, protecting Singleton pattern.
|
||||
* Alternative to overriding <code>equals()</code>.
|
||||
*/
|
||||
private Object readResolve() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MethodMatcher.TRUE";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Canonical Pointcut instance that always matches.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
class TruePointcut implements Pointcut, Serializable {
|
||||
|
||||
public static final TruePointcut INSTANCE = new TruePointcut();
|
||||
|
||||
/**
|
||||
* Enforce Singleton pattern.
|
||||
*/
|
||||
private TruePointcut() {
|
||||
}
|
||||
|
||||
public ClassFilter getClassFilter() {
|
||||
return ClassFilter.TRUE;
|
||||
}
|
||||
|
||||
public MethodMatcher getMethodMatcher() {
|
||||
return MethodMatcher.TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Required to support serialization. Replaces with canonical
|
||||
* instance on deserialization, protecting Singleton pattern.
|
||||
* Alternative to overriding <code>equals()</code>.
|
||||
*/
|
||||
private Object readResolve() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Pointcut.TRUE";
|
||||
}
|
||||
|
||||
}
|
||||
-687
@@ -1,687 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.weaver.tools.JoinPointMatch;
|
||||
import org.aspectj.weaver.tools.PointcutParameter;
|
||||
|
||||
import org.springframework.aop.AopInvocationException;
|
||||
import org.springframework.aop.MethodMatcher;
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.ProxyMethodInvocation;
|
||||
import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
|
||||
import org.springframework.aop.support.ComposablePointcut;
|
||||
import org.springframework.aop.support.MethodMatchers;
|
||||
import org.springframework.aop.support.StaticMethodMatcher;
|
||||
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.PrioritizedParameterNameDiscoverer;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Base class for AOP Alliance {@link org.aopalliance.aop.Advice} classes
|
||||
* wrapping an AspectJ aspect or an AspectJ-annotated advice method.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Adrian Colyer
|
||||
* @author Juergen Hoeller
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation {
|
||||
|
||||
/**
|
||||
* Key used in ReflectiveMethodInvocation userAtributes map for the current joinpoint.
|
||||
*/
|
||||
protected static final String JOIN_POINT_KEY = JoinPoint.class.getName();
|
||||
|
||||
|
||||
/**
|
||||
* Lazily instantiate joinpoint for the current invocation.
|
||||
* Requires MethodInvocation to be bound with ExposeInvocationInterceptor.
|
||||
* <p>Do not use if access is available to the current ReflectiveMethodInvocation
|
||||
* (in an around advice).
|
||||
* @return current AspectJ joinpoint, or through an exception if we're not in a
|
||||
* Spring AOP invocation.
|
||||
*/
|
||||
public static JoinPoint currentJoinPoint() {
|
||||
MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
|
||||
if (!(mi instanceof ProxyMethodInvocation)) {
|
||||
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
|
||||
}
|
||||
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
|
||||
JoinPoint jp = (JoinPoint) pmi.getUserAttribute(JOIN_POINT_KEY);
|
||||
if (jp == null) {
|
||||
jp = new MethodInvocationProceedingJoinPoint(pmi);
|
||||
pmi.setUserAttribute(JOIN_POINT_KEY, jp);
|
||||
}
|
||||
return jp;
|
||||
}
|
||||
|
||||
|
||||
protected final Method aspectJAdviceMethod;
|
||||
|
||||
/** The total number of arguments we have to populate on advice dispatch */
|
||||
private final int adviceInvocationArgumentCount;
|
||||
|
||||
private final AspectJExpressionPointcut pointcut;
|
||||
|
||||
private final AspectInstanceFactory aspectInstanceFactory;
|
||||
|
||||
/**
|
||||
* The name of the aspect (ref bean) in which this advice was defined (used
|
||||
* when determining advice precedence so that we can determine
|
||||
* whether two pieces of advice come from the same aspect).
|
||||
*/
|
||||
private String aspectName;
|
||||
|
||||
/**
|
||||
* The order of declaration of this advice within the aspect.
|
||||
*/
|
||||
private int declarationOrder;
|
||||
|
||||
/**
|
||||
* This will be non-null if the creator of this advice object knows the argument names
|
||||
* and sets them explicitly
|
||||
*/
|
||||
private String[] argumentNames = null;
|
||||
|
||||
/** Non-null if after throwing advice binds the thrown value */
|
||||
private String throwingName = null;
|
||||
|
||||
/** Non-null if after returning advice binds the return value */
|
||||
private String returningName = null;
|
||||
|
||||
private Class discoveredReturningType = Object.class;
|
||||
|
||||
private Class discoveredThrowingType = Object.class;
|
||||
|
||||
/**
|
||||
* Index for thisJoinPoint argument (currently only
|
||||
* supported at index 0 if present at all)
|
||||
*/
|
||||
private int joinPointArgumentIndex = -1;
|
||||
|
||||
/**
|
||||
* Index for thisJoinPointStaticPart argument (currently only
|
||||
* supported at index 0 if present at all)
|
||||
*/
|
||||
private int joinPointStaticPartArgumentIndex = -1;
|
||||
|
||||
private Map<String, Integer> argumentBindings = null;
|
||||
|
||||
private boolean argumentsIntrospected = false;
|
||||
|
||||
// The actual type is java.lang.reflect.Type,
|
||||
// but for JDK 1.4 compatibility we use Object as the static type.
|
||||
private Object discoveredReturningGenericType;
|
||||
// Note: Unlike return type, no such generic information is needed for the throwing type,
|
||||
// since Java doesn't allow exception types to be parameterized.
|
||||
|
||||
|
||||
/**
|
||||
* Create a new AbstractAspectJAdvice for the given advice method.
|
||||
* @param aspectJAdviceMethod the AspectJ-style advice method
|
||||
* @param pointcut the AspectJ expression pointcut
|
||||
* @param aspectInstanceFactory the factory for aspect instances
|
||||
*/
|
||||
public AbstractAspectJAdvice(
|
||||
Method aspectJAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aspectInstanceFactory) {
|
||||
|
||||
Assert.notNull(aspectJAdviceMethod, "Advice method must not be null");
|
||||
this.aspectJAdviceMethod = aspectJAdviceMethod;
|
||||
this.adviceInvocationArgumentCount = this.aspectJAdviceMethod.getParameterTypes().length;
|
||||
this.pointcut = pointcut;
|
||||
this.aspectInstanceFactory = aspectInstanceFactory;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the AspectJ-style advice method.
|
||||
*/
|
||||
public final Method getAspectJAdviceMethod() {
|
||||
return this.aspectJAdviceMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the AspectJ expression pointcut.
|
||||
*/
|
||||
public final AspectJExpressionPointcut getPointcut() {
|
||||
calculateArgumentBindings();
|
||||
return this.pointcut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a 'safe' pointcut that excludes the AspectJ advice method itself.
|
||||
* @return a composable pointcut that builds on the original AspectJ expression pointcut
|
||||
* @see #getPointcut()
|
||||
*/
|
||||
public final Pointcut buildSafePointcut() {
|
||||
Pointcut pc = getPointcut();
|
||||
MethodMatcher safeMethodMatcher = MethodMatchers.intersection(
|
||||
new AdviceExcludingMethodMatcher(this.aspectJAdviceMethod), pc.getMethodMatcher());
|
||||
return new ComposablePointcut(pc.getClassFilter(), safeMethodMatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the factory for aspect instances.
|
||||
*/
|
||||
public final AspectInstanceFactory getAspectInstanceFactory() {
|
||||
return this.aspectInstanceFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ClassLoader for aspect instances.
|
||||
*/
|
||||
public final ClassLoader getAspectClassLoader() {
|
||||
return this.aspectInstanceFactory.getAspectClassLoader();
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return this.aspectInstanceFactory.getOrder();
|
||||
}
|
||||
|
||||
|
||||
public void setAspectName(String name) {
|
||||
this.aspectName = name;
|
||||
}
|
||||
|
||||
public String getAspectName() {
|
||||
return this.aspectName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <b>declaration order</b> of this advice within the aspect
|
||||
*/
|
||||
public void setDeclarationOrder(int order) {
|
||||
this.declarationOrder = order;
|
||||
}
|
||||
|
||||
public int getDeclarationOrder() {
|
||||
return this.declarationOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set by creator of this advice object if the argument names are known.
|
||||
* <p>This could be for example because they have been explicitly specified in XML,
|
||||
* or in an advice annotation.
|
||||
* @param argNames comma delimited list of arg names
|
||||
*/
|
||||
public void setArgumentNames(String argNames) {
|
||||
String[] tokens = StringUtils.commaDelimitedListToStringArray(argNames);
|
||||
setArgumentNamesFromStringArray(tokens);
|
||||
}
|
||||
|
||||
public void setArgumentNamesFromStringArray(String[] args) {
|
||||
this.argumentNames = new String[args.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
this.argumentNames[i] = StringUtils.trimWhitespace(args[i]);
|
||||
if (!isVariableName(this.argumentNames[i])) {
|
||||
throw new IllegalArgumentException(
|
||||
"'argumentNames' property of AbstractAspectJAdvice contains an argument name '" +
|
||||
this.argumentNames[i] + "' that is not a valid Java identifier");
|
||||
}
|
||||
}
|
||||
if (argumentNames != null) {
|
||||
if (aspectJAdviceMethod.getParameterTypes().length == argumentNames.length + 1) {
|
||||
// May need to add implicit join point arg name...
|
||||
Class firstArgType = aspectJAdviceMethod.getParameterTypes()[0];
|
||||
if (firstArgType == JoinPoint.class ||
|
||||
firstArgType == ProceedingJoinPoint.class ||
|
||||
firstArgType == JoinPoint.StaticPart.class) {
|
||||
String[] oldNames = argumentNames;
|
||||
argumentNames = new String[oldNames.length + 1];
|
||||
argumentNames[0] = "THIS_JOIN_POINT";
|
||||
System.arraycopy(oldNames, 0, argumentNames, 1, oldNames.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setReturningName(String name) {
|
||||
throw new UnsupportedOperationException("Only afterReturning advice can be used to bind a return value");
|
||||
}
|
||||
|
||||
/**
|
||||
* We need to hold the returning name at this level for argument binding calculations,
|
||||
* this method allows the afterReturning advice subclass to set the name.
|
||||
*/
|
||||
protected void setReturningNameNoCheck(String name) {
|
||||
// name could be a variable or a type...
|
||||
if (isVariableName(name)) {
|
||||
this.returningName = name;
|
||||
}
|
||||
else {
|
||||
// assume a type
|
||||
try {
|
||||
this.discoveredReturningType = ClassUtils.forName(name, getAspectClassLoader());
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException("Returning name '" + name +
|
||||
"' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath. " +
|
||||
"Root cause: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Class getDiscoveredReturningType() {
|
||||
return this.discoveredReturningType;
|
||||
}
|
||||
|
||||
protected Object getDiscoveredReturningGenericType() {
|
||||
return this.discoveredReturningGenericType;
|
||||
}
|
||||
|
||||
public void setThrowingName(String name) {
|
||||
throw new UnsupportedOperationException("Only afterThrowing advice can be used to bind a thrown exception");
|
||||
}
|
||||
|
||||
/**
|
||||
* We need to hold the throwing name at this level for argument binding calculations,
|
||||
* this method allows the afterThrowing advice subclass to set the name.
|
||||
*/
|
||||
protected void setThrowingNameNoCheck(String name) {
|
||||
// name could be a variable or a type...
|
||||
if (isVariableName(name)) {
|
||||
this.throwingName = name;
|
||||
}
|
||||
else {
|
||||
// assume a type
|
||||
try {
|
||||
this.discoveredThrowingType = ClassUtils.forName(name, getAspectClassLoader());
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException("Throwing name '" + name +
|
||||
"' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath. " +
|
||||
"Root cause: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Class getDiscoveredThrowingType() {
|
||||
return this.discoveredThrowingType;
|
||||
}
|
||||
|
||||
private boolean isVariableName(String name) {
|
||||
char[] chars = name.toCharArray();
|
||||
if (!Character.isJavaIdentifierStart(chars[0])) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 1; i < chars.length; i++) {
|
||||
if (!Character.isJavaIdentifierPart(chars[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do as much work as we can as part of the set-up so that argument binding
|
||||
* on subsequent advice invocations can be as fast as possible.
|
||||
* <p>If the first argument is of type JoinPoint or ProceedingJoinPoint then we
|
||||
* pass a JoinPoint in that position (ProceedingJoinPoint for around advice).
|
||||
* <p>If the first argument is of type <code>JoinPoint.StaticPart</code>
|
||||
* then we pass a <code>JoinPoint.StaticPart</code> in that position.
|
||||
* <p>Remaining arguments have to be bound by pointcut evaluation at
|
||||
* a given join point. We will get back a map from argument name to
|
||||
* value. We need to calculate which advice parameter needs to be bound
|
||||
* to which argument name. There are multiple strategies for determining
|
||||
* this binding, which are arranged in a ChainOfResponsibility.
|
||||
*/
|
||||
public synchronized final void calculateArgumentBindings() {
|
||||
// The simple case... nothing to bind.
|
||||
if (this.argumentsIntrospected || this.adviceInvocationArgumentCount == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int numUnboundArgs = this.adviceInvocationArgumentCount;
|
||||
Class[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
|
||||
if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0])) {
|
||||
numUnboundArgs--;
|
||||
}
|
||||
else if (maybeBindJoinPointStaticPart(parameterTypes[0])) {
|
||||
numUnboundArgs--;
|
||||
}
|
||||
|
||||
if (numUnboundArgs > 0) {
|
||||
// need to bind arguments by name as returned from the pointcut match
|
||||
bindArgumentsByName(numUnboundArgs);
|
||||
}
|
||||
|
||||
this.argumentsIntrospected = true;
|
||||
}
|
||||
|
||||
private boolean maybeBindJoinPoint(Class candidateParameterType) {
|
||||
if (candidateParameterType.equals(JoinPoint.class)) {
|
||||
this.joinPointArgumentIndex = 0;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean maybeBindProceedingJoinPoint(Class candidateParameterType) {
|
||||
if (candidateParameterType.equals(ProceedingJoinPoint.class)) {
|
||||
if (!supportsProceedingJoinPoint()) {
|
||||
throw new IllegalArgumentException("ProceedingJoinPoint is only supported for around advice");
|
||||
}
|
||||
this.joinPointArgumentIndex = 0;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean supportsProceedingJoinPoint() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean maybeBindJoinPointStaticPart(Class candidateParameterType) {
|
||||
if (candidateParameterType.equals(JoinPoint.StaticPart.class)) {
|
||||
this.joinPointStaticPartArgumentIndex = 0;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void bindArgumentsByName(int numArgumentsExpectingToBind) {
|
||||
if (this.argumentNames == null) {
|
||||
this.argumentNames = createParameterNameDiscoverer().getParameterNames(this.aspectJAdviceMethod);
|
||||
}
|
||||
if (this.argumentNames != null) {
|
||||
// We have been able to determine the arg names.
|
||||
bindExplicitArguments(numArgumentsExpectingToBind);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Advice method [" + this.aspectJAdviceMethod.getName() + "] " +
|
||||
"requires " + numArgumentsExpectingToBind + " arguments to be bound by name, but " +
|
||||
"the argument names were not specified and could not be discovered.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ParameterNameDiscoverer to be used for argument binding.
|
||||
* <p>The default implementation creates a {@link PrioritizedParameterNameDiscoverer}
|
||||
* containing a {@link LocalVariableTableParameterNameDiscoverer} and an
|
||||
* {@link AspectJAdviceParameterNameDiscoverer}.
|
||||
*/
|
||||
protected ParameterNameDiscoverer createParameterNameDiscoverer() {
|
||||
// We need to discover them, or if that fails, guess,
|
||||
// and if we can't guess with 100% accuracy, fail.
|
||||
PrioritizedParameterNameDiscoverer discoverer = new PrioritizedParameterNameDiscoverer();
|
||||
discoverer.addDiscoverer(new LocalVariableTableParameterNameDiscoverer());
|
||||
AspectJAdviceParameterNameDiscoverer adviceParameterNameDiscoverer =
|
||||
new AspectJAdviceParameterNameDiscoverer(this.pointcut.getExpression());
|
||||
adviceParameterNameDiscoverer.setReturningName(this.returningName);
|
||||
adviceParameterNameDiscoverer.setThrowingName(this.throwingName);
|
||||
// Last in chain, so if we're called and we fail, that's bad...
|
||||
adviceParameterNameDiscoverer.setRaiseExceptions(true);
|
||||
discoverer.addDiscoverer(adviceParameterNameDiscoverer);
|
||||
return discoverer;
|
||||
}
|
||||
|
||||
private void bindExplicitArguments(int numArgumentsLeftToBind) {
|
||||
this.argumentBindings = new HashMap<String, Integer>();
|
||||
|
||||
int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterTypes().length;
|
||||
if (this.argumentNames.length != numExpectedArgumentNames) {
|
||||
throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames
|
||||
+ " arguments to bind by name in advice, but actually found " +
|
||||
this.argumentNames.length + " arguments.");
|
||||
}
|
||||
|
||||
// So we match in number...
|
||||
int argumentIndexOffset = this.adviceInvocationArgumentCount - numArgumentsLeftToBind;
|
||||
for (int i = argumentIndexOffset; i < this.argumentNames.length; i++) {
|
||||
this.argumentBindings.put(this.argumentNames[i], i);
|
||||
}
|
||||
|
||||
// Check that returning and throwing were in the argument names list if
|
||||
// specified, and find the discovered argument types.
|
||||
if (this.returningName != null) {
|
||||
if (!this.argumentBindings.containsKey(this.returningName)) {
|
||||
throw new IllegalStateException("Returning argument name '"
|
||||
+ this.returningName + "' was not bound in advice arguments");
|
||||
}
|
||||
else {
|
||||
Integer index = this.argumentBindings.get(this.returningName);
|
||||
this.discoveredReturningType = this.aspectJAdviceMethod.getParameterTypes()[index];
|
||||
this.discoveredReturningGenericType = this.aspectJAdviceMethod.getGenericParameterTypes()[index];
|
||||
}
|
||||
}
|
||||
if (this.throwingName != null) {
|
||||
if (!this.argumentBindings.containsKey(this.throwingName)) {
|
||||
throw new IllegalStateException("Throwing argument name '"
|
||||
+ this.throwingName + "' was not bound in advice arguments");
|
||||
}
|
||||
else {
|
||||
Integer index = this.argumentBindings.get(this.throwingName);
|
||||
this.discoveredThrowingType = this.aspectJAdviceMethod.getParameterTypes()[index];
|
||||
}
|
||||
}
|
||||
|
||||
// configure the pointcut expression accordingly.
|
||||
configurePointcutParameters(argumentIndexOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* All parameters from argumentIndexOffset onwards are candidates for
|
||||
* pointcut parameters - but returning and throwing vars are handled differently
|
||||
* and must be removed from the list if present.
|
||||
*/
|
||||
private void configurePointcutParameters(int argumentIndexOffset) {
|
||||
int numParametersToRemove = argumentIndexOffset;
|
||||
if (this.returningName != null) {
|
||||
numParametersToRemove++;
|
||||
}
|
||||
if (this.throwingName != null) {
|
||||
numParametersToRemove++;
|
||||
}
|
||||
String[] pointcutParameterNames = new String[this.argumentNames.length - numParametersToRemove];
|
||||
Class[] pointcutParameterTypes = new Class[pointcutParameterNames.length];
|
||||
Class[] methodParameterTypes = this.aspectJAdviceMethod.getParameterTypes();
|
||||
|
||||
int index = 0;
|
||||
for (int i = 0; i < this.argumentNames.length; i++) {
|
||||
if (i < argumentIndexOffset) {
|
||||
continue;
|
||||
}
|
||||
if (this.argumentNames[i].equals(this.returningName) ||
|
||||
this.argumentNames[i].equals(this.throwingName)) {
|
||||
continue;
|
||||
}
|
||||
pointcutParameterNames[index] = this.argumentNames[i];
|
||||
pointcutParameterTypes[index] = methodParameterTypes[i];
|
||||
index++;
|
||||
}
|
||||
|
||||
this.pointcut.setParameterNames(pointcutParameterNames);
|
||||
this.pointcut.setParameterTypes(pointcutParameterTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the arguments at the method execution join point and output a set of arguments
|
||||
* to the advice method
|
||||
* @param jp the current JoinPoint
|
||||
* @param jpMatch the join point match that matched this execution join point
|
||||
* @param returnValue the return value from the method execution (may be null)
|
||||
* @param ex the exception thrown by the method execution (may be null)
|
||||
* @return the empty array if there are no arguments
|
||||
*/
|
||||
protected Object[] argBinding(JoinPoint jp, JoinPointMatch jpMatch, Object returnValue, Throwable ex) {
|
||||
calculateArgumentBindings();
|
||||
|
||||
// AMC start
|
||||
Object[] adviceInvocationArgs = new Object[this.adviceInvocationArgumentCount];
|
||||
int numBound = 0;
|
||||
|
||||
if (this.joinPointArgumentIndex != -1) {
|
||||
adviceInvocationArgs[this.joinPointArgumentIndex] = jp;
|
||||
numBound++;
|
||||
}
|
||||
else if (this.joinPointStaticPartArgumentIndex != -1) {
|
||||
adviceInvocationArgs[this.joinPointStaticPartArgumentIndex] = jp.getStaticPart();
|
||||
numBound++;
|
||||
}
|
||||
|
||||
if (!CollectionUtils.isEmpty(this.argumentBindings)) {
|
||||
// binding from pointcut match
|
||||
if (jpMatch != null) {
|
||||
PointcutParameter[] parameterBindings = jpMatch.getParameterBindings();
|
||||
for (PointcutParameter parameter : parameterBindings) {
|
||||
String name = parameter.getName();
|
||||
Integer index = this.argumentBindings.get(name);
|
||||
adviceInvocationArgs[index] = parameter.getBinding();
|
||||
numBound++;
|
||||
}
|
||||
}
|
||||
// binding from returning clause
|
||||
if (this.returningName != null) {
|
||||
Integer index = this.argumentBindings.get(this.returningName);
|
||||
adviceInvocationArgs[index] = returnValue;
|
||||
numBound++;
|
||||
}
|
||||
// binding from thrown exception
|
||||
if (this.throwingName != null) {
|
||||
Integer index = this.argumentBindings.get(this.throwingName);
|
||||
adviceInvocationArgs[index] = ex;
|
||||
numBound++;
|
||||
}
|
||||
}
|
||||
|
||||
if (numBound != this.adviceInvocationArgumentCount) {
|
||||
throw new IllegalStateException("Required to bind " + this.adviceInvocationArgumentCount
|
||||
+ " arguments, but only bound " + numBound + " (JoinPointMatch " +
|
||||
(jpMatch == null ? "was NOT" : "WAS") +
|
||||
" bound in invocation)");
|
||||
}
|
||||
|
||||
return adviceInvocationArgs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Invoke the advice method.
|
||||
* @param jpMatch the JoinPointMatch that matched this execution join point
|
||||
* @param returnValue the return value from the method execution (may be null)
|
||||
* @param ex the exception thrown by the method execution (may be null)
|
||||
* @return the invocation result
|
||||
* @throws Throwable in case of invocation failure
|
||||
*/
|
||||
protected Object invokeAdviceMethod(JoinPointMatch jpMatch, Object returnValue, Throwable ex) throws Throwable {
|
||||
return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
|
||||
}
|
||||
|
||||
// As above, but in this case we are given the join point.
|
||||
protected Object invokeAdviceMethod(JoinPoint jp, JoinPointMatch jpMatch, Object returnValue, Throwable t)
|
||||
throws Throwable {
|
||||
|
||||
return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
|
||||
}
|
||||
|
||||
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
|
||||
Object[] actualArgs = args;
|
||||
if (this.aspectJAdviceMethod.getParameterTypes().length == 0) {
|
||||
actualArgs = null;
|
||||
}
|
||||
try {
|
||||
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
|
||||
// TODO AopUtils.invokeJoinpointUsingReflection
|
||||
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
throw new AopInvocationException("Mismatch on arguments to advice method [" +
|
||||
this.aspectJAdviceMethod + "]; pointcut expression [" +
|
||||
this.pointcut.getPointcutExpression() + "]", ex);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw ex.getTargetException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridden in around advice to return proceeding join point.
|
||||
*/
|
||||
protected JoinPoint getJoinPoint() {
|
||||
return currentJoinPoint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current join point match at the join point we are being dispatched on.
|
||||
*/
|
||||
protected JoinPointMatch getJoinPointMatch() {
|
||||
MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
|
||||
if (!(mi instanceof ProxyMethodInvocation)) {
|
||||
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
|
||||
}
|
||||
return getJoinPointMatch((ProxyMethodInvocation) mi);
|
||||
}
|
||||
|
||||
// Note: We can't use JoinPointMatch.getClass().getName() as the key, since
|
||||
// Spring AOP does all the matching at a join point, and then all the invocations.
|
||||
// Under this scenario, if we just use JoinPointMatch as the key, then
|
||||
// 'last man wins' which is not what we want at all.
|
||||
// Using the expression is guaranteed to be safe, since 2 identical expressions
|
||||
// are guaranteed to bind in exactly the same way.
|
||||
protected JoinPointMatch getJoinPointMatch(ProxyMethodInvocation pmi) {
|
||||
return (JoinPointMatch) pmi.getUserAttribute(this.pointcut.getExpression());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getName() + ": advice method [" + this.aspectJAdviceMethod + "]; " +
|
||||
"aspect name '" + this.aspectName + "'";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* MethodMatcher that excludes the specified advice method.
|
||||
* @see AbstractAspectJAdvice#buildSafePointcut()
|
||||
*/
|
||||
private static class AdviceExcludingMethodMatcher extends StaticMethodMatcher {
|
||||
|
||||
private final Method adviceMethod;
|
||||
|
||||
public AdviceExcludingMethodMatcher(Method adviceMethod) {
|
||||
this.adviceMethod = adviceMethod;
|
||||
}
|
||||
|
||||
public boolean matches(Method method, Class targetClass) {
|
||||
return !this.adviceMethod.equals(method);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
/**
|
||||
* Interface implemented to provide an instance of an AspectJ aspect.
|
||||
* Decouples from Spring's bean factory.
|
||||
*
|
||||
* <p>Extends the {@link org.springframework.core.Ordered} interface
|
||||
* to express an order value for the underlying aspect in a chain.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see org.springframework.beans.factory.BeanFactory#getBean
|
||||
*/
|
||||
public interface AspectInstanceFactory extends Ordered {
|
||||
|
||||
/**
|
||||
* Create an instance of this factory's aspect.
|
||||
* @return the aspect instance (never <code>null</code>)
|
||||
*/
|
||||
Object getAspectInstance();
|
||||
|
||||
/**
|
||||
* Expose the aspect class loader that this factory uses.
|
||||
* @return the aspect class loader (never <code>null</code>)
|
||||
*/
|
||||
ClassLoader getAspectClassLoader();
|
||||
|
||||
}
|
||||
-804
@@ -1,804 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.weaver.tools.PointcutParser;
|
||||
import org.aspectj.weaver.tools.PointcutPrimitive;
|
||||
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link ParameterNameDiscoverer} implementation that tries to deduce parameter names
|
||||
* for an advice method from the pointcut expression, returning, and throwing clauses.
|
||||
* If an unambiguous interpretation is not available, it returns <code>null</code>.
|
||||
*
|
||||
* <p>This class interprets arguments in the following way:
|
||||
* <ol>
|
||||
* <li>If the first parameter of the method is of type {@link JoinPoint}
|
||||
* or {@link ProceedingJoinPoint}, it is assumed to be for passing
|
||||
* <code>thisJoinPoint</code> to the advice, and the parameter name will
|
||||
* be assigned the value <code>"thisJoinPoint"</code>.</li>
|
||||
* <li>If the first parameter of the method is of type
|
||||
* <code>JoinPoint.StaticPart</code>, it is assumed to be for passing
|
||||
* <code>"thisJoinPointStaticPart"</code> to the advice, and the parameter name
|
||||
* will be assigned the value <code>"thisJoinPointStaticPart"</code>.</li>
|
||||
* <li>If a {@link #setThrowingName(String) throwingName} has been set, and
|
||||
* there are no unbound arguments of type <code>Throwable+</code>, then an
|
||||
* {@link IllegalArgumentException} is raised. If there is more than one
|
||||
* unbound argument of type <code>Throwable+</code>, then an
|
||||
* {@link AmbiguousBindingException} is raised. If there is exactly one
|
||||
* unbound argument of type <code>Throwable+</code>, then the corresponding
|
||||
* parameter name is assigned the value <throwingName>.</li>
|
||||
* <li>If there remain unbound arguments, then the pointcut expression is
|
||||
* examined. Let <code>a</code> be the number of annotation-based pointcut
|
||||
* expressions (@annotation, @this, @target, @args,
|
||||
* @within, @withincode) that are used in binding form. Usage in
|
||||
* binding form has itself to be deduced: if the expression inside the
|
||||
* pointcut is a single string literal that meets Java variable name
|
||||
* conventions it is assumed to be a variable name. If <code>a</code> is
|
||||
* zero we proceed to the next stage. If <code>a</code> > 1 then an
|
||||
* <code>AmbiguousBindingException</code> is raised. If <code>a</code> == 1,
|
||||
* and there are no unbound arguments of type <code>Annotation+</code>,
|
||||
* then an <code>IllegalArgumentException</code> is raised. if there is
|
||||
* exactly one such argument, then the corresponding parameter name is
|
||||
* assigned the value from the pointcut expression.</li>
|
||||
* <li>If a returningName has been set, and there are no unbound arguments
|
||||
* then an <code>IllegalArgumentException</code> is raised. If there is
|
||||
* more than one unbound argument then an
|
||||
* <code>AmbiguousBindingException</code> is raised. If there is exactly
|
||||
* one unbound argument then the corresponding parameter name is assigned
|
||||
* the value <returningName>.</li>
|
||||
* <li>If there remain unbound arguments, then the pointcut expression is
|
||||
* examined once more for <code>this</code>, <code>target</code>, and
|
||||
* <code>args</code> pointcut expressions used in the binding form (binding
|
||||
* forms are deduced as described for the annotation based pointcuts). If
|
||||
* there remains more than one unbound argument of a primitive type (which
|
||||
* can only be bound in <code>args</code>) then an
|
||||
* <code>AmbiguousBindingException</code> is raised. If there is exactly
|
||||
* one argument of a primitive type, then if exactly one <code>args</code>
|
||||
* bound variable was found, we assign the corresponding parameter name
|
||||
* the variable name. If there were no <code>args</code> bound variables
|
||||
* found an <code>IllegalStateException</code> is raised. If there are
|
||||
* multiple <code>args</code> bound variables, an
|
||||
* <code>AmbiguousBindingException</code> is raised. At this point, if
|
||||
* there remains more than one unbound argument we raise an
|
||||
* <code>AmbiguousBindingException</code>. If there are no unbound arguments
|
||||
* remaining, we are done. If there is exactly one unbound argument
|
||||
* remaining, and only one candidate variable name unbound from
|
||||
* <code>this</code>, <code>target</code>, or <code>args</code>, it is
|
||||
* assigned as the corresponding parameter name. If there are multiple
|
||||
* possibilities, an <code>AmbiguousBindingException</code> is raised.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>The behavior on raising an <code>IllegalArgumentException</code> or
|
||||
* <code>AmbiguousBindingException</code> is configurable to allow this discoverer
|
||||
* to be used as part of a chain-of-responsibility. By default the condition will
|
||||
* be logged and the <code>getParameterNames(..)</code> method will simply return
|
||||
* <code>null</code>. If the {@link #setRaiseExceptions(boolean) raiseExceptions}
|
||||
* property is set to <code>true</code>, the conditions will be thrown as
|
||||
* <code>IllegalArgumentException</code> and <code>AmbiguousBindingException</code>,
|
||||
* respectively.
|
||||
*
|
||||
* <p>Was that perfectly clear? ;)
|
||||
*
|
||||
* <p>Short version: If an unambiguous binding can be deduced, then it is.
|
||||
* If the advice requirements cannot possibly be satisfied, then <code>null</code>
|
||||
* is returned. By setting the {@link #setRaiseExceptions(boolean) raiseExceptions}
|
||||
* property to <code>true</code>, descriptive exceptions will be thrown instead of
|
||||
* returning <code>null</code> in the case that the parameter names cannot be discovered.
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscoverer {
|
||||
|
||||
private static final String THIS_JOIN_POINT = "thisJoinPoint";
|
||||
private static final String THIS_JOIN_POINT_STATIC_PART = "thisJoinPointStaticPart";
|
||||
|
||||
// Steps in the binding algorithm...
|
||||
private static final int STEP_JOIN_POINT_BINDING = 1;
|
||||
private static final int STEP_THROWING_BINDING = 2;
|
||||
private static final int STEP_ANNOTATION_BINDING = 3;
|
||||
private static final int STEP_RETURNING_BINDING = 4;
|
||||
private static final int STEP_PRIMITIVE_ARGS_BINDING = 5;
|
||||
private static final int STEP_THIS_TARGET_ARGS_BINDING = 6;
|
||||
private static final int STEP_REFERENCE_PCUT_BINDING = 7;
|
||||
private static final int STEP_FINISHED = 8;
|
||||
|
||||
private static final Set<String> singleValuedAnnotationPcds = new HashSet<String>();
|
||||
private static final Set<String> nonReferencePointcutTokens = new HashSet<String>();
|
||||
|
||||
|
||||
static {
|
||||
singleValuedAnnotationPcds.add("@this");
|
||||
singleValuedAnnotationPcds.add("@target");
|
||||
singleValuedAnnotationPcds.add("@within");
|
||||
singleValuedAnnotationPcds.add("@withincode");
|
||||
singleValuedAnnotationPcds.add("@annotation");
|
||||
|
||||
Set pointcutPrimitives = PointcutParser.getAllSupportedPointcutPrimitives();
|
||||
for (Iterator iterator = pointcutPrimitives.iterator(); iterator.hasNext();) {
|
||||
PointcutPrimitive primitive = (PointcutPrimitive) iterator.next();
|
||||
nonReferencePointcutTokens.add(primitive.getName());
|
||||
}
|
||||
nonReferencePointcutTokens.add("&&");
|
||||
nonReferencePointcutTokens.add("!");
|
||||
nonReferencePointcutTokens.add("||");
|
||||
nonReferencePointcutTokens.add("and");
|
||||
nonReferencePointcutTokens.add("or");
|
||||
nonReferencePointcutTokens.add("not");
|
||||
}
|
||||
|
||||
|
||||
private boolean raiseExceptions;
|
||||
|
||||
/**
|
||||
* If the advice is afterReturning, and binds the return value, this is the parameter name used.
|
||||
*/
|
||||
private String returningName;
|
||||
|
||||
/**
|
||||
* If the advice is afterThrowing, and binds the thrown value, this is the parameter name used.
|
||||
*/
|
||||
private String throwingName;
|
||||
|
||||
/**
|
||||
* The pointcut expression associated with the advice, as a simple String.
|
||||
*/
|
||||
private String pointcutExpression;
|
||||
|
||||
private Class[] argumentTypes;
|
||||
|
||||
private String[] parameterNameBindings;
|
||||
|
||||
private int numberOfRemainingUnboundArguments;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new discoverer that attempts to discover parameter names
|
||||
* from the given pointcut expression.
|
||||
*/
|
||||
public AspectJAdviceParameterNameDiscoverer(String pointcutExpression) {
|
||||
this.pointcutExpression = pointcutExpression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether {@link IllegalArgumentException} and {@link AmbiguousBindingException}
|
||||
* must be thrown as appropriate in the case of failing to deduce advice parameter names.
|
||||
* @param raiseExceptions <code>true</code> if exceptions are to be thrown
|
||||
*/
|
||||
public void setRaiseExceptions(boolean raiseExceptions) {
|
||||
this.raiseExceptions = raiseExceptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* If <code>afterReturning</code> advice binds the return value, the
|
||||
* returning variable name must be specified.
|
||||
* @param returningName the name of the returning variable
|
||||
*/
|
||||
public void setReturningName(String returningName) {
|
||||
this.returningName = returningName;
|
||||
}
|
||||
|
||||
/**
|
||||
* If <code>afterThrowing</code> advice binds the thrown value, the
|
||||
* throwing variable name must be specified.
|
||||
* @param throwingName the name of the throwing variable
|
||||
*/
|
||||
public void setThrowingName(String throwingName) {
|
||||
this.throwingName = throwingName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deduce the parameter names for an advice method.
|
||||
* <p>See the {@link AspectJAdviceParameterNameDiscoverer class level javadoc}
|
||||
* for this class for details of the algorithm used.
|
||||
* @param method the target {@link Method}
|
||||
* @return the parameter names
|
||||
*/
|
||||
public String[] getParameterNames(Method method) {
|
||||
this.argumentTypes = method.getParameterTypes();
|
||||
this.numberOfRemainingUnboundArguments = this.argumentTypes.length;
|
||||
this.parameterNameBindings = new String[this.numberOfRemainingUnboundArguments];
|
||||
|
||||
int minimumNumberUnboundArgs = 0;
|
||||
if (this.returningName != null) {
|
||||
minimumNumberUnboundArgs++;
|
||||
}
|
||||
if (this.throwingName != null) {
|
||||
minimumNumberUnboundArgs++;
|
||||
}
|
||||
if (this.numberOfRemainingUnboundArguments < minimumNumberUnboundArgs) {
|
||||
throw new IllegalStateException(
|
||||
"Not enough arguments in method to satisfy binding of returning and throwing variables");
|
||||
}
|
||||
|
||||
try {
|
||||
int algorithmicStep = STEP_JOIN_POINT_BINDING;
|
||||
while ((this.numberOfRemainingUnboundArguments > 0) && algorithmicStep < STEP_FINISHED) {
|
||||
switch (algorithmicStep++) {
|
||||
case STEP_JOIN_POINT_BINDING:
|
||||
if (!maybeBindThisJoinPoint()) {
|
||||
maybeBindThisJoinPointStaticPart();
|
||||
}
|
||||
break;
|
||||
case STEP_THROWING_BINDING:
|
||||
maybeBindThrowingVariable();
|
||||
break;
|
||||
case STEP_ANNOTATION_BINDING:
|
||||
maybeBindAnnotationsFromPointcutExpression();
|
||||
break;
|
||||
case STEP_RETURNING_BINDING:
|
||||
maybeBindReturningVariable();
|
||||
break;
|
||||
case STEP_PRIMITIVE_ARGS_BINDING:
|
||||
maybeBindPrimitiveArgsFromPointcutExpression();
|
||||
break;
|
||||
case STEP_THIS_TARGET_ARGS_BINDING:
|
||||
maybeBindThisOrTargetOrArgsFromPointcutExpression();
|
||||
break;
|
||||
case STEP_REFERENCE_PCUT_BINDING:
|
||||
maybeBindReferencePointcutParameter();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown algorithmic step: " + (algorithmicStep - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (AmbiguousBindingException ambigEx) {
|
||||
if (this.raiseExceptions) {
|
||||
throw ambigEx;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
if (this.raiseExceptions) {
|
||||
throw ex;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.numberOfRemainingUnboundArguments == 0) {
|
||||
return this.parameterNameBindings;
|
||||
}
|
||||
else {
|
||||
if (this.raiseExceptions) {
|
||||
throw new IllegalStateException("Failed to bind all argument names: " +
|
||||
this.numberOfRemainingUnboundArguments + " argument(s) could not be bound");
|
||||
}
|
||||
else {
|
||||
// convention for failing is to return null, allowing participation in a chain of responsibility
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An advice method can never be a constructor in Spring.
|
||||
* @return <code>null</code>
|
||||
* @throws UnsupportedOperationException if
|
||||
* {@link #setRaiseExceptions(boolean) raiseExceptions} has been set to <code>true</code>
|
||||
*/
|
||||
public String[] getParameterNames(Constructor ctor) {
|
||||
if (this.raiseExceptions) {
|
||||
throw new UnsupportedOperationException("An advice method can never be a constructor");
|
||||
}
|
||||
else {
|
||||
// we return null rather than throw an exception so that we behave well
|
||||
// in a chain-of-responsibility.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void bindParameterName(int index, String name) {
|
||||
this.parameterNameBindings[index] = name;
|
||||
this.numberOfRemainingUnboundArguments--;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the first parameter is of type JoinPoint or ProceedingJoinPoint,bind "thisJoinPoint" as
|
||||
* parameter name and return true, else return false.
|
||||
*/
|
||||
private boolean maybeBindThisJoinPoint() {
|
||||
if ((this.argumentTypes[0] == JoinPoint.class) || (this.argumentTypes[0] == ProceedingJoinPoint.class)) {
|
||||
bindParameterName(0, THIS_JOIN_POINT);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void maybeBindThisJoinPointStaticPart() {
|
||||
if (this.argumentTypes[0] == JoinPoint.StaticPart.class) {
|
||||
bindParameterName(0, THIS_JOIN_POINT_STATIC_PART);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If a throwing name was specified and there is exactly one choice remaining
|
||||
* (argument that is a subtype of Throwable) then bind it.
|
||||
*/
|
||||
private void maybeBindThrowingVariable() {
|
||||
if (this.throwingName == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// So there is binding work to do...
|
||||
int throwableIndex = -1;
|
||||
for (int i = 0; i < this.argumentTypes.length; i++) {
|
||||
if (isUnbound(i) && isSubtypeOf(Throwable.class, i)) {
|
||||
if (throwableIndex == -1) {
|
||||
throwableIndex = i;
|
||||
}
|
||||
else {
|
||||
// Second candidate we've found - ambiguous binding
|
||||
throw new AmbiguousBindingException("Binding of throwing parameter '" +
|
||||
this.throwingName + "' is ambiguous: could be bound to argument " +
|
||||
throwableIndex + " or argument " + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (throwableIndex == -1) {
|
||||
throw new IllegalStateException("Binding of throwing parameter '" + this.throwingName
|
||||
+ "' could not be completed as no available arguments are a subtype of Throwable");
|
||||
}
|
||||
else {
|
||||
bindParameterName(throwableIndex, this.throwingName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If a returning variable was specified and there is only one choice remaining, bind it.
|
||||
*/
|
||||
private void maybeBindReturningVariable() {
|
||||
if (this.numberOfRemainingUnboundArguments == 0) {
|
||||
throw new IllegalStateException(
|
||||
"Algorithm assumes that there must be at least one unbound parameter on entry to this method");
|
||||
}
|
||||
|
||||
if (this.returningName != null) {
|
||||
if (this.numberOfRemainingUnboundArguments > 1) {
|
||||
throw new AmbiguousBindingException("Binding of returning parameter '" + this.returningName +
|
||||
"' is ambiguous, there are " + this.numberOfRemainingUnboundArguments + " candidates.");
|
||||
}
|
||||
|
||||
// We're all set... find the unbound parameter, and bind it.
|
||||
for (int i = 0; i < this.parameterNameBindings.length; i++) {
|
||||
if (this.parameterNameBindings[i] == null) {
|
||||
bindParameterName(i, this.returningName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse the string pointcut expression looking for:
|
||||
* @this, @target, @args, @within, @withincode, @annotation.
|
||||
* If we find one of these pointcut expressions, try and extract a candidate variable
|
||||
* name (or variable names, in the case of args).
|
||||
* <p>Some more support from AspectJ in doing this exercise would be nice... :)
|
||||
*/
|
||||
private void maybeBindAnnotationsFromPointcutExpression() {
|
||||
List<String> varNames = new ArrayList<String>();
|
||||
String[] tokens = StringUtils.tokenizeToStringArray(this.pointcutExpression, " ");
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
String toMatch = tokens[i];
|
||||
int firstParenIndex = toMatch.indexOf("(");
|
||||
if (firstParenIndex != -1) {
|
||||
toMatch = toMatch.substring(0, firstParenIndex);
|
||||
}
|
||||
if (singleValuedAnnotationPcds.contains(toMatch)) {
|
||||
PointcutBody body = getPointcutBody(tokens, i);
|
||||
i += body.numTokensConsumed;
|
||||
String varName = maybeExtractVariableName(body.text);
|
||||
if (varName != null) {
|
||||
varNames.add(varName);
|
||||
}
|
||||
}
|
||||
else if (tokens[i].startsWith("@args(") || tokens[i].equals("@args")) {
|
||||
PointcutBody body = getPointcutBody(tokens, i);
|
||||
i += body.numTokensConsumed;
|
||||
maybeExtractVariableNamesFromArgs(body.text, varNames);
|
||||
}
|
||||
}
|
||||
|
||||
bindAnnotationsFromVarNames(varNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the given list of extracted variable names to argument slots.
|
||||
*/
|
||||
private void bindAnnotationsFromVarNames(List<String> varNames) {
|
||||
if (!varNames.isEmpty()) {
|
||||
// we have work to do...
|
||||
int numAnnotationSlots = countNumberOfUnboundAnnotationArguments();
|
||||
if (numAnnotationSlots > 1) {
|
||||
throw new AmbiguousBindingException("Found " + varNames.size() +
|
||||
" potential annotation variable(s), and " +
|
||||
numAnnotationSlots + " potential argument slots");
|
||||
}
|
||||
else if (numAnnotationSlots == 1) {
|
||||
if (varNames.size() == 1) {
|
||||
// it's a match
|
||||
findAndBind(Annotation.class, varNames.get(0));
|
||||
}
|
||||
else {
|
||||
// multiple candidate vars, but only one slot
|
||||
throw new IllegalArgumentException("Found " + varNames.size() +
|
||||
" candidate annotation binding variables" +
|
||||
" but only one potential argument binding slot");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no slots so presume those candidate vars were actually type names
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the token starts meets Java identifier conventions, it's in.
|
||||
*/
|
||||
private String maybeExtractVariableName(String candidateToken) {
|
||||
if (candidateToken == null || candidateToken.equals("")) {
|
||||
return null;
|
||||
}
|
||||
if (Character.isJavaIdentifierStart(candidateToken.charAt(0)) &&
|
||||
Character.isLowerCase(candidateToken.charAt(0))) {
|
||||
char[] tokenChars = candidateToken.toCharArray();
|
||||
for (char tokenChar : tokenChars) {
|
||||
if (!Character.isJavaIdentifierPart(tokenChar)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return candidateToken;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an args pointcut body (could be <code>args</code> or <code>at_args</code>),
|
||||
* add any candidate variable names to the given list.
|
||||
*/
|
||||
private void maybeExtractVariableNamesFromArgs(String argsSpec, List<String> varNames) {
|
||||
if (argsSpec == null) {
|
||||
return;
|
||||
}
|
||||
String[] tokens = StringUtils.tokenizeToStringArray(argsSpec, ",");
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
tokens[i] = StringUtils.trimWhitespace(tokens[i]);
|
||||
String varName = maybeExtractVariableName(tokens[i]);
|
||||
if (varName != null) {
|
||||
varNames.add(varName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the string pointcut expression looking for this(), target() and args() expressions.
|
||||
* If we find one, try and extract a candidate variable name and bind it.
|
||||
*/
|
||||
private void maybeBindThisOrTargetOrArgsFromPointcutExpression() {
|
||||
if (this.numberOfRemainingUnboundArguments > 1) {
|
||||
throw new AmbiguousBindingException("Still " + this.numberOfRemainingUnboundArguments
|
||||
+ " unbound args at this(),target(),args() binding stage, with no way to determine between them");
|
||||
}
|
||||
|
||||
List<String> varNames = new ArrayList<String>();
|
||||
String[] tokens = StringUtils.tokenizeToStringArray(this.pointcutExpression, " ");
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
if (tokens[i].equals("this") ||
|
||||
tokens[i].startsWith("this(") ||
|
||||
tokens[i].equals("target") ||
|
||||
tokens[i].startsWith("target(")) {
|
||||
PointcutBody body = getPointcutBody(tokens, i);
|
||||
i += body.numTokensConsumed;
|
||||
String varName = maybeExtractVariableName(body.text);
|
||||
if (varName != null) {
|
||||
varNames.add(varName);
|
||||
}
|
||||
}
|
||||
else if (tokens[i].equals("args") || tokens[i].startsWith("args(")) {
|
||||
PointcutBody body = getPointcutBody(tokens, i);
|
||||
i += body.numTokensConsumed;
|
||||
List<String> candidateVarNames = new ArrayList<String>();
|
||||
maybeExtractVariableNamesFromArgs(body.text, candidateVarNames);
|
||||
// we may have found some var names that were bound in previous primitive args binding step,
|
||||
// filter them out...
|
||||
for (String varName : candidateVarNames) {
|
||||
if (!alreadyBound(varName)) {
|
||||
varNames.add(varName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (varNames.size() > 1) {
|
||||
throw new AmbiguousBindingException("Found " + varNames.size() +
|
||||
" candidate this(), target() or args() variables but only one unbound argument slot");
|
||||
}
|
||||
else if (varNames.size() == 1) {
|
||||
for (int j = 0; j < this.parameterNameBindings.length; j++) {
|
||||
if (isUnbound(j)) {
|
||||
bindParameterName(j, varNames.get(0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// else varNames.size must be 0 and we have nothing to bind.
|
||||
}
|
||||
|
||||
private void maybeBindReferencePointcutParameter() {
|
||||
if (this.numberOfRemainingUnboundArguments > 1) {
|
||||
throw new AmbiguousBindingException("Still " + this.numberOfRemainingUnboundArguments
|
||||
+ " unbound args at reference pointcut binding stage, with no way to determine between them");
|
||||
}
|
||||
|
||||
List<String> varNames = new ArrayList<String>();
|
||||
String[] tokens = StringUtils.tokenizeToStringArray(this.pointcutExpression, " ");
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
String toMatch = tokens[i];
|
||||
if (toMatch.startsWith("!")) {
|
||||
toMatch = toMatch.substring(1);
|
||||
}
|
||||
int firstParenIndex = toMatch.indexOf("(");
|
||||
if (firstParenIndex != -1) {
|
||||
toMatch = toMatch.substring(0, firstParenIndex);
|
||||
}
|
||||
else {
|
||||
if (tokens.length < i + 2) {
|
||||
// no "(" and nothing following
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
String nextToken = tokens[i + 1];
|
||||
if (nextToken.charAt(0) != '(') {
|
||||
// next token is not "(" either, can't be a pc...
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// eat the body
|
||||
PointcutBody body = getPointcutBody(tokens, i);
|
||||
i += body.numTokensConsumed;
|
||||
|
||||
if (!nonReferencePointcutTokens.contains(toMatch)) {
|
||||
// then it could be a reference pointcut
|
||||
String varName = maybeExtractVariableName(body.text);
|
||||
if (varName != null) {
|
||||
varNames.add(varName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (varNames.size() > 1) {
|
||||
throw new AmbiguousBindingException("Found " + varNames.size() +
|
||||
" candidate reference pointcut variables but only one unbound argument slot");
|
||||
}
|
||||
else if (varNames.size() == 1) {
|
||||
for (int j = 0; j < this.parameterNameBindings.length; j++) {
|
||||
if (isUnbound(j)) {
|
||||
bindParameterName(j, varNames.get(0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// else varNames.size must be 0 and we have nothing to bind.
|
||||
}
|
||||
|
||||
/*
|
||||
* We've found the start of a binding pointcut at the given index into the
|
||||
* token array. Now we need to extract the pointcut body and return it.
|
||||
*/
|
||||
private PointcutBody getPointcutBody(String[] tokens, int startIndex) {
|
||||
int numTokensConsumed = 0;
|
||||
String currentToken = tokens[startIndex];
|
||||
int bodyStart = currentToken.indexOf('(');
|
||||
if (currentToken.charAt(currentToken.length() - 1) == ')') {
|
||||
// It's an all in one... get the text between the first (and the last)
|
||||
return new PointcutBody(0, currentToken.substring(bodyStart + 1, currentToken.length() - 1));
|
||||
}
|
||||
else {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (bodyStart >= 0 && bodyStart != (currentToken.length() - 1)) {
|
||||
sb.append(currentToken.substring(bodyStart + 1));
|
||||
sb.append(" ");
|
||||
}
|
||||
numTokensConsumed++;
|
||||
int currentIndex = startIndex + numTokensConsumed;
|
||||
while (currentIndex < tokens.length) {
|
||||
if (tokens[currentIndex].equals("(")) {
|
||||
currentIndex++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tokens[currentIndex].endsWith(")")) {
|
||||
sb.append(tokens[currentIndex].substring(0, tokens[currentIndex].length() - 1));
|
||||
return new PointcutBody(numTokensConsumed, sb.toString().trim());
|
||||
}
|
||||
|
||||
String toAppend = tokens[currentIndex];
|
||||
if (toAppend.startsWith("(")) {
|
||||
toAppend = toAppend.substring(1);
|
||||
}
|
||||
sb.append(toAppend);
|
||||
sb.append(" ");
|
||||
currentIndex++;
|
||||
numTokensConsumed++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// We looked and failed...
|
||||
return new PointcutBody(numTokensConsumed, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Match up args against unbound arguments of primitive types
|
||||
*/
|
||||
private void maybeBindPrimitiveArgsFromPointcutExpression() {
|
||||
int numUnboundPrimitives = countNumberOfUnboundPrimitiveArguments();
|
||||
if (numUnboundPrimitives > 1) {
|
||||
throw new AmbiguousBindingException("Found '" + numUnboundPrimitives +
|
||||
"' unbound primitive arguments with no way to distinguish between them.");
|
||||
}
|
||||
if (numUnboundPrimitives == 1) {
|
||||
// Look for arg variable and bind it if we find exactly one...
|
||||
List<String> varNames = new ArrayList<String>();
|
||||
String[] tokens = StringUtils.tokenizeToStringArray(this.pointcutExpression, " ");
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
if (tokens[i].equals("args") || tokens[i].startsWith("args(")) {
|
||||
PointcutBody body = getPointcutBody(tokens, i);
|
||||
i += body.numTokensConsumed;
|
||||
maybeExtractVariableNamesFromArgs(body.text, varNames);
|
||||
}
|
||||
}
|
||||
if (varNames.size() > 1) {
|
||||
throw new AmbiguousBindingException("Found " + varNames.size() +
|
||||
" candidate variable names but only one candidate binding slot when matching primitive args");
|
||||
}
|
||||
else if (varNames.size() == 1) {
|
||||
// 1 primitive arg, and one candidate...
|
||||
for (int i = 0; i < this.argumentTypes.length; i++) {
|
||||
if (isUnbound(i) && this.argumentTypes[i].isPrimitive()) {
|
||||
bindParameterName(i, (String) varNames.get(0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if the parameter name binding for the given parameter
|
||||
* index has not yet been assigned.
|
||||
*/
|
||||
private boolean isUnbound(int i) {
|
||||
return this.parameterNameBindings[i] == null;
|
||||
}
|
||||
|
||||
private boolean alreadyBound(String varName) {
|
||||
for (int i = 0; i < this.parameterNameBindings.length; i++) {
|
||||
if (!isUnbound(i) && varName.equals(this.parameterNameBindings[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return <code>true</code> if the given argument type is a subclass
|
||||
* of the given supertype.
|
||||
*/
|
||||
private boolean isSubtypeOf(Class supertype, int argumentNumber) {
|
||||
return supertype.isAssignableFrom(this.argumentTypes[argumentNumber]);
|
||||
}
|
||||
|
||||
private int countNumberOfUnboundAnnotationArguments() {
|
||||
int count = 0;
|
||||
for (int i = 0; i < this.argumentTypes.length; i++) {
|
||||
if (isUnbound(i) && isSubtypeOf(Annotation.class, i)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private int countNumberOfUnboundPrimitiveArguments() {
|
||||
int count = 0;
|
||||
for (int i = 0; i < this.argumentTypes.length; i++) {
|
||||
if (isUnbound(i) && this.argumentTypes[i].isPrimitive()) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the argument index with the given type, and bind the given
|
||||
* <code>varName</code> in that position.
|
||||
*/
|
||||
private void findAndBind(Class argumentType, String varName) {
|
||||
for (int i = 0; i < this.argumentTypes.length; i++) {
|
||||
if (isUnbound(i) && isSubtypeOf(argumentType, i)) {
|
||||
bindParameterName(i, varName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("Expected to find an unbound argument of type '" +
|
||||
argumentType.getName() + "'");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Simple struct to hold the extracted text from a pointcut body, together
|
||||
* with the number of tokens consumed in extracting it.
|
||||
*/
|
||||
private static class PointcutBody {
|
||||
|
||||
private int numTokensConsumed;
|
||||
|
||||
private String text;
|
||||
|
||||
public PointcutBody(int tokens, String text) {
|
||||
this.numTokensConsumed = tokens;
|
||||
this.text = text;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thrown in response to an ambiguous binding being detected when
|
||||
* trying to resolve a method's parameter names.
|
||||
*/
|
||||
public static class AmbiguousBindingException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Construct a new AmbiguousBindingException with the specified message.
|
||||
* @param msg the detail message
|
||||
*/
|
||||
public AmbiguousBindingException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-57
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.aop.AfterAdvice;
|
||||
|
||||
/**
|
||||
* Spring AOP advice wrapping an AspectJ after advice method.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice {
|
||||
|
||||
public AspectJAfterAdvice(
|
||||
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
|
||||
|
||||
super(aspectJBeforeAdviceMethod, pointcut, aif);
|
||||
}
|
||||
|
||||
public Object invoke(MethodInvocation mi) throws Throwable {
|
||||
try {
|
||||
return mi.proceed();
|
||||
}
|
||||
finally {
|
||||
invokeAdviceMethod(getJoinPointMatch(), null, null);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isBeforeAdvice() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isAfterAdvice() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
-89
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import org.springframework.aop.AfterAdvice;
|
||||
import org.springframework.aop.AfterReturningAdvice;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.TypeUtils;
|
||||
|
||||
/**
|
||||
* Spring AOP advice wrapping an AspectJ after-returning advice method.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice implements AfterReturningAdvice, AfterAdvice {
|
||||
|
||||
public AspectJAfterReturningAdvice(
|
||||
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
|
||||
|
||||
super(aspectJBeforeAdviceMethod, pointcut, aif);
|
||||
}
|
||||
|
||||
public boolean isBeforeAdvice() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isAfterAdvice() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReturningName(String name) {
|
||||
setReturningNameNoCheck(name);
|
||||
}
|
||||
|
||||
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
|
||||
if (shouldInvokeOnReturnValueOf(method, returnValue)) {
|
||||
invokeAdviceMethod(getJoinPointMatch(), returnValue, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Following AspectJ semantics, if a returning clause was specified, then the
|
||||
* advice is only invoked if the returned value is an instance of the given
|
||||
* returning type and generic type parameters, if any, match the assignment
|
||||
* rules. If the returning type is Object, the advice is *always* invoked.
|
||||
* @param returnValue the return value of the target method
|
||||
* @return whether to invoke the advice method for the given return value
|
||||
*/
|
||||
private boolean shouldInvokeOnReturnValueOf(Method method, Object returnValue) {
|
||||
Class type = getDiscoveredReturningType();
|
||||
Object genericType = getDiscoveredReturningGenericType();
|
||||
// If we aren't dealing with a raw type, check if generic parameters are assignable.
|
||||
return (ClassUtils.isAssignableValue(type, returnValue) &&
|
||||
(genericType == null || genericType == type || GenericTypeMatcher.isAssignable(genericType, method)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner class to avoid a static JDK 1.5 dependency for generic type matching.
|
||||
*/
|
||||
private static class GenericTypeMatcher {
|
||||
|
||||
public static boolean isAssignable(Object genericType, Method method) {
|
||||
return TypeUtils.isAssignable((Type) genericType, method.getGenericReturnType());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-74
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.aop.AfterAdvice;
|
||||
|
||||
/**
|
||||
* Spring AOP advice wrapping an AspectJ after-throwing advice method.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice {
|
||||
|
||||
public AspectJAfterThrowingAdvice(
|
||||
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
|
||||
|
||||
super(aspectJBeforeAdviceMethod, pointcut, aif);
|
||||
}
|
||||
|
||||
public boolean isBeforeAdvice() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isAfterAdvice() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThrowingName(String name) {
|
||||
setThrowingNameNoCheck(name);
|
||||
}
|
||||
|
||||
public Object invoke(MethodInvocation mi) throws Throwable {
|
||||
try {
|
||||
return mi.proceed();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
if (shouldInvokeOnThrowing(t)) {
|
||||
invokeAdviceMethod(getJoinPointMatch(), null, t);
|
||||
}
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In AspectJ semantics, after throwing advice that specifies a throwing clause
|
||||
* is only invoked if the thrown exception is a subtype of the given throwing type.
|
||||
*/
|
||||
private boolean shouldInvokeOnThrowing(Throwable t) {
|
||||
Class throwingType = getDiscoveredThrowingType();
|
||||
return throwingType.isAssignableFrom(t.getClass());
|
||||
}
|
||||
|
||||
}
|
||||
-72
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.AfterAdvice;
|
||||
import org.springframework.aop.BeforeAdvice;
|
||||
|
||||
/**
|
||||
* Utility methods for dealing with AspectJ advisors.
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class AspectJAopUtils {
|
||||
|
||||
/**
|
||||
* Return <code>true</code> if the advisor is a form of before advice.
|
||||
*/
|
||||
public static boolean isBeforeAdvice(Advisor anAdvisor) {
|
||||
AspectJPrecedenceInformation precedenceInfo = getAspectJPrecedenceInformationFor(anAdvisor);
|
||||
if (precedenceInfo != null) {
|
||||
return precedenceInfo.isBeforeAdvice();
|
||||
}
|
||||
return (anAdvisor.getAdvice() instanceof BeforeAdvice);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return <code>true</code> if the advisor is a form of after advice.
|
||||
*/
|
||||
public static boolean isAfterAdvice(Advisor anAdvisor) {
|
||||
AspectJPrecedenceInformation precedenceInfo = getAspectJPrecedenceInformationFor(anAdvisor);
|
||||
if (precedenceInfo != null) {
|
||||
return precedenceInfo.isAfterAdvice();
|
||||
}
|
||||
return (anAdvisor.getAdvice() instanceof AfterAdvice);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the AspectJPrecedenceInformation provided by this advisor or its advice.
|
||||
* If neither the advisor nor the advice have precedence information, this method
|
||||
* will return <code>null</code>.
|
||||
*/
|
||||
public static AspectJPrecedenceInformation getAspectJPrecedenceInformationFor(Advisor anAdvisor) {
|
||||
if (anAdvisor instanceof AspectJPrecedenceInformation) {
|
||||
return (AspectJPrecedenceInformation) anAdvisor;
|
||||
}
|
||||
Advice advice = anAdvisor.getAdvice();
|
||||
if (advice instanceof AspectJPrecedenceInformation) {
|
||||
return (AspectJPrecedenceInformation) advice;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
-79
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.weaver.tools.JoinPointMatch;
|
||||
|
||||
import org.springframework.aop.ProxyMethodInvocation;
|
||||
|
||||
/**
|
||||
* Spring AOP around advice (MethodInterceptor) that wraps
|
||||
* an AspectJ advice method. Exposes ProceedingJoinPoint.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor {
|
||||
|
||||
public AspectJAroundAdvice(
|
||||
Method aspectJAroundAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
|
||||
|
||||
super(aspectJAroundAdviceMethod, pointcut, aif);
|
||||
}
|
||||
|
||||
public boolean isBeforeAdvice() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isAfterAdvice() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsProceedingJoinPoint() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public Object invoke(MethodInvocation mi) throws Throwable {
|
||||
if (!(mi instanceof ProxyMethodInvocation)) {
|
||||
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
|
||||
}
|
||||
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
|
||||
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
|
||||
JoinPointMatch jpm = getJoinPointMatch(pmi);
|
||||
return invokeAdviceMethod(pjp, jpm, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ProceedingJoinPoint for the current invocation,
|
||||
* instantiating it lazily if it hasn't been bound to the thread already.
|
||||
* @param rmi the current Spring AOP ReflectiveMethodInvocation,
|
||||
* which we'll use for attribute binding
|
||||
* @return the ProceedingJoinPoint to make available to advice methods
|
||||
*/
|
||||
protected ProceedingJoinPoint lazyGetProceedingJoinPoint(ProxyMethodInvocation rmi) {
|
||||
return new MethodInvocationProceedingJoinPoint(rmi);
|
||||
}
|
||||
|
||||
}
|
||||
-533
@@ -1,533 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.aspectj.weaver.BCException;
|
||||
import org.aspectj.weaver.patterns.NamePattern;
|
||||
import org.aspectj.weaver.reflect.ReflectionWorld;
|
||||
import org.aspectj.weaver.tools.ContextBasedMatcher;
|
||||
import org.aspectj.weaver.tools.FuzzyBoolean;
|
||||
import org.aspectj.weaver.tools.JoinPointMatch;
|
||||
import org.aspectj.weaver.tools.MatchingContext;
|
||||
import org.aspectj.weaver.tools.PointcutDesignatorHandler;
|
||||
import org.aspectj.weaver.tools.PointcutExpression;
|
||||
import org.aspectj.weaver.tools.PointcutParameter;
|
||||
import org.aspectj.weaver.tools.PointcutParser;
|
||||
import org.aspectj.weaver.tools.PointcutPrimitive;
|
||||
import org.aspectj.weaver.tools.ShadowMatch;
|
||||
|
||||
import org.springframework.aop.ClassFilter;
|
||||
import org.springframework.aop.IntroductionAwareMethodMatcher;
|
||||
import org.springframework.aop.MethodMatcher;
|
||||
import org.springframework.aop.ProxyMethodInvocation;
|
||||
import org.springframework.aop.framework.autoproxy.ProxyCreationContext;
|
||||
import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
|
||||
import org.springframework.aop.support.AbstractExpressionPointcut;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Spring {@link org.springframework.aop.Pointcut} implementation
|
||||
* that uses the AspectJ weaver to evaluate a pointcut expression.
|
||||
*
|
||||
* <p>The pointcut expression value is an AspectJ expression. This can
|
||||
* reference other pointcuts and use composition and other operations.
|
||||
*
|
||||
* <p>Naturally, as this is to be processed by Spring AOP's proxy-based model,
|
||||
* only method execution pointcuts are supported.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Adrian Colyer
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware {
|
||||
|
||||
private static final Set<PointcutPrimitive> DEFAULT_SUPPORTED_PRIMITIVES = new HashSet<PointcutPrimitive>();
|
||||
|
||||
static {
|
||||
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
|
||||
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.ARGS);
|
||||
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.REFERENCE);
|
||||
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.THIS);
|
||||
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.TARGET);
|
||||
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.WITHIN);
|
||||
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ANNOTATION);
|
||||
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_WITHIN);
|
||||
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ARGS);
|
||||
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_TARGET);
|
||||
}
|
||||
|
||||
|
||||
private static final Log logger = LogFactory.getLog(AspectJExpressionPointcut.class);
|
||||
|
||||
private final Map<Method, ShadowMatch> shadowMatchCache = new HashMap<Method, ShadowMatch>();
|
||||
|
||||
private PointcutParser pointcutParser;
|
||||
|
||||
private Class pointcutDeclarationScope;
|
||||
|
||||
private String[] pointcutParameterNames = new String[0];
|
||||
|
||||
private Class[] pointcutParameterTypes = new Class[0];
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private PointcutExpression pointcutExpression;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new default AspectJExpressionPointcut.
|
||||
*/
|
||||
public AspectJExpressionPointcut() {
|
||||
this(DEFAULT_SUPPORTED_PRIMITIVES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new AspectJExpressionPointcut with the given supported primitives.
|
||||
* @param supportedPrimitives Set of {@link org.aspectj.weaver.tools.PointcutPrimitive}
|
||||
* instances
|
||||
*/
|
||||
public AspectJExpressionPointcut(Set supportedPrimitives) {
|
||||
this.pointcutParser =
|
||||
PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(
|
||||
supportedPrimitives);
|
||||
this.pointcutParser.registerPointcutDesignatorHandler(new BeanNamePointcutDesignatorHandler());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new AspectJExpressionPointcut with the given settings.
|
||||
* @param declarationScope the declaration scope for the pointcut
|
||||
* @param paramNames the parameter names for the pointcut
|
||||
* @param paramTypes the parameter types for the pointcut
|
||||
*/
|
||||
public AspectJExpressionPointcut(Class declarationScope, String[] paramNames, Class[] paramTypes) {
|
||||
this(DEFAULT_SUPPORTED_PRIMITIVES);
|
||||
this.pointcutDeclarationScope = declarationScope;
|
||||
if (paramNames.length != paramTypes.length) {
|
||||
throw new IllegalStateException(
|
||||
"Number of pointcut parameter names must match number of pointcut parameter types");
|
||||
}
|
||||
this.pointcutParameterNames = paramNames;
|
||||
this.pointcutParameterTypes = paramTypes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the declaration scope for the pointcut.
|
||||
*/
|
||||
public void setPointcutDeclarationScope(Class pointcutDeclarationScope) {
|
||||
this.pointcutDeclarationScope = pointcutDeclarationScope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the parameter names for the pointcut.
|
||||
*/
|
||||
public void setParameterNames(String[] names) {
|
||||
this.pointcutParameterNames = names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the parameter types for the pointcut.
|
||||
*/
|
||||
public void setParameterTypes(Class[] types) {
|
||||
this.pointcutParameterTypes = types;
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
|
||||
public ClassFilter getClassFilter() {
|
||||
checkReadyToMatch();
|
||||
return this;
|
||||
}
|
||||
|
||||
public MethodMatcher getMethodMatcher() {
|
||||
checkReadyToMatch();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check whether this pointcut is ready to match,
|
||||
* lazily building the underlying AspectJ pointcut expression.
|
||||
*/
|
||||
private void checkReadyToMatch() {
|
||||
if (getExpression() == null) {
|
||||
throw new IllegalStateException("Must set property 'expression' before attempting to match");
|
||||
}
|
||||
if (this.pointcutExpression == null) {
|
||||
this.pointcutExpression = buildPointcutExpression();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the underlying AspectJ pointcut expression.
|
||||
*/
|
||||
private PointcutExpression buildPointcutExpression() {
|
||||
PointcutParameter[] pointcutParameters = new PointcutParameter[this.pointcutParameterNames.length];
|
||||
for (int i = 0; i < pointcutParameters.length; i++) {
|
||||
pointcutParameters[i] = this.pointcutParser.createPointcutParameter(
|
||||
this.pointcutParameterNames[i], this.pointcutParameterTypes[i]);
|
||||
}
|
||||
return this.pointcutParser.parsePointcutExpression(
|
||||
replaceBooleanOperators(getExpression()), this.pointcutDeclarationScope, pointcutParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* If a pointcut expression has been specified in XML, the user cannot
|
||||
* write <code>and</code> as "&&" (though && will work).
|
||||
* We also allow <code>and</code> between two pointcut sub-expressions.
|
||||
* <p>This method converts back to <code>&&</code> for the AspectJ pointcut parser.
|
||||
*/
|
||||
private String replaceBooleanOperators(String pcExpr) {
|
||||
pcExpr = StringUtils.replace(pcExpr," and "," && ");
|
||||
pcExpr = StringUtils.replace(pcExpr, " or ", " || ");
|
||||
pcExpr = StringUtils.replace(pcExpr, " not ", " ! ");
|
||||
return pcExpr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying AspectJ pointcut expression.
|
||||
*/
|
||||
public PointcutExpression getPointcutExpression() {
|
||||
checkReadyToMatch();
|
||||
return this.pointcutExpression;
|
||||
}
|
||||
|
||||
|
||||
public boolean matches(Class targetClass) {
|
||||
checkReadyToMatch();
|
||||
try {
|
||||
return this.pointcutExpression.couldMatchJoinPointsInType(targetClass);
|
||||
}
|
||||
catch (BCException ex) {
|
||||
logger.debug("PointcutExpression matching rejected target class", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean matches(Method method, Class targetClass, boolean beanHasIntroductions) {
|
||||
checkReadyToMatch();
|
||||
Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
|
||||
ShadowMatch shadowMatch = null;
|
||||
try {
|
||||
shadowMatch = getShadowMatch(targetMethod, method);
|
||||
}
|
||||
catch (ReflectionWorld.ReflectionWorldException ex) {
|
||||
// Could neither introspect the target class nor the proxy class ->
|
||||
// let's simply consider this method as non-matching.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Special handling for this, target, @this, @target, @annotation
|
||||
// in Spring - we can optimize since we know we have exactly this class,
|
||||
// and there will never be matching subclass at runtime.
|
||||
if (shadowMatch.alwaysMatches()) {
|
||||
return true;
|
||||
}
|
||||
else if (shadowMatch.neverMatches()) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// the maybe case
|
||||
return (beanHasIntroductions || matchesIgnoringSubtypes(shadowMatch) || matchesTarget(shadowMatch, targetClass));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean matches(Method method, Class targetClass) {
|
||||
return matches(method, targetClass, false);
|
||||
}
|
||||
|
||||
public boolean isRuntime() {
|
||||
checkReadyToMatch();
|
||||
return this.pointcutExpression.mayNeedDynamicTest();
|
||||
}
|
||||
|
||||
public boolean matches(Method method, Class targetClass, Object[] args) {
|
||||
checkReadyToMatch();
|
||||
ShadowMatch shadowMatch = null;
|
||||
ShadowMatch originalShadowMatch = null;
|
||||
try {
|
||||
shadowMatch = getShadowMatch(AopUtils.getMostSpecificMethod(method, targetClass), method);
|
||||
originalShadowMatch = getShadowMatch(method, method);
|
||||
}
|
||||
catch (ReflectionWorld.ReflectionWorldException ex) {
|
||||
// Could neither introspect the target class nor the proxy class ->
|
||||
// let's simply consider this method as non-matching.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bind Spring AOP proxy to AspectJ "this" and Spring AOP target to AspectJ target,
|
||||
// consistent with return of MethodInvocationProceedingJoinPoint
|
||||
ProxyMethodInvocation pmi = null;
|
||||
Object targetObject = null;
|
||||
Object thisObject = null;
|
||||
try {
|
||||
MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
|
||||
targetObject = mi.getThis();
|
||||
if (!(mi instanceof ProxyMethodInvocation)) {
|
||||
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
|
||||
}
|
||||
pmi = (ProxyMethodInvocation) mi;
|
||||
thisObject = pmi.getProxy();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
// No current invocation...
|
||||
// TODO: Should we really proceed here?
|
||||
logger.debug("Couldn't access current invocation - matching with limited context: " + ex);
|
||||
}
|
||||
|
||||
JoinPointMatch joinPointMatch = shadowMatch.matchesJoinPoint(thisObject, targetObject, args);
|
||||
|
||||
/*
|
||||
* Do a final check to see if any this(TYPE) kind of residue match. For
|
||||
* this purpose, we use the original method's (proxy method's) shadow to
|
||||
* ensure that 'this' is correctly checked against. Without this check,
|
||||
* we get incorrect match on this(TYPE) where TYPE matches the target
|
||||
* type but not 'this' (as would be the case of JDK dynamic proxies).
|
||||
* <p>See SPR-2979 for the original bug.
|
||||
*/
|
||||
if (pmi != null) { // there is a current invocation
|
||||
RuntimeTestWalker originalMethodResidueTest = new RuntimeTestWalker(originalShadowMatch);
|
||||
if (!originalMethodResidueTest.testThisInstanceOfResidue(thisObject.getClass())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (joinPointMatch.matches() && pmi != null) {
|
||||
bindParameters(pmi, joinPointMatch);
|
||||
}
|
||||
return joinPointMatch.matches();
|
||||
}
|
||||
|
||||
|
||||
protected String getCurrentProxiedBeanName() {
|
||||
return ProxyCreationContext.getCurrentProxiedBeanName();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A match test returned maybe - if there are any subtype sensitive variables
|
||||
* involved in the test (this, target, at_this, at_target, at_annotation) then
|
||||
* we say this is not a match as in Spring there will never be a different
|
||||
* runtime subtype.
|
||||
*/
|
||||
private boolean matchesIgnoringSubtypes(ShadowMatch shadowMatch) {
|
||||
return !(new RuntimeTestWalker(shadowMatch).testsSubtypeSensitiveVars());
|
||||
}
|
||||
|
||||
private boolean matchesTarget(ShadowMatch shadowMatch, Class targetClass) {
|
||||
return new RuntimeTestWalker(shadowMatch).testTargetInstanceOfResidue(targetClass);
|
||||
}
|
||||
|
||||
private void bindParameters(ProxyMethodInvocation invocation, JoinPointMatch jpm) {
|
||||
// Note: Can't use JoinPointMatch.getClass().getName() as the key, since
|
||||
// Spring AOP does all the matching at a join point, and then all the invocations
|
||||
// under this scenario, if we just use JoinPointMatch as the key, then
|
||||
// 'last man wins' which is not what we want at all.
|
||||
// Using the expression is guaranteed to be safe, since 2 identical expressions
|
||||
// are guaranteed to bind in exactly the same way.
|
||||
invocation.setUserAttribute(getExpression(), jpm);
|
||||
}
|
||||
|
||||
private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
|
||||
synchronized (this.shadowMatchCache) {
|
||||
ShadowMatch shadowMatch = this.shadowMatchCache.get(targetMethod);
|
||||
if (shadowMatch == null) {
|
||||
try {
|
||||
shadowMatch = this.pointcutExpression.matchesMethodExecution(targetMethod);
|
||||
}
|
||||
catch (ReflectionWorld.ReflectionWorldException ex) {
|
||||
// Failed to introspect target method, probably because it has been loaded
|
||||
// in a special ClassLoader. Let's try the original method instead...
|
||||
if (targetMethod == originalMethod) {
|
||||
throw ex;
|
||||
}
|
||||
shadowMatch = this.pointcutExpression.matchesMethodExecution(originalMethod);
|
||||
}
|
||||
this.shadowMatchCache.put(targetMethod, shadowMatch);
|
||||
}
|
||||
return shadowMatch;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof AspectJExpressionPointcut)) {
|
||||
return false;
|
||||
}
|
||||
AspectJExpressionPointcut otherPc = (AspectJExpressionPointcut) other;
|
||||
return ObjectUtils.nullSafeEquals(this.getExpression(), otherPc.getExpression()) &&
|
||||
ObjectUtils.nullSafeEquals(this.pointcutDeclarationScope, otherPc.pointcutDeclarationScope) &&
|
||||
ObjectUtils.nullSafeEquals(this.pointcutParameterNames, otherPc.pointcutParameterNames) &&
|
||||
ObjectUtils.nullSafeEquals(this.pointcutParameterTypes, otherPc.pointcutParameterTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hashCode = ObjectUtils.nullSafeHashCode(this.getExpression());
|
||||
hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.pointcutDeclarationScope);
|
||||
hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.pointcutParameterNames);
|
||||
hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.pointcutParameterTypes);
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("AspectJExpressionPointcut: ");
|
||||
if (this.pointcutParameterNames != null && this.pointcutParameterTypes != null) {
|
||||
sb.append("(");
|
||||
for (int i = 0; i < this.pointcutParameterTypes.length; i++) {
|
||||
sb.append(this.pointcutParameterTypes[i].getName());
|
||||
sb.append(" ");
|
||||
sb.append(this.pointcutParameterNames[i]);
|
||||
if ((i+1) < this.pointcutParameterTypes.length) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
sb.append(")");
|
||||
}
|
||||
sb.append(" ");
|
||||
if (getExpression() != null) {
|
||||
sb.append(getExpression());
|
||||
}
|
||||
else {
|
||||
sb.append("<pointcut expression not set>");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handler for the Spring-specific <code>bean()</code> pointcut designator
|
||||
* extension to AspectJ.
|
||||
* <p>This handler must be added to each pointcut object that needs to
|
||||
* handle the <code>bean()</code> PCD. Matching context is obtained
|
||||
* automatically by examining a thread local variable and therefore a matching
|
||||
* context need not be set on the pointcut.
|
||||
*/
|
||||
private class BeanNamePointcutDesignatorHandler implements PointcutDesignatorHandler {
|
||||
|
||||
private static final String BEAN_DESIGNATOR_NAME = "bean";
|
||||
|
||||
public String getDesignatorName() {
|
||||
return BEAN_DESIGNATOR_NAME;
|
||||
}
|
||||
|
||||
public ContextBasedMatcher parse(String expression) {
|
||||
return new BeanNameContextMatcher(expression);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Matcher class for the BeanNamePointcutDesignatorHandler.
|
||||
*
|
||||
* <p>Dynamic match tests for this matcher always return true,
|
||||
* since the matching decision is made at the proxy creation time.
|
||||
* For static match tests, this matcher abstains to allow the overall
|
||||
* pointcut to match even when negation is used with the bean() poitncut.
|
||||
*/
|
||||
private class BeanNameContextMatcher implements ContextBasedMatcher {
|
||||
|
||||
private final NamePattern expressionPattern;
|
||||
|
||||
public BeanNameContextMatcher(String expression) {
|
||||
this.expressionPattern = new NamePattern(expression);
|
||||
}
|
||||
|
||||
public boolean couldMatchJoinPointsInType(Class someClass) {
|
||||
return (contextMatch(someClass) == FuzzyBoolean.YES);
|
||||
}
|
||||
|
||||
public boolean couldMatchJoinPointsInType(Class someClass, MatchingContext context) {
|
||||
return (contextMatch(someClass) == FuzzyBoolean.YES);
|
||||
}
|
||||
|
||||
public boolean matchesDynamically(MatchingContext context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public FuzzyBoolean matchesStatically(MatchingContext context) {
|
||||
return contextMatch(null);
|
||||
}
|
||||
|
||||
public boolean mayNeedDynamicTest() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private FuzzyBoolean contextMatch(Class targetType) {
|
||||
String advisedBeanName = getCurrentProxiedBeanName();
|
||||
if (advisedBeanName == null) { // no proxy creation in progress
|
||||
// abstain; can't return YES, since that will make pointcut with negation fail
|
||||
return FuzzyBoolean.MAYBE;
|
||||
}
|
||||
if (BeanFactoryUtils.isGeneratedBeanName(advisedBeanName)) {
|
||||
return FuzzyBoolean.NO;
|
||||
}
|
||||
if (targetType != null) {
|
||||
boolean isFactory = FactoryBean.class.isAssignableFrom(targetType);
|
||||
return FuzzyBoolean.fromBoolean(
|
||||
matchesBeanName(isFactory ? BeanFactory.FACTORY_BEAN_PREFIX + advisedBeanName : advisedBeanName));
|
||||
}
|
||||
else {
|
||||
return FuzzyBoolean.fromBoolean(matchesBeanName(advisedBeanName) ||
|
||||
matchesBeanName(BeanFactory.FACTORY_BEAN_PREFIX + advisedBeanName));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean matchesBeanName(String advisedBeanName) {
|
||||
if (this.expressionPattern.matches(advisedBeanName)) {
|
||||
return true;
|
||||
}
|
||||
if (beanFactory != null) {
|
||||
String[] aliases = beanFactory.getAliases(advisedBeanName);
|
||||
for (String alias : aliases) {
|
||||
if (this.expressionPattern.matches(alias)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-61
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.support.AbstractGenericPointcutAdvisor;
|
||||
|
||||
/**
|
||||
* Spring AOP Advisor that can be used for any AspectJ pointcut expression.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AspectJExpressionPointcutAdvisor extends AbstractGenericPointcutAdvisor {
|
||||
|
||||
private final AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
|
||||
|
||||
|
||||
public Pointcut getPointcut() {
|
||||
return this.pointcut;
|
||||
}
|
||||
|
||||
public void setExpression(String expression) {
|
||||
this.pointcut.setExpression(expression);
|
||||
}
|
||||
|
||||
public void setLocation(String location) {
|
||||
this.pointcut.setLocation(location);
|
||||
}
|
||||
|
||||
public void setParameterTypes(Class[] types) {
|
||||
this.pointcut.setParameterTypes(types);
|
||||
}
|
||||
|
||||
public void setParameterNames(String[] names) {
|
||||
this.pointcut.setParameterNames(names);
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return this.pointcut.getLocation();
|
||||
}
|
||||
|
||||
public String getExpression() {
|
||||
return this.pointcut.getExpression();
|
||||
}
|
||||
|
||||
}
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.aop.MethodBeforeAdvice;
|
||||
|
||||
/**
|
||||
* Spring AOP advice that wraps an AspectJ before method.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Adrian Colyer
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice {
|
||||
|
||||
public AspectJMethodBeforeAdvice(
|
||||
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
|
||||
|
||||
super(aspectJBeforeAdviceMethod, pointcut, aif);
|
||||
}
|
||||
|
||||
public void before(Method method, Object[] args, Object target) throws Throwable {
|
||||
invokeAdviceMethod(getJoinPointMatch(), null, null);
|
||||
}
|
||||
|
||||
public boolean isBeforeAdvice() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isAfterAdvice() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
-98
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.PointcutAdvisor;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* AspectJPointcutAdvisor that adapts an {@link AbstractAspectJAdvice}
|
||||
* to the {@link org.springframework.aop.PointcutAdvisor} interface.
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
|
||||
|
||||
private final AbstractAspectJAdvice advice;
|
||||
|
||||
private final Pointcut pointcut;
|
||||
|
||||
private Integer order;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new AspectJPointcutAdvisor for the given advice
|
||||
* @param advice the AbstractAspectJAdvice to wrap
|
||||
*/
|
||||
public AspectJPointcutAdvisor(AbstractAspectJAdvice advice) {
|
||||
Assert.notNull(advice, "Advice must not be null");
|
||||
this.advice = advice;
|
||||
this.pointcut = advice.buildSafePointcut();
|
||||
}
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
|
||||
public boolean isPerInstance() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Advice getAdvice() {
|
||||
return this.advice;
|
||||
}
|
||||
|
||||
public Pointcut getPointcut() {
|
||||
return this.pointcut;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
if (this.order != null) {
|
||||
return this.order;
|
||||
}
|
||||
else {
|
||||
return this.advice.getOrder();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof AspectJPointcutAdvisor)) {
|
||||
return false;
|
||||
}
|
||||
AspectJPointcutAdvisor otherAdvisor = (AspectJPointcutAdvisor) other;
|
||||
return (ObjectUtils.nullSafeEquals(this.advice, otherAdvisor.advice));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return AspectJPointcutAdvisor.class.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
-58
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by types that can supply the information
|
||||
* needed to sort advice/advisors by AspectJ's precedence rules.
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @since 2.0
|
||||
* @see org.springframework.aop.aspectj.autoproxy.AspectJPrecedenceComparator
|
||||
*/
|
||||
public interface AspectJPrecedenceInformation extends Ordered {
|
||||
|
||||
// Implementation note:
|
||||
// We need the level of indirection this interface provides as otherwise the
|
||||
// AspectJPrecedenceComparator must ask an Advisor for its Advice in all cases
|
||||
// in order to sort advisors. This causes problems with the
|
||||
// InstantiationModelAwarePointcutAdvisor which needs to delay creating
|
||||
// its advice for aspects with non-singleton instantiation models.
|
||||
|
||||
/**
|
||||
* The name of the aspect (bean) in which the advice was declared.
|
||||
*/
|
||||
String getAspectName();
|
||||
|
||||
/**
|
||||
* The declaration order of the advice member within the aspect.
|
||||
*/
|
||||
int getDeclarationOrder();
|
||||
|
||||
/**
|
||||
* Return whether this is a before advice.
|
||||
*/
|
||||
boolean isBeforeAdvice();
|
||||
|
||||
/**
|
||||
* Return whether this is an after advice.
|
||||
*/
|
||||
boolean isAfterAdvice();
|
||||
|
||||
}
|
||||
-72
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.PointcutAdvisor;
|
||||
import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
|
||||
|
||||
/**
|
||||
* Utility methods for working with AspectJ proxies.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class AspectJProxyUtils {
|
||||
|
||||
/**
|
||||
* Add special advisors if necessary to work with a proxy chain that contains AspectJ advisors.
|
||||
* This will expose the current Spring AOP invocation (necessary for some AspectJ pointcut matching)
|
||||
* and make available the current AspectJ JoinPoint. The call will have no effect if there are no
|
||||
* AspectJ advisors in the advisor chain.
|
||||
* @param advisors Advisors available
|
||||
* @return <code>true</code> if any special {@link Advisor Advisors} were added, otherwise <code>false</code>.
|
||||
*/
|
||||
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
|
||||
// Don't add advisors to an empty list; may indicate that proxying is just not required
|
||||
if (!advisors.isEmpty()) {
|
||||
boolean foundAspectJAdvice = false;
|
||||
for (Advisor advisor : advisors) {
|
||||
// Be careful not to get the Advice without a guard, as
|
||||
// this might eagerly instantiate a non-singleton AspectJ aspect
|
||||
if (isAspectJAdvice(advisor)) {
|
||||
foundAspectJAdvice = true;
|
||||
}
|
||||
}
|
||||
if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
|
||||
advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given Advisor contains an AspectJ advice.
|
||||
* @param advisor the Advisor to check
|
||||
*/
|
||||
private static boolean isAspectJAdvice(Advisor advisor) {
|
||||
return (advisor instanceof InstantiationModelAwarePointcutAdvisor ||
|
||||
advisor.getAdvice() instanceof AbstractAspectJAdvice ||
|
||||
(advisor instanceof PointcutAdvisor &&
|
||||
((PointcutAdvisor) advisor).getPointcut() instanceof AspectJExpressionPointcut));
|
||||
}
|
||||
|
||||
}
|
||||
-109
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.aspectj.bridge.AbortException;
|
||||
import org.aspectj.bridge.IMessage;
|
||||
import org.aspectj.bridge.IMessage.Kind;
|
||||
import org.aspectj.bridge.IMessageHandler;
|
||||
|
||||
/**
|
||||
* Implementation of AspectJ's {@link IMessageHandler} interface that
|
||||
* routes AspectJ weaving messages through the same logging system as the
|
||||
* regular Spring messages.
|
||||
*
|
||||
* <p>Pass the option...
|
||||
*
|
||||
* <p><code class="code">-XmessageHandlerClass:org.springframework.aop.aspectj.AspectJWeaverMessageHandler</code>
|
||||
*
|
||||
* <p>to the weaver; for example, specifying the following in a
|
||||
* "<code>META-INF/aop.xml</code> file:
|
||||
*
|
||||
* <p><code class="code"><weaver options="..."/></code>
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AspectJWeaverMessageHandler implements IMessageHandler {
|
||||
|
||||
private static final String AJ_ID = "[AspectJ] ";
|
||||
|
||||
private static final Log LOGGER = LogFactory.getLog("AspectJ Weaver");
|
||||
|
||||
|
||||
public boolean handleMessage(IMessage message) throws AbortException {
|
||||
Kind messageKind = message.getKind();
|
||||
|
||||
if (LOGGER.isDebugEnabled() || LOGGER.isTraceEnabled()) {
|
||||
if (messageKind == IMessage.DEBUG) {
|
||||
LOGGER.debug(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (LOGGER.isInfoEnabled()) {
|
||||
if ((messageKind == IMessage.INFO) || (messageKind == IMessage.WEAVEINFO)) {
|
||||
LOGGER.info(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (LOGGER.isWarnEnabled()) {
|
||||
if (messageKind == IMessage.WARNING) {
|
||||
LOGGER.warn(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (LOGGER.isErrorEnabled()) {
|
||||
if (messageKind == IMessage.ERROR) {
|
||||
LOGGER.error(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (LOGGER.isFatalEnabled()) {
|
||||
if (messageKind == IMessage.ABORT) {
|
||||
LOGGER.fatal(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private String makeMessageFor(IMessage aMessage) {
|
||||
return AJ_ID + aMessage.getMessage();
|
||||
}
|
||||
|
||||
public boolean isIgnoring(Kind messageKind) {
|
||||
// We want to see everything, and allow configuration of log levels dynamically.
|
||||
return false;
|
||||
}
|
||||
|
||||
public void dontIgnore(Kind messageKind) {
|
||||
// We weren't ignoring anything anyway...
|
||||
}
|
||||
|
||||
public void ignore(Kind kind) {
|
||||
// We weren't ignoring anything anyway...
|
||||
}
|
||||
|
||||
}
|
||||
-110
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
|
||||
import org.springframework.aop.ClassFilter;
|
||||
import org.springframework.aop.IntroductionAdvisor;
|
||||
import org.springframework.aop.support.ClassFilters;
|
||||
import org.springframework.aop.support.DelegatePerTargetObjectIntroductionInterceptor;
|
||||
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
|
||||
|
||||
/**
|
||||
* Introduction advisor delegating to the given object.
|
||||
* Implements AspectJ annotation-style behavior for the DeclareParents annotation.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.0
|
||||
*/
|
||||
public class DeclareParentsAdvisor implements IntroductionAdvisor {
|
||||
|
||||
private final Class introducedInterface;
|
||||
|
||||
private final ClassFilter typePatternClassFilter;
|
||||
|
||||
private final Advice advice;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new advisor for this DeclareParents field.
|
||||
* @param interfaceType static field defining the introduction
|
||||
* @param typePattern type pattern the introduction is restricted to
|
||||
* @param defaultImpl the default implementation class
|
||||
*/
|
||||
public DeclareParentsAdvisor(Class interfaceType, String typePattern, Class defaultImpl) {
|
||||
this(interfaceType, typePattern, defaultImpl,
|
||||
new DelegatePerTargetObjectIntroductionInterceptor(defaultImpl, interfaceType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new advisor for this DeclareParents field.
|
||||
* @param interfaceType static field defining the introduction
|
||||
* @param typePattern type pattern the introduction is restricted to
|
||||
* @param delegateRef the delegate implementation object
|
||||
*/
|
||||
public DeclareParentsAdvisor(Class interfaceType, String typePattern, Object delegateRef) {
|
||||
this(interfaceType, typePattern, delegateRef.getClass(),
|
||||
new DelegatingIntroductionInterceptor(delegateRef));
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor to share common code between impl-based delegate and reference-based delegate
|
||||
* (cannot use method such as init() to share common code, due the the use of final fields)
|
||||
* @param interfaceType static field defining the introduction
|
||||
* @param typePattern type pattern the introduction is restricted to
|
||||
* @param implementationClass implementation class
|
||||
* @param advice delegation advice
|
||||
*/
|
||||
private DeclareParentsAdvisor(Class interfaceType, String typePattern, Class implementationClass, Advice advice) {
|
||||
this.introducedInterface = interfaceType;
|
||||
ClassFilter typePatternFilter = new TypePatternClassFilter(typePattern);
|
||||
|
||||
// Excludes methods implemented.
|
||||
ClassFilter exclusion = new ClassFilter() {
|
||||
public boolean matches(Class clazz) {
|
||||
return !(introducedInterface.isAssignableFrom(clazz));
|
||||
}
|
||||
};
|
||||
|
||||
this.typePatternClassFilter = ClassFilters.intersection(typePatternFilter, exclusion);
|
||||
this.advice = advice;
|
||||
}
|
||||
|
||||
|
||||
public ClassFilter getClassFilter() {
|
||||
return this.typePatternClassFilter;
|
||||
}
|
||||
|
||||
public void validateInterfaces() throws IllegalArgumentException {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public boolean isPerInstance() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Advice getAdvice() {
|
||||
return this.advice;
|
||||
}
|
||||
|
||||
public Class[] getInterfaces() {
|
||||
return new Class[] {this.introducedInterface};
|
||||
}
|
||||
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import org.springframework.aop.PointcutAdvisor;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by Spring AOP Advisors wrapping AspectJ
|
||||
* aspects that may have a lazy initialization strategy. For example,
|
||||
* a perThis instantiation model would mean lazy initialization of the advice.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface InstantiationModelAwarePointcutAdvisor extends PointcutAdvisor {
|
||||
|
||||
/**
|
||||
* Return whether this advisor is lazily initializing its underlying advice.
|
||||
*/
|
||||
boolean isLazy();
|
||||
|
||||
/**
|
||||
* Return whether this advisor has already instantiated its advice.
|
||||
*/
|
||||
boolean isAdviceInstantiated();
|
||||
|
||||
}
|
||||
-285
@@ -1,285 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.Signature;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.aspectj.lang.reflect.SourceLocation;
|
||||
import org.aspectj.runtime.internal.AroundClosure;
|
||||
|
||||
import org.springframework.aop.ProxyMethodInvocation;
|
||||
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Implementation of AspectJ ProceedingJoinPoint interface
|
||||
* wrapping an AOP Alliance MethodInvocation.
|
||||
*
|
||||
* <p><b>Note</b>: the <code>getThis()</code> method returns the current Spring AOP proxy.
|
||||
* The <code>getTarget()</code> method returns the current Spring AOP target (which may be
|
||||
* <code>null</code> if there is no target), and is a plain POJO without any advice.
|
||||
* <b>If you want to call the object and have the advice take effect, use
|
||||
* <code>getThis()</code>.</b> A common example is casting the object to an
|
||||
* introduced interface in the implementation of an introduction.
|
||||
*
|
||||
* <p>Of course there is no such distinction between target and proxy in AspectJ.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Adrian Colyer
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.0
|
||||
*/
|
||||
public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint, JoinPoint.StaticPart {
|
||||
|
||||
private final ProxyMethodInvocation methodInvocation;
|
||||
|
||||
private Object[] defensiveCopyOfArgs;
|
||||
|
||||
/** Lazily initialized signature object */
|
||||
private Signature signature;
|
||||
|
||||
/** Lazily initialized source location object */
|
||||
private SourceLocation sourceLocation;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new MethodInvocationProceedingJoinPoint, wrapping the given
|
||||
* Spring ProxyMethodInvocation object.
|
||||
* @param methodInvocation the Spring ProxyMethodInvocation object
|
||||
*/
|
||||
public MethodInvocationProceedingJoinPoint(ProxyMethodInvocation methodInvocation) {
|
||||
Assert.notNull(methodInvocation, "MethodInvocation must not be null");
|
||||
this.methodInvocation = methodInvocation;
|
||||
}
|
||||
|
||||
public void set$AroundClosure(AroundClosure aroundClosure) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Object proceed() throws Throwable {
|
||||
return this.methodInvocation.invocableClone().proceed();
|
||||
}
|
||||
|
||||
public Object proceed(Object[] arguments) throws Throwable {
|
||||
Assert.notNull(arguments, "Argument array passed to proceed cannot be null");
|
||||
if (arguments.length != this.methodInvocation.getArguments().length) {
|
||||
throw new IllegalArgumentException("Expecting " +
|
||||
this.methodInvocation.getArguments().length + " arguments to proceed, " +
|
||||
"but was passed " + arguments.length + " arguments");
|
||||
}
|
||||
this.methodInvocation.setArguments(arguments);
|
||||
return this.methodInvocation.invocableClone(arguments).proceed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Spring AOP proxy. Cannot be <code>null</code>.
|
||||
*/
|
||||
public Object getThis() {
|
||||
return this.methodInvocation.getProxy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Spring AOP target. May be <code>null</code> if there is no target.
|
||||
*/
|
||||
public Object getTarget() {
|
||||
return this.methodInvocation.getThis();
|
||||
}
|
||||
|
||||
public Object[] getArgs() {
|
||||
if (this.defensiveCopyOfArgs == null) {
|
||||
Object[] argsSource = this.methodInvocation.getArguments();
|
||||
this.defensiveCopyOfArgs = new Object[argsSource.length];
|
||||
System.arraycopy(argsSource, 0, this.defensiveCopyOfArgs, 0, argsSource.length);
|
||||
}
|
||||
return this.defensiveCopyOfArgs;
|
||||
}
|
||||
|
||||
public Signature getSignature() {
|
||||
if (this.signature == null) {
|
||||
this.signature = new MethodSignatureImpl();
|
||||
}
|
||||
return signature;
|
||||
}
|
||||
|
||||
public SourceLocation getSourceLocation() {
|
||||
if (this.sourceLocation == null) {
|
||||
this.sourceLocation = new SourceLocationImpl();
|
||||
}
|
||||
return this.sourceLocation;
|
||||
}
|
||||
|
||||
public String getKind() {
|
||||
return ProceedingJoinPoint.METHOD_EXECUTION;
|
||||
}
|
||||
|
||||
public JoinPoint.StaticPart getStaticPart() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public String toShortString() {
|
||||
return "execution(" + getSignature().toShortString() + ")";
|
||||
}
|
||||
|
||||
public String toLongString() {
|
||||
return "execution(" + getSignature().toLongString() + ")";
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "execution(" + getSignature().toString() + ")";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Lazily initialized MethodSignature.
|
||||
*/
|
||||
private class MethodSignatureImpl implements MethodSignature {
|
||||
|
||||
private volatile String[] parameterNames;
|
||||
|
||||
public String getName() {
|
||||
return methodInvocation.getMethod().getName();
|
||||
}
|
||||
|
||||
public int getModifiers() {
|
||||
return methodInvocation.getMethod().getModifiers();
|
||||
}
|
||||
|
||||
public Class getDeclaringType() {
|
||||
return methodInvocation.getMethod().getDeclaringClass();
|
||||
}
|
||||
|
||||
public String getDeclaringTypeName() {
|
||||
return methodInvocation.getMethod().getDeclaringClass().getName();
|
||||
}
|
||||
|
||||
public Class getReturnType() {
|
||||
return methodInvocation.getMethod().getReturnType();
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return methodInvocation.getMethod();
|
||||
}
|
||||
|
||||
public Class[] getParameterTypes() {
|
||||
return methodInvocation.getMethod().getParameterTypes();
|
||||
}
|
||||
|
||||
public String[] getParameterNames() {
|
||||
if (this.parameterNames == null) {
|
||||
this.parameterNames = (new LocalVariableTableParameterNameDiscoverer()).getParameterNames(getMethod());
|
||||
}
|
||||
return this.parameterNames;
|
||||
}
|
||||
|
||||
public Class[] getExceptionTypes() {
|
||||
return methodInvocation.getMethod().getExceptionTypes();
|
||||
}
|
||||
|
||||
public String toShortString() {
|
||||
return toString(false, false, false, false);
|
||||
}
|
||||
|
||||
public String toLongString() {
|
||||
return toString(true, true, true, true);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return toString(false, true, false, true);
|
||||
}
|
||||
|
||||
private String toString(boolean includeModifier, boolean includeReturnTypeAndArgs,
|
||||
boolean useLongReturnAndArgumentTypeName, boolean useLongTypeName) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (includeModifier) {
|
||||
sb.append(Modifier.toString(getModifiers()));
|
||||
sb.append(" ");
|
||||
}
|
||||
if (includeReturnTypeAndArgs) {
|
||||
appendType(sb, getReturnType(), useLongReturnAndArgumentTypeName);
|
||||
sb.append(" ");
|
||||
}
|
||||
appendType(sb, getDeclaringType(), useLongTypeName);
|
||||
sb.append(".");
|
||||
sb.append(getMethod().getName());
|
||||
sb.append("(");
|
||||
Class[] parametersTypes = getParameterTypes();
|
||||
appendTypes(sb, parametersTypes, includeReturnTypeAndArgs, useLongReturnAndArgumentTypeName);
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void appendTypes(StringBuilder sb, Class<?>[] types,
|
||||
boolean includeArgs, boolean useLongReturnAndArgumentTypeName) {
|
||||
if (includeArgs) {
|
||||
for (int size = types.length, i = 0; i < size; i++) {
|
||||
appendType(sb, types[i], useLongReturnAndArgumentTypeName);
|
||||
if (i < size - 1) {
|
||||
sb.append(",");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (types.length != 0) {
|
||||
sb.append("..");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void appendType(StringBuilder sb, Class<?> type, boolean useLongTypeName) {
|
||||
if (type.isArray()) {
|
||||
appendType(sb, type.getComponentType(), useLongTypeName);
|
||||
sb.append("[]");
|
||||
}
|
||||
else {
|
||||
sb.append(useLongTypeName ? type.getName() : type.getSimpleName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Lazily initialized SourceLocation.
|
||||
*/
|
||||
private class SourceLocationImpl implements SourceLocation {
|
||||
|
||||
public Class getWithinType() {
|
||||
if (methodInvocation.getThis() == null) {
|
||||
throw new UnsupportedOperationException("No source location joinpoint available: target is null");
|
||||
}
|
||||
return methodInvocation.getThis().getClass();
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public int getColumn() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-258
@@ -1,258 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.aspectj.weaver.ResolvedType;
|
||||
import org.aspectj.weaver.ast.And;
|
||||
import org.aspectj.weaver.ast.Call;
|
||||
import org.aspectj.weaver.ast.FieldGetCall;
|
||||
import org.aspectj.weaver.ast.HasAnnotation;
|
||||
import org.aspectj.weaver.ast.ITestVisitor;
|
||||
import org.aspectj.weaver.ast.Instanceof;
|
||||
import org.aspectj.weaver.ast.Literal;
|
||||
import org.aspectj.weaver.ast.Not;
|
||||
import org.aspectj.weaver.ast.Or;
|
||||
import org.aspectj.weaver.ast.Test;
|
||||
import org.aspectj.weaver.internal.tools.MatchingContextBasedTest;
|
||||
import org.aspectj.weaver.reflect.ReflectionVar;
|
||||
import org.aspectj.weaver.reflect.ShadowMatchImpl;
|
||||
import org.aspectj.weaver.tools.ShadowMatch;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* This class encapsulates some AspectJ internal knowledge that should be
|
||||
* pushed back into the AspectJ project in a future release.
|
||||
*
|
||||
* <p>It relies on implementation specific knowledge in AspectJ to break
|
||||
* encapsulation and do something AspectJ was not designed to do: query
|
||||
* the types of runtime tests that will be performed. The code here should
|
||||
* migrate to <code>ShadowMatch.getVariablesInvolvedInRuntimeTest()</code>
|
||||
* or some similar operation.
|
||||
*
|
||||
* <p>See <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=151593"/>.
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.0
|
||||
*/
|
||||
class RuntimeTestWalker {
|
||||
|
||||
private final Test runtimeTest;
|
||||
|
||||
|
||||
public RuntimeTestWalker(ShadowMatch shadowMatch) {
|
||||
ShadowMatchImpl shadowMatchImplementation = (ShadowMatchImpl) shadowMatch;
|
||||
try {
|
||||
Field testField = shadowMatchImplementation.getClass().getDeclaredField("residualTest");
|
||||
ReflectionUtils.makeAccessible(testField);
|
||||
this.runtimeTest = (Test) testField.get(shadowMatch);
|
||||
}
|
||||
catch (NoSuchFieldException noSuchFieldEx) {
|
||||
throw new IllegalStateException("The version of aspectjtools.jar / aspectjweaver.jar " +
|
||||
"on the classpath is incompatible with this version of Spring: Expected field " +
|
||||
"'runtimeTest' is not present on ShadowMatchImpl class.");
|
||||
}
|
||||
catch (IllegalAccessException illegalAccessEx) {
|
||||
// Famous last words... but I don't see how this can happen given the
|
||||
// makeAccessible call above
|
||||
throw new IllegalStateException("Unable to access ShadowMatchImpl.runtimeTest field.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If the test uses any of the this, target, at_this, at_target, and at_annotation vars,
|
||||
* then it tests subtype sensitive vars.
|
||||
*/
|
||||
public boolean testsSubtypeSensitiveVars() {
|
||||
return new SubtypeSensitiveVarTypeTestVisitor().testsSubtypeSensitiveVars(this.runtimeTest);
|
||||
}
|
||||
|
||||
public boolean testThisInstanceOfResidue(Class thisClass) {
|
||||
return new ThisInstanceOfResidueTestVisitor(thisClass).thisInstanceOfMatches(this.runtimeTest);
|
||||
}
|
||||
|
||||
public boolean testTargetInstanceOfResidue(Class targetClass) {
|
||||
return new TargetInstanceOfResidueTestVisitor(targetClass).targetInstanceOfMatches(this.runtimeTest);
|
||||
}
|
||||
|
||||
|
||||
private static class TestVisitorAdapter implements ITestVisitor {
|
||||
|
||||
protected static final int THIS_VAR = 0;
|
||||
protected static final int TARGET_VAR = 1;
|
||||
protected static final int AT_THIS_VAR = 3;
|
||||
protected static final int AT_TARGET_VAR = 4;
|
||||
protected static final int AT_ANNOTATION_VAR = 8;
|
||||
|
||||
public void visit(And e) {
|
||||
e.getLeft().accept(this);
|
||||
e.getRight().accept(this);
|
||||
}
|
||||
|
||||
public void visit(Or e) {
|
||||
e.getLeft().accept(this);
|
||||
e.getRight().accept(this);
|
||||
}
|
||||
|
||||
public void visit(Not e) {
|
||||
e.getBody().accept(this);
|
||||
}
|
||||
|
||||
public void visit(Instanceof i) {
|
||||
}
|
||||
|
||||
public void visit(Literal literal) {
|
||||
}
|
||||
|
||||
public void visit(Call call) {
|
||||
}
|
||||
|
||||
public void visit(FieldGetCall fieldGetCall) {
|
||||
}
|
||||
|
||||
public void visit(HasAnnotation hasAnnotation) {
|
||||
}
|
||||
|
||||
public void visit(MatchingContextBasedTest matchingContextTest) {
|
||||
}
|
||||
|
||||
protected int getVarType(ReflectionVar v) {
|
||||
try {
|
||||
Field varTypeField = ReflectionVar.class.getDeclaredField("varType");
|
||||
ReflectionUtils.makeAccessible(varTypeField);
|
||||
Integer varTypeValue = (Integer) varTypeField.get(v);
|
||||
return varTypeValue.intValue();
|
||||
}
|
||||
catch (NoSuchFieldException noSuchFieldEx) {
|
||||
throw new IllegalStateException("the version of aspectjtools.jar / aspectjweaver.jar " +
|
||||
"on the classpath is incompatible with this version of Spring:- expected field " +
|
||||
"'varType' is not present on ReflectionVar class");
|
||||
}
|
||||
catch (IllegalAccessException illegalAccessEx) {
|
||||
// Famous last words... but I don't see how this can happen given the
|
||||
// makeAccessible call above
|
||||
throw new IllegalStateException("Unable to access ReflectionVar.varType field.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static abstract class InstanceOfResidueTestVisitor extends TestVisitorAdapter {
|
||||
|
||||
private Class matchClass;
|
||||
private boolean matches;
|
||||
private int matchVarType;
|
||||
|
||||
public InstanceOfResidueTestVisitor(Class matchClass, boolean defaultMatches, int matchVarType) {
|
||||
this.matchClass = matchClass;
|
||||
this.matches = defaultMatches;
|
||||
this.matchVarType = matchVarType;
|
||||
}
|
||||
|
||||
public boolean instanceOfMatches(Test test) {
|
||||
test.accept(this);
|
||||
return matches;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Instanceof i) {
|
||||
ResolvedType type = (ResolvedType) i.getType();
|
||||
int varType = getVarType((ReflectionVar) i.getVar());
|
||||
if (varType != this.matchVarType) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Class typeClass = ClassUtils.forName(type.getName(), this.matchClass.getClassLoader());
|
||||
// Don't use ReflectionType.isAssignableFrom() as it won't be aware of (Spring) mixins
|
||||
this.matches = typeClass.isAssignableFrom(this.matchClass);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
this.matches = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if residue of target(TYPE) kind. See SPR-3783 for more details.
|
||||
*/
|
||||
private static class TargetInstanceOfResidueTestVisitor extends InstanceOfResidueTestVisitor {
|
||||
|
||||
public TargetInstanceOfResidueTestVisitor(Class targetClass) {
|
||||
super(targetClass, false, TARGET_VAR);
|
||||
}
|
||||
|
||||
public boolean targetInstanceOfMatches(Test test) {
|
||||
return instanceOfMatches(test);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if residue of this(TYPE) kind. See SPR-2979 for more details.
|
||||
*/
|
||||
private static class ThisInstanceOfResidueTestVisitor extends InstanceOfResidueTestVisitor {
|
||||
|
||||
public ThisInstanceOfResidueTestVisitor(Class thisClass) {
|
||||
super(thisClass, true, THIS_VAR);
|
||||
}
|
||||
|
||||
// TODO: Optimization: Process only if this() specifies a type and not an identifier.
|
||||
public boolean thisInstanceOfMatches(Test test) {
|
||||
return instanceOfMatches(test);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class SubtypeSensitiveVarTypeTestVisitor extends TestVisitorAdapter {
|
||||
|
||||
private final Object thisObj = new Object();
|
||||
private final Object targetObj = new Object();
|
||||
private final Object[] argsObjs = new Object[0];
|
||||
private boolean testsSubtypeSensitiveVars = false;
|
||||
|
||||
public boolean testsSubtypeSensitiveVars(Test aTest) {
|
||||
aTest.accept(this);
|
||||
return this.testsSubtypeSensitiveVars;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Instanceof i) {
|
||||
ReflectionVar v = (ReflectionVar) i.getVar();
|
||||
Object varUnderTest = v.getBindingAtJoinPoint(thisObj,targetObj,argsObjs);
|
||||
if ((varUnderTest == thisObj) || (varUnderTest == targetObj)) {
|
||||
this.testsSubtypeSensitiveVars = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(HasAnnotation hasAnn) {
|
||||
// If you thought things were bad before, now we sink to new levels of horror...
|
||||
ReflectionVar v = (ReflectionVar) hasAnn.getVar();
|
||||
int varType = getVarType(v);
|
||||
if ((varType == AT_THIS_VAR) || (varType == AT_TARGET_VAR) || (varType == AT_ANNOTATION_VAR)) {
|
||||
this.testsSubtypeSensitiveVars = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-91
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Implementation of {@link AspectInstanceFactory} that creates a new instance
|
||||
* of the specified aspect class for every {@link #getAspectInstance()} call.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0.4
|
||||
*/
|
||||
public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
|
||||
|
||||
private final Class aspectClass;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new SimpleAspectInstanceFactory for the given aspect class.
|
||||
* @param aspectClass the aspect class
|
||||
*/
|
||||
public SimpleAspectInstanceFactory(Class aspectClass) {
|
||||
Assert.notNull(aspectClass, "Aspect class must not be null");
|
||||
this.aspectClass = aspectClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the specified aspect class (never <code>null</code>).
|
||||
*/
|
||||
public final Class getAspectClass() {
|
||||
return this.aspectClass;
|
||||
}
|
||||
|
||||
|
||||
public final Object getAspectInstance() {
|
||||
try {
|
||||
return this.aspectClass.newInstance();
|
||||
}
|
||||
catch (InstantiationException ex) {
|
||||
throw new AopConfigException("Unable to instantiate aspect class [" + this.aspectClass.getName() + "]", ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new AopConfigException("Cannot access element class [" + this.aspectClass.getName() + "]", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public ClassLoader getAspectClassLoader() {
|
||||
return this.aspectClass.getClassLoader();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the order for this factory's aspect instance,
|
||||
* either an instance-specific order expressed through implementing
|
||||
* the {@link org.springframework.core.Ordered} interface,
|
||||
* or a fallback order.
|
||||
* @see org.springframework.core.Ordered
|
||||
* @see #getOrderForAspectClass
|
||||
*/
|
||||
public int getOrder() {
|
||||
return getOrderForAspectClass(this.aspectClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine a fallback order for the case that the aspect instance
|
||||
* does not express an instance-specific order through implementing
|
||||
* the {@link org.springframework.core.Ordered} interface.
|
||||
* <p>The default implementation simply returns <code>Ordered.LOWEST_PRECEDENCE</code>.
|
||||
* @param aspectClass the aspect class
|
||||
*/
|
||||
protected int getOrderForAspectClass(Class aspectClass) {
|
||||
return Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
}
|
||||
-81
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Implementation of {@link AspectInstanceFactory} that is backed by a
|
||||
* specified singleton object, returning the same instance for every
|
||||
* {@link #getAspectInstance()} call.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see SimpleAspectInstanceFactory
|
||||
*/
|
||||
public class SingletonAspectInstanceFactory implements AspectInstanceFactory {
|
||||
|
||||
private final Object aspectInstance;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new SingletonAspectInstanceFactory for the given aspect instance.
|
||||
* @param aspectInstance the singleton aspect instance
|
||||
*/
|
||||
public SingletonAspectInstanceFactory(Object aspectInstance) {
|
||||
Assert.notNull(aspectInstance, "Aspect instance must not be null");
|
||||
this.aspectInstance = aspectInstance;
|
||||
}
|
||||
|
||||
|
||||
public final Object getAspectInstance() {
|
||||
return this.aspectInstance;
|
||||
}
|
||||
|
||||
public ClassLoader getAspectClassLoader() {
|
||||
return this.aspectInstance.getClass().getClassLoader();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the order for this factory's aspect instance,
|
||||
* either an instance-specific order expressed through implementing
|
||||
* the {@link org.springframework.core.Ordered} interface,
|
||||
* or a fallback order.
|
||||
* @see org.springframework.core.Ordered
|
||||
* @see #getOrderForAspectClass
|
||||
*/
|
||||
public int getOrder() {
|
||||
if (this.aspectInstance instanceof Ordered) {
|
||||
return ((Ordered) this.aspectInstance).getOrder();
|
||||
}
|
||||
return getOrderForAspectClass(this.aspectInstance.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine a fallback order for the case that the aspect instance
|
||||
* does not express an instance-specific order through implementing
|
||||
* the {@link org.springframework.core.Ordered} interface.
|
||||
* <p>The default implementation simply returns <code>Ordered.LOWEST_PRECEDENCE</code>.
|
||||
* @param aspectClass the aspect class
|
||||
*/
|
||||
protected int getOrderForAspectClass(Class aspectClass) {
|
||||
return Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
}
|
||||
-115
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import org.aspectj.weaver.tools.PointcutParser;
|
||||
import org.aspectj.weaver.tools.TypePatternMatcher;
|
||||
|
||||
import org.springframework.aop.ClassFilter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Spring AOP {@link ClassFilter} implementation using AspectJ type matching.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
*/
|
||||
public class TypePatternClassFilter implements ClassFilter {
|
||||
|
||||
private String typePattern;
|
||||
|
||||
private TypePatternMatcher aspectJTypePatternMatcher;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance of the {@link TypePatternClassFilter} class.
|
||||
* <p>This is the JavaBean constructor; be sure to set the
|
||||
* {@link #setTypePattern(String) typePattern} property, else a
|
||||
* no doubt fatal {@link IllegalStateException} will be thrown
|
||||
* when the {@link #matches(Class)} method is first invoked.
|
||||
*/
|
||||
public TypePatternClassFilter() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a fully configured {@link TypePatternClassFilter} using the
|
||||
* given type pattern.
|
||||
* @param typePattern the type pattern that AspectJ weaver should parse
|
||||
* @throws IllegalArgumentException if the supplied <code>typePattern</code> is <code>null</code>
|
||||
* or is recognized as invalid
|
||||
*/
|
||||
public TypePatternClassFilter(String typePattern) {
|
||||
setTypePattern(typePattern);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the AspectJ type pattern to match.
|
||||
* <p>Examples include:
|
||||
* <code class="code">
|
||||
* org.springframework.beans.*
|
||||
* </code>
|
||||
* This will match any class or interface in the given package.
|
||||
* <code class="code">
|
||||
* org.springframework.beans.ITestBean+
|
||||
* </code>
|
||||
* This will match the <code>ITestBean</code> interface and any class
|
||||
* that implements it.
|
||||
* <p>These conventions are established by AspectJ, not Spring AOP.
|
||||
* @param typePattern the type pattern that AspectJ weaver should parse
|
||||
* @throws IllegalArgumentException if the supplied <code>typePattern</code> is <code>null</code>
|
||||
* or is recognized as invalid
|
||||
*/
|
||||
public void setTypePattern(String typePattern) {
|
||||
Assert.notNull(typePattern);
|
||||
this.typePattern = typePattern;
|
||||
this.aspectJTypePatternMatcher =
|
||||
PointcutParser.getPointcutParserSupportingAllPrimitivesAndUsingContextClassloaderForResolution().
|
||||
parseTypePattern(replaceBooleanOperators(typePattern));
|
||||
}
|
||||
|
||||
public String getTypePattern() {
|
||||
return typePattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the pointcut apply to the given interface or target class?
|
||||
* @param clazz candidate target class
|
||||
* @return whether the advice should apply to this candidate target class
|
||||
* @throws IllegalStateException if no {@link #setTypePattern(String)} has been set
|
||||
*/
|
||||
public boolean matches(Class clazz) {
|
||||
if (this.aspectJTypePatternMatcher == null) {
|
||||
throw new IllegalStateException("No 'typePattern' has been set via ctor/setter.");
|
||||
}
|
||||
return this.aspectJTypePatternMatcher.matches(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* If a type pattern has been specified in XML, the user cannot
|
||||
* write <code>and</code> as "&&" (though && will work).
|
||||
* We also allow <code>and</code> between two sub-expressions.
|
||||
* <p>This method converts back to <code>&&</code> for the AspectJ pointcut parser.
|
||||
*/
|
||||
private String replaceBooleanOperators(String pcExpr) {
|
||||
pcExpr = StringUtils.replace(pcExpr," and "," && ");
|
||||
pcExpr = StringUtils.replace(pcExpr, " or ", " || ");
|
||||
pcExpr = StringUtils.replace(pcExpr, " not ", " ! ");
|
||||
return pcExpr;
|
||||
}
|
||||
}
|
||||
-342
@@ -1,342 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.aspectj.lang.annotation.After;
|
||||
import org.aspectj.lang.annotation.AfterReturning;
|
||||
import org.aspectj.lang.annotation.AfterThrowing;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.AjType;
|
||||
import org.aspectj.lang.reflect.AjTypeSystem;
|
||||
import org.aspectj.lang.reflect.PerClauseKind;
|
||||
|
||||
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.PrioritizedParameterNameDiscoverer;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Abstract base class for factories that can create Spring AOP Advisors
|
||||
* given AspectJ classes from classes honoring the AspectJ 5 annotation syntax.
|
||||
*
|
||||
* <p>This class handles annotation parsing and validation functionality.
|
||||
* It does not actually generate Spring AOP Advisors, which is deferred to subclasses.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Adrian Colyer
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFactory {
|
||||
|
||||
protected static final ParameterNameDiscoverer ASPECTJ_ANNOTATION_PARAMETER_NAME_DISCOVERER =
|
||||
new AspectJAnnotationParameterNameDiscoverer();
|
||||
|
||||
private static final String AJC_MAGIC = "ajc$";
|
||||
|
||||
|
||||
/**
|
||||
* Find and return the first AspectJ annotation on the given method
|
||||
* (there <i>should</i> only be one anyway...)
|
||||
*/
|
||||
protected static AspectJAnnotation findAspectJAnnotationOnMethod(Method aMethod) {
|
||||
Class<? extends Annotation>[] classesToLookFor = (Class<? extends Annotation>[]) new Class[] {
|
||||
Before.class,
|
||||
Around.class,
|
||||
After.class,
|
||||
AfterReturning.class,
|
||||
AfterThrowing.class,
|
||||
Pointcut.class
|
||||
};
|
||||
for (Class<? extends Annotation> c : classesToLookFor) {
|
||||
AspectJAnnotation foundAnnotation = findAnnotation(aMethod, c);
|
||||
if (foundAnnotation != null) {
|
||||
return foundAnnotation;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
|
||||
A result = AnnotationUtils.findAnnotation(method, toLookFor);
|
||||
if (result != null) {
|
||||
return new AspectJAnnotation<A>(result);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Logger available to subclasses */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
protected final ParameterNameDiscoverer parameterNameDiscoverer;
|
||||
|
||||
|
||||
protected AbstractAspectJAdvisorFactory() {
|
||||
PrioritizedParameterNameDiscoverer prioritizedParameterNameDiscoverer = new PrioritizedParameterNameDiscoverer();
|
||||
prioritizedParameterNameDiscoverer.addDiscoverer(ASPECTJ_ANNOTATION_PARAMETER_NAME_DISCOVERER);
|
||||
this.parameterNameDiscoverer = prioritizedParameterNameDiscoverer;
|
||||
}
|
||||
|
||||
/**
|
||||
* We consider something to be an AspectJ aspect suitable for use by the Spring AOP system
|
||||
* if it has the @Aspect annotation, and was not compiled by ajc. The reason for this latter test
|
||||
* is that aspects written in the code-style (AspectJ language) also have the annotation present
|
||||
* when compiled by ajc with the -1.5 flag, yet they cannot be consumed by Spring AOP.
|
||||
*/
|
||||
public boolean isAspect(Class<?> clazz) {
|
||||
return (AjTypeSystem.getAjType(clazz).isAspect() &&
|
||||
hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
|
||||
}
|
||||
|
||||
private boolean hasAspectAnnotation(Class<?> clazz) {
|
||||
return clazz.isAnnotationPresent(Aspect.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* We need to detect this as "code-style" AspectJ aspects should not be
|
||||
* interpreted by Spring AOP.
|
||||
*/
|
||||
private boolean compiledByAjc(Class<?> clazz) {
|
||||
// The AJTypeSystem goes to great lengths to provide a uniform appearance between code-style and
|
||||
// annotation-style aspects. Therefore there is no 'clean' way to tell them apart. Here we rely on
|
||||
// an implementation detail of the AspectJ compiler.
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
if (field.getName().startsWith(AJC_MAGIC)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void validate(Class<?> aspectClass) throws AopConfigException {
|
||||
// If the parent has the annotation and isn't abstract it's an error
|
||||
if (aspectClass.getSuperclass().getAnnotation(Aspect.class) != null &&
|
||||
!Modifier.isAbstract(aspectClass.getSuperclass().getModifiers())) {
|
||||
throw new AopConfigException("[" + aspectClass.getName() + "] cannot extend concrete aspect [" +
|
||||
aspectClass.getSuperclass().getName() + "]");
|
||||
}
|
||||
|
||||
AjType<?> ajType = AjTypeSystem.getAjType(aspectClass);
|
||||
if (!ajType.isAspect()) {
|
||||
throw new NotAnAtAspectException(aspectClass);
|
||||
}
|
||||
if (ajType.getPerClause().getKind() == PerClauseKind.PERCFLOW) {
|
||||
throw new AopConfigException(aspectClass.getName() + " uses percflow instantiation model: " +
|
||||
"This is not supported in Spring AOP.");
|
||||
}
|
||||
if (ajType.getPerClause().getKind() == PerClauseKind.PERCFLOWBELOW) {
|
||||
throw new AopConfigException(aspectClass.getName() + " uses percflowbelow instantiation model: " +
|
||||
"This is not supported in Spring AOP.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The pointcut and advice annotations both have an "argNames" member which contains a
|
||||
* comma-separated list of the argument names. We use this (if non-empty) to build the
|
||||
* formal parameters for the pointcut.
|
||||
*/
|
||||
protected AspectJExpressionPointcut createPointcutExpression(
|
||||
Method annotatedMethod, Class declarationScope, String[] pointcutParameterNames) {
|
||||
|
||||
Class<?> [] pointcutParameterTypes = new Class<?>[0];
|
||||
if (pointcutParameterNames != null) {
|
||||
pointcutParameterTypes = extractPointcutParameterTypes(pointcutParameterNames,annotatedMethod);
|
||||
}
|
||||
|
||||
AspectJExpressionPointcut ajexp =
|
||||
new AspectJExpressionPointcut(declarationScope,pointcutParameterNames,pointcutParameterTypes);
|
||||
ajexp.setLocation(annotatedMethod.toString());
|
||||
return ajexp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the pointcut parameters needed by aspectj based on the given argument names
|
||||
* and the argument types that are available from the adviceMethod. Needs to take into
|
||||
* account (ignore) any JoinPoint based arguments as these are not pointcut context but
|
||||
* rather part of the advice execution context (thisJoinPoint, thisJoinPointStaticPart)
|
||||
*/
|
||||
private Class<?>[] extractPointcutParameterTypes(String[] argNames, Method adviceMethod) {
|
||||
Class<?>[] ret = new Class<?>[argNames.length];
|
||||
Class<?>[] paramTypes = adviceMethod.getParameterTypes();
|
||||
if (argNames.length > paramTypes.length) {
|
||||
throw new IllegalStateException("Expecting at least " + argNames.length +
|
||||
" arguments in the advice declaration, but only found " + paramTypes.length);
|
||||
}
|
||||
// Make the simplifying assumption for now that all of the JoinPoint based arguments
|
||||
// come first in the advice declaration.
|
||||
int typeOffset = paramTypes.length - argNames.length;
|
||||
for (int i = 0; i < ret.length; i++) {
|
||||
ret[i] = paramTypes[i+typeOffset];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
protected enum AspectJAnnotationType {
|
||||
AtPointcut,
|
||||
AtBefore,
|
||||
AtAfter,
|
||||
AtAfterReturning,
|
||||
AtAfterThrowing,
|
||||
AtAround
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class modelling an AspectJ annotation, exposing its type enumeration and
|
||||
* pointcut String.
|
||||
*/
|
||||
protected static class AspectJAnnotation<A extends Annotation> {
|
||||
|
||||
private static Map<Class,AspectJAnnotationType> annotationTypes = new HashMap<Class,AspectJAnnotationType>();
|
||||
|
||||
private static final String[] EXPRESSION_PROPERTIES = new String[]{"value", "pointcut"};
|
||||
|
||||
static {
|
||||
annotationTypes.put(Pointcut.class,AspectJAnnotationType.AtPointcut);
|
||||
annotationTypes.put(After.class,AspectJAnnotationType.AtAfter);
|
||||
annotationTypes.put(AfterReturning.class,AspectJAnnotationType.AtAfterReturning);
|
||||
annotationTypes.put(AfterThrowing.class,AspectJAnnotationType.AtAfterThrowing);
|
||||
annotationTypes.put(Around.class,AspectJAnnotationType.AtAround);
|
||||
annotationTypes.put(Before.class,AspectJAnnotationType.AtBefore);
|
||||
}
|
||||
|
||||
private final A annotation;
|
||||
private AspectJAnnotationType annotationType;
|
||||
private final String expression;
|
||||
private final String argNames;
|
||||
|
||||
public AspectJAnnotation(A aspectjAnnotation) {
|
||||
this.annotation = aspectjAnnotation;
|
||||
for (Class type : annotationTypes.keySet()) {
|
||||
if (type.isInstance(this.annotation)) {
|
||||
this.annotationType = annotationTypes.get(type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (this.annotationType == null) {
|
||||
throw new IllegalStateException("Unknown annotation type: " + this.annotation.toString());
|
||||
}
|
||||
|
||||
// We know these methods exist with the same name on each object,
|
||||
// but need to invoke them reflectively as there isn't a common interface.
|
||||
try {
|
||||
this.expression = resolveExpression();
|
||||
this.argNames = (String)
|
||||
this.annotation.getClass().getMethod("argNames", (Class[]) null).invoke(this.annotation);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalArgumentException(aspectjAnnotation + " cannot be an AspectJ annotation", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveExpression() throws Exception {
|
||||
String expression = null;
|
||||
for (int i = 0; i < EXPRESSION_PROPERTIES.length; i++) {
|
||||
String methodName = EXPRESSION_PROPERTIES[i];
|
||||
Method method;
|
||||
try {
|
||||
method = this.annotation.getClass().getDeclaredMethod(methodName);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
method = null;
|
||||
}
|
||||
if (method != null) {
|
||||
String candidate = (String) method.invoke(this.annotation);
|
||||
if (StringUtils.hasText(candidate)) {
|
||||
expression = candidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
|
||||
public AspectJAnnotationType getAnnotationType() {
|
||||
return this.annotationType;
|
||||
}
|
||||
|
||||
public A getAnnotation() {
|
||||
return this.annotation;
|
||||
}
|
||||
|
||||
public String getPointcutExpression() {
|
||||
return this.expression;
|
||||
}
|
||||
|
||||
public String getArgNames() {
|
||||
return this.argNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.annotation.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ParameterNameDiscoverer implementation that analyzes the arg names
|
||||
* specified at the AspectJ annotation level.
|
||||
*/
|
||||
private static class AspectJAnnotationParameterNameDiscoverer implements ParameterNameDiscoverer {
|
||||
|
||||
public String[] getParameterNames(Method method) {
|
||||
if (method.getParameterTypes().length == 0) {
|
||||
return new String[0];
|
||||
}
|
||||
AspectJAnnotation annotation = findAspectJAnnotationOnMethod(method);
|
||||
if (annotation == null) {
|
||||
return null;
|
||||
}
|
||||
StringTokenizer strTok = new StringTokenizer(annotation.getArgNames(), ",");
|
||||
if (strTok.countTokens() > 0) {
|
||||
String[] names = new String[strTok.countTokens()];
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
names[i] = strTok.nextToken();
|
||||
}
|
||||
return names;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getParameterNames(Constructor ctor) {
|
||||
throw new UnsupportedOperationException("Spring AOP cannot handle constructor advice");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-140
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link AspectJAwareAdvisorAutoProxyCreator} subclass that processes all AspectJ
|
||||
* annotation aspects in the current application context, as well as Spring Advisors.
|
||||
*
|
||||
* <p>Any AspectJ annotated classes will automatically be recognized, and their
|
||||
* advice applied if Spring AOP's proxy-based model is capable of applying it.
|
||||
* This covers method execution joinpoints.
|
||||
*
|
||||
* <p>If the <aop:include> element is used, only @AspectJ beans with names matched by
|
||||
* an include pattern will be considered as defining aspects to use for Spring auto-proxying.
|
||||
*
|
||||
* <p>Processing of Spring Advisors follows the rules established in
|
||||
* {@link org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator}.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see org.springframework.aop.aspectj.annotation.AspectJAdvisorFactory
|
||||
*/
|
||||
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
|
||||
|
||||
private List<Pattern> includePatterns;
|
||||
|
||||
private AspectJAdvisorFactory aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory();
|
||||
|
||||
private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;
|
||||
|
||||
|
||||
/**
|
||||
* Set a list of regex patterns, matching eligible @AspectJ bean names.
|
||||
* <p>Default is to consider all @AspectJ beans as eligible.
|
||||
*/
|
||||
public void setIncludePatterns(List<String> patterns) {
|
||||
this.includePatterns = new ArrayList<Pattern>(patterns.size());
|
||||
for (String patternText : patterns) {
|
||||
this.includePatterns.add(Pattern.compile(patternText));
|
||||
}
|
||||
}
|
||||
|
||||
public void setAspectJAdvisorFactory(AspectJAdvisorFactory aspectJAdvisorFactory) {
|
||||
Assert.notNull(this.aspectJAdvisorFactory, "AspectJAdvisorFactory must not be null");
|
||||
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
|
||||
super.initBeanFactory(beanFactory);
|
||||
this.aspectJAdvisorsBuilder =
|
||||
new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected List findCandidateAdvisors() {
|
||||
// Add all the Spring advisors found according to superclass rules.
|
||||
List advisors = super.findCandidateAdvisors();
|
||||
// Build Advisors for all AspectJ aspects in the bean factory.
|
||||
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
|
||||
return advisors;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isInfrastructureClass(Class beanClass) {
|
||||
// Previously we setProxyTargetClass(true) in the constructor, but that has too
|
||||
// broad an impact. Instead we now override isInfrastructureClass to avoid proxying
|
||||
// aspects. I'm not entirely happy with that as there is no good reason not
|
||||
// to advise aspects, except that it causes advice invocation to go through a
|
||||
// proxy, and if the aspect implements e.g the Ordered interface it will be
|
||||
// proxied by that interface and fail at runtime as the advice method is not
|
||||
// defined on the interface. We could potentially relax the restriction about
|
||||
// not advising aspects in the future.
|
||||
return (super.isInfrastructureClass(beanClass) || this.aspectJAdvisorFactory.isAspect(beanClass));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given aspect bean is eligible for auto-proxying.
|
||||
* <p>If no <aop:include> elements were used then "includePatterns" will be
|
||||
* <code>null</code> and all beans are included. If "includePatterns" is non-null,
|
||||
* then one of the patterns must match.
|
||||
*/
|
||||
protected boolean isEligibleAspectBean(String beanName) {
|
||||
if (this.includePatterns == null) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
for (Pattern pattern : this.includePatterns) {
|
||||
if (pattern.matcher(beanName).matches()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of BeanFactoryAspectJAdvisorsBuilderAdapter that delegates to
|
||||
* surrounding AnnotationAwareAspectJAutoProxyCreator facilities.
|
||||
*/
|
||||
private class BeanFactoryAspectJAdvisorsBuilderAdapter extends BeanFactoryAspectJAdvisorsBuilder {
|
||||
|
||||
public BeanFactoryAspectJAdvisorsBuilderAdapter(
|
||||
ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {
|
||||
super(beanFactory, advisorFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEligibleBean(String beanName) {
|
||||
return AnnotationAwareAspectJAutoProxyCreator.this.isEligibleAspectBean(beanName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-104
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
|
||||
/**
|
||||
* Interface for factories that can create Spring AOP Advisors from classes
|
||||
* annotated with AspectJ annotation syntax.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see AspectMetadata
|
||||
* @see org.aspectj.lang.reflect.AjTypeSystem
|
||||
*/
|
||||
public interface AspectJAdvisorFactory {
|
||||
|
||||
/**
|
||||
* Determine whether or not the given class is an aspect, as reported
|
||||
* by AspectJ's {@link org.aspectj.lang.reflect.AjTypeSystem}.
|
||||
* <p>Will simply return <code>false</code> if the supposed aspect is
|
||||
* invalid (such as an extension of a concrete aspect class).
|
||||
* Will return true for some aspects that Spring AOP cannot process,
|
||||
* such as those with unsupported instantiation models.
|
||||
* Use the {@link #validate} method to handle these cases if necessary.
|
||||
* @param clazz the supposed annotation-style AspectJ class
|
||||
* @return whether or not this class is recognized by AspectJ as an aspect class
|
||||
*/
|
||||
boolean isAspect(Class<?> clazz);
|
||||
|
||||
/**
|
||||
* Is the given class a valid AspectJ aspect class?
|
||||
* @param aspectClass the supposed AspectJ annotation-style class to validate
|
||||
* @throws AopConfigException if the class is an invalid aspect
|
||||
* (which can never be legal)
|
||||
* @throws NotAnAtAspectException if the class is not an aspect at all
|
||||
* (which may or may not be legal, depending on the context)
|
||||
*/
|
||||
void validate(Class<?> aspectClass) throws AopConfigException;
|
||||
|
||||
/**
|
||||
* Build Spring AOP Advisors for all annotated At-AspectJ methods
|
||||
* on the specified aspect instance.
|
||||
* @param aif the aspect instance factory (not the aspect instance itself
|
||||
* in order to avoid eager instantiation)
|
||||
* @return a list of advisors for this class
|
||||
*/
|
||||
List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aif);
|
||||
|
||||
/**
|
||||
* Build a Spring AOP Advisor for the given AspectJ advice method.
|
||||
* @param candidateAdviceMethod the candidate advice method
|
||||
* @param aif the aspect instance factory
|
||||
* @param declarationOrderInAspect the declaration order within the aspect
|
||||
* @param aspectName the name of the aspect
|
||||
* @return <code>null</code> if the method is not an AspectJ advice method
|
||||
* or if it is a pointcut that will be used by other advice but will not
|
||||
* create a Spring advice in its own right
|
||||
*/
|
||||
Advisor getAdvisor(Method candidateAdviceMethod,
|
||||
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName);
|
||||
|
||||
/**
|
||||
* Build a Spring AOP Advice for the given AspectJ advice method.
|
||||
* @param candidateAdviceMethod the candidate advice method
|
||||
* @param pointcut the corresponding AspectJ expression pointcut
|
||||
* @param aif the aspect instance factory
|
||||
* @param declarationOrderInAspect the declaration order within the aspect
|
||||
* @param aspectName the name of the aspect
|
||||
* @return <code>null</code> if the method is not an AspectJ advice method
|
||||
* or if it is a pointcut that will be used by other advice but will not
|
||||
* create a Spring advice in its own right
|
||||
* @see org.springframework.aop.aspectj.AspectJAroundAdvice
|
||||
* @see org.springframework.aop.aspectj.AspectJMethodBeforeAdvice
|
||||
* @see org.springframework.aop.aspectj.AspectJAfterAdvice
|
||||
* @see org.springframework.aop.aspectj.AspectJAfterReturningAdvice
|
||||
* @see org.springframework.aop.aspectj.AspectJAfterThrowingAdvice
|
||||
*/
|
||||
Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut pointcut,
|
||||
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName);
|
||||
|
||||
}
|
||||
-210
@@ -1,210 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.aspectj.lang.reflect.PerClauseKind;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.aspectj.AspectJProxyUtils;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.aop.framework.ProxyCreatorSupport;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.core.OrderComparator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* AspectJ-based proxy factory, allowing for programmatic building
|
||||
* of proxies which include AspectJ aspects (code style as well
|
||||
* Java 5 annotation style).
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.0
|
||||
* @see #addAspect(Object)
|
||||
* @see #addAspect(Class)
|
||||
* @see #getProxy()
|
||||
* @see #getProxy(ClassLoader)
|
||||
* @see org.springframework.aop.framework.ProxyFactory
|
||||
*/
|
||||
public class AspectJProxyFactory extends ProxyCreatorSupport {
|
||||
|
||||
/** Cache for singleton aspect instances */
|
||||
private static final Map<Class, Object> aspectCache = new HashMap<Class, Object>();
|
||||
|
||||
private final AspectJAdvisorFactory aspectFactory = new ReflectiveAspectJAdvisorFactory();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new AspectJProxyFactory.
|
||||
*/
|
||||
public AspectJProxyFactory() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new AspectJProxyFactory.
|
||||
* <p>Will proxy all interfaces that the given target implements.
|
||||
* @param target the target object to be proxied
|
||||
*/
|
||||
public AspectJProxyFactory(Object target) {
|
||||
Assert.notNull(target, "Target object must not be null");
|
||||
setInterfaces(ClassUtils.getAllInterfaces(target));
|
||||
setTarget(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new <code>AspectJProxyFactory</code>.
|
||||
* No target, only interfaces. Must add interceptors.
|
||||
*/
|
||||
public AspectJProxyFactory(Class[] interfaces) {
|
||||
setInterfaces(interfaces);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the supplied aspect instance to the chain. The type of the aspect instance
|
||||
* supplied must be a singleton aspect. True singleton lifecycle is not honoured when
|
||||
* using this method - the caller is responsible for managing the lifecycle of any
|
||||
* aspects added in this way.
|
||||
* @param aspectInstance the AspectJ aspect instance
|
||||
*/
|
||||
public void addAspect(Object aspectInstance) {
|
||||
Class aspectClass = aspectInstance.getClass();
|
||||
String aspectName = aspectClass.getName();
|
||||
AspectMetadata am = createAspectMetadata(aspectClass, aspectName);
|
||||
if (am.getAjType().getPerClause().getKind() != PerClauseKind.SINGLETON) {
|
||||
throw new IllegalArgumentException(
|
||||
"Aspect class [" + aspectClass.getName() + "] does not define a singleton aspect");
|
||||
}
|
||||
addAdvisorsFromAspectInstanceFactory(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(aspectInstance, aspectName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an aspect of the supplied type to the end of the advice chain.
|
||||
* @param aspectClass the AspectJ aspect class
|
||||
*/
|
||||
public void addAspect(Class aspectClass) {
|
||||
String aspectName = aspectClass.getName();
|
||||
AspectMetadata am = createAspectMetadata(aspectClass, aspectName);
|
||||
MetadataAwareAspectInstanceFactory instanceFactory = createAspectInstanceFactory(am, aspectClass, aspectName);
|
||||
addAdvisorsFromAspectInstanceFactory(instanceFactory);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add all {@link Advisor Advisors} from the supplied {@link MetadataAwareAspectInstanceFactory}
|
||||
* to the current chain. Exposes any special purpose {@link Advisor Advisors} if needed.
|
||||
* @see #makeAdvisorChainAspectJCapableIfNecessary()
|
||||
*/
|
||||
private void addAdvisorsFromAspectInstanceFactory(MetadataAwareAspectInstanceFactory instanceFactory) {
|
||||
List<Advisor> advisors = this.aspectFactory.getAdvisors(instanceFactory);
|
||||
advisors = AopUtils.findAdvisorsThatCanApply(advisors, getTargetClass());
|
||||
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(advisors);
|
||||
OrderComparator.sort(advisors);
|
||||
addAdvisors(advisors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an {@link AspectMetadata} instance for the supplied aspect type.
|
||||
*/
|
||||
private AspectMetadata createAspectMetadata(Class aspectClass, String aspectName) {
|
||||
AspectMetadata am = new AspectMetadata(aspectClass, aspectName);
|
||||
if (!am.getAjType().isAspect()) {
|
||||
throw new IllegalArgumentException("Class [" + aspectClass.getName() + "] is not a valid aspect type");
|
||||
}
|
||||
return am;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MetadataAwareAspectInstanceFactory} for the supplied aspect type. If the aspect type
|
||||
* has no per clause, then a {@link SingletonMetadataAwareAspectInstanceFactory} is returned, otherwise
|
||||
* a {@link PrototypeAspectInstanceFactory} is returned.
|
||||
*/
|
||||
private MetadataAwareAspectInstanceFactory createAspectInstanceFactory(
|
||||
AspectMetadata am, Class aspectClass, String aspectName) {
|
||||
|
||||
MetadataAwareAspectInstanceFactory instanceFactory = null;
|
||||
if (am.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
|
||||
// Create a shared aspect instance.
|
||||
Object instance = getSingletonAspectInstance(aspectClass);
|
||||
instanceFactory = new SingletonMetadataAwareAspectInstanceFactory(instance, aspectName);
|
||||
}
|
||||
else {
|
||||
// Create a factory for independent aspect instances.
|
||||
instanceFactory = new SimpleMetadataAwareAspectInstanceFactory(aspectClass, aspectName);
|
||||
}
|
||||
return instanceFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the singleton aspect instance for the supplied aspect type. An instance
|
||||
* is created if one cannot be found in the instance cache.
|
||||
*/
|
||||
private Object getSingletonAspectInstance(Class aspectClass) {
|
||||
synchronized (aspectCache) {
|
||||
Object instance = aspectCache.get(aspectClass);
|
||||
if (instance != null) {
|
||||
return instance;
|
||||
}
|
||||
try {
|
||||
instance = aspectClass.newInstance();
|
||||
aspectCache.put(aspectClass, instance);
|
||||
return instance;
|
||||
}
|
||||
catch (InstantiationException ex) {
|
||||
throw new AopConfigException("Unable to instantiate aspect class [" + aspectClass.getName() + "]", ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new AopConfigException("Cannot access aspect class [" + aspectClass.getName() + "]", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new proxy according to the settings in this factory.
|
||||
* <p>Can be called repeatedly. Effect will vary if we've added
|
||||
* or removed interfaces. Can add and remove interceptors.
|
||||
* <p>Uses a default class loader: Usually, the thread context class loader
|
||||
* (if necessary for proxy creation).
|
||||
* @return the new proxy
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getProxy() {
|
||||
return (T) createAopProxy().getProxy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new proxy according to the settings in this factory.
|
||||
* <p>Can be called repeatedly. Effect will vary if we've added
|
||||
* or removed interfaces. Can add and remove interceptors.
|
||||
* <p>Uses the given class loader (if necessary for proxy creation).
|
||||
* @param classLoader the class loader to create the proxy with
|
||||
* @return the new proxy
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getProxy(ClassLoader classLoader) {
|
||||
return (T) createAopProxy().getProxy(classLoader);
|
||||
}
|
||||
|
||||
}
|
||||
-166
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.reflect.AjType;
|
||||
import org.aspectj.lang.reflect.AjTypeSystem;
|
||||
import org.aspectj.lang.reflect.PerClauseKind;
|
||||
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
|
||||
import org.springframework.aop.aspectj.TypePatternClassFilter;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.aop.support.ComposablePointcut;
|
||||
|
||||
/**
|
||||
* Metadata for an AspectJ aspect class, with an additional Spring AOP pointcut
|
||||
* for the per clause.
|
||||
*
|
||||
* <p>Uses AspectJ 5 AJType reflection API, so is only supported on Java 5.
|
||||
* Enables us to work with different AspectJ instantiation models such as
|
||||
* "singleton", "pertarget" and "perthis".
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see org.springframework.aop.aspectj.AspectJExpressionPointcut
|
||||
*/
|
||||
public class AspectMetadata {
|
||||
|
||||
/**
|
||||
* AspectJ reflection information (AspectJ 5 / Java 5 specific).
|
||||
*/
|
||||
private final AjType ajType;
|
||||
|
||||
/**
|
||||
* Spring AOP pointcut corresponding to the per clause of the
|
||||
* aspect. Will be the Pointcut.TRUE canonical instance in the
|
||||
* case of a singleton, otherwise an AspectJExpressionPointcut.
|
||||
*/
|
||||
private final Pointcut perClausePointcut;
|
||||
|
||||
/**
|
||||
* The name of this aspect as defined to Spring (the bean name) -
|
||||
* allows us to determine if two pieces of advice come from the
|
||||
* same aspect and hence their relative precedence.
|
||||
*/
|
||||
private String aspectName;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new AspectMetadata instance for the given aspect class.
|
||||
* @param aspectClass the aspect class
|
||||
* @param aspectName the name of the aspect
|
||||
*/
|
||||
public AspectMetadata(Class aspectClass, String aspectName) {
|
||||
this.aspectName = aspectName;
|
||||
this.ajType = AjTypeSystem.getAjType(aspectClass);
|
||||
|
||||
if (!this.ajType.isAspect()) {
|
||||
throw new IllegalArgumentException("Class '" + aspectClass.getName() + "' is not an @AspectJ aspect");
|
||||
}
|
||||
if (this.ajType.getDeclarePrecedence().length > 0) {
|
||||
throw new IllegalArgumentException("DeclarePrecendence not presently supported in Spring AOP");
|
||||
}
|
||||
|
||||
switch (this.ajType.getPerClause().getKind()) {
|
||||
case SINGLETON :
|
||||
this.perClausePointcut = Pointcut.TRUE;
|
||||
return;
|
||||
case PERTARGET : case PERTHIS :
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setLocation("@Aspect annotation on " + aspectClass.getName());
|
||||
ajexp.setExpression(findPerClause(aspectClass));
|
||||
this.perClausePointcut = ajexp;
|
||||
return;
|
||||
case PERTYPEWITHIN :
|
||||
// Works with a type pattern
|
||||
this.perClausePointcut = new ComposablePointcut(new TypePatternClassFilter(findPerClause(aspectClass)));
|
||||
return;
|
||||
default :
|
||||
throw new AopConfigException(
|
||||
"PerClause " + ajType.getPerClause().getKind() + " not supported by Spring AOP for " + aspectClass);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract contents from String of form <code>pertarget(contents)</code>.
|
||||
*/
|
||||
private String findPerClause(Class<?> aspectClass) {
|
||||
// TODO when AspectJ provides this, we can remove this hack. Hence we don't
|
||||
// bother to make it elegant. Or efficient. Or robust :-)
|
||||
String str = aspectClass.getAnnotation(Aspect.class).value();
|
||||
str = str.substring(str.indexOf("(") + 1);
|
||||
str = str.substring(0, str.length() - 1);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return AspectJ reflection information.
|
||||
*/
|
||||
public AjType getAjType() {
|
||||
return this.ajType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the aspect class.
|
||||
*/
|
||||
public Class getAspectClass() {
|
||||
return this.ajType.getJavaClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the aspect class.
|
||||
*/
|
||||
public String getAspectName() {
|
||||
return this.aspectName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Spring pointcut expression for a singleton aspect.
|
||||
* (e.g. <code>Pointcut.TRUE</code> if it's a singleton).
|
||||
*/
|
||||
public Pointcut getPerClausePointcut() {
|
||||
return this.perClausePointcut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the aspect is defined as "perthis" or "pertarget".
|
||||
*/
|
||||
public boolean isPerThisOrPerTarget() {
|
||||
PerClauseKind kind = getAjType().getPerClause().getKind();
|
||||
return (kind == PerClauseKind.PERTARGET || kind == PerClauseKind.PERTHIS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the aspect is defined as "pertypewithin".
|
||||
*/
|
||||
public boolean isPerTypeWithin() {
|
||||
PerClauseKind kind = getAjType().getPerClause().getKind();
|
||||
return (kind == PerClauseKind.PERTYPEWITHIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the aspect needs to be lazily instantiated.
|
||||
*/
|
||||
public boolean isLazilyInstantiated() {
|
||||
return (isPerThisOrPerTarget() || isPerTypeWithin());
|
||||
}
|
||||
|
||||
}
|
||||
-122
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.aop.aspectj.AspectInstanceFactory} implementation
|
||||
* backed by a Spring {@link org.springframework.beans.factory.BeanFactory}.
|
||||
*
|
||||
* <p>Note that this may instantiate multiple times if using a prototype,
|
||||
* which probably won't give the semantics you expect.
|
||||
* Use a {@link LazySingletonAspectInstanceFactoryDecorator}
|
||||
* to wrap this to ensure only one new aspect comes back.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see LazySingletonAspectInstanceFactoryDecorator
|
||||
*/
|
||||
public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInstanceFactory {
|
||||
|
||||
private final BeanFactory beanFactory;
|
||||
|
||||
private final String name;
|
||||
|
||||
private final AspectMetadata aspectMetadata;
|
||||
|
||||
|
||||
/**
|
||||
* Create a BeanFactoryAspectInstanceFactory. AspectJ will be called to
|
||||
* introspect to create AJType metadata using the type returned for the
|
||||
* given bean name from the BeanFactory.
|
||||
* @param beanFactory BeanFactory to obtain instance(s) from
|
||||
* @param name name of the bean
|
||||
*/
|
||||
public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name) {
|
||||
this(beanFactory, name, beanFactory.getType(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a BeanFactoryAspectInstanceFactory, providing a type that AspectJ should
|
||||
* introspect to create AJType metadata. Use if the BeanFactory may consider the type
|
||||
* to be a subclass (as when using CGLIB), and the information should relate to a superclass.
|
||||
* @param beanFactory BeanFactory to obtain instance(s) from
|
||||
* @param name the name of the bean
|
||||
* @param type the type that should be introspected by AspectJ
|
||||
*/
|
||||
public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name, Class type) {
|
||||
this.beanFactory = beanFactory;
|
||||
this.name = name;
|
||||
this.aspectMetadata = new AspectMetadata(type, name);
|
||||
}
|
||||
|
||||
|
||||
public Object getAspectInstance() {
|
||||
return this.beanFactory.getBean(this.name);
|
||||
}
|
||||
|
||||
public ClassLoader getAspectClassLoader() {
|
||||
if (this.beanFactory instanceof ConfigurableBeanFactory) {
|
||||
return ((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader();
|
||||
}
|
||||
else {
|
||||
return ClassUtils.getDefaultClassLoader();
|
||||
}
|
||||
}
|
||||
|
||||
public AspectMetadata getAspectMetadata() {
|
||||
return this.aspectMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the order for this factory's target aspect, either
|
||||
* an instance-specific order expressed through implementing the
|
||||
* {@link org.springframework.core.Ordered} interface (only
|
||||
* checked for singleton beans), or an order expressed through the
|
||||
* {@link org.springframework.core.annotation.Order} annotation
|
||||
* at the class level.
|
||||
* @see org.springframework.core.Ordered
|
||||
* @see org.springframework.core.annotation.Order
|
||||
*/
|
||||
public int getOrder() {
|
||||
Class<?> type = this.beanFactory.getType(this.name);
|
||||
if (type != null) {
|
||||
if (Ordered.class.isAssignableFrom(type) && this.beanFactory.isSingleton(this.name)) {
|
||||
return ((Ordered) this.beanFactory.getBean(this.name)).getOrder();
|
||||
}
|
||||
Order order = type.getAnnotation(Order.class);
|
||||
if (order != null) {
|
||||
return order.value();
|
||||
}
|
||||
}
|
||||
return Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + ": bean name '" + this.name + "'";
|
||||
}
|
||||
|
||||
}
|
||||
-162
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.aspectj.lang.reflect.PerClauseKind;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Helper for retrieving @AspectJ beans from a BeanFactory and building
|
||||
* Spring Advisors based on them, for use with auto-proxying.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0.2
|
||||
* @see AnnotationAwareAspectJAutoProxyCreator
|
||||
*/
|
||||
public class BeanFactoryAspectJAdvisorsBuilder {
|
||||
|
||||
private final ListableBeanFactory beanFactory;
|
||||
|
||||
private final AspectJAdvisorFactory advisorFactory;
|
||||
|
||||
private List<String> aspectBeanNames;
|
||||
|
||||
private final Map<String, List<Advisor>> advisorsCache = new HashMap<String, List<Advisor>>();
|
||||
|
||||
private final Map<String, MetadataAwareAspectInstanceFactory> aspectFactoryCache =
|
||||
new HashMap<String, MetadataAwareAspectInstanceFactory>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new BeanFactoryAspectJAdvisorsBuilder for the given BeanFactory.
|
||||
* @param beanFactory the ListableBeanFactory to scan
|
||||
*/
|
||||
public BeanFactoryAspectJAdvisorsBuilder(ListableBeanFactory beanFactory) {
|
||||
this(beanFactory, new ReflectiveAspectJAdvisorFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new BeanFactoryAspectJAdvisorsBuilder for the given BeanFactory.
|
||||
* @param beanFactory the ListableBeanFactory to scan
|
||||
* @param advisorFactory the AspectJAdvisorFactory to build each Advisor with
|
||||
*/
|
||||
public BeanFactoryAspectJAdvisorsBuilder(ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {
|
||||
Assert.notNull(beanFactory, "ListableBeanFactory must not be null");
|
||||
Assert.notNull(advisorFactory, "AspectJAdvisorFactory must not be null");
|
||||
this.beanFactory = beanFactory;
|
||||
this.advisorFactory = advisorFactory;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Look for AspectJ-annotated aspect beans in the current bean factory,
|
||||
* and return to a list of Spring AOP Advisors representing them.
|
||||
* <p>Creates a Spring Advisor for each AspectJ advice method.
|
||||
* @return the list of {@link org.springframework.aop.Advisor} beans
|
||||
* @see #isEligibleBean
|
||||
*/
|
||||
public List<Advisor> buildAspectJAdvisors() {
|
||||
List<String> aspectNames = null;
|
||||
|
||||
synchronized (this) {
|
||||
aspectNames = this.aspectBeanNames;
|
||||
if (aspectNames == null) {
|
||||
List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
aspectNames = new LinkedList<String>();
|
||||
String[] beanNames =
|
||||
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
|
||||
for (String beanName : beanNames) {
|
||||
if (!isEligibleBean(beanName)) {
|
||||
continue;
|
||||
}
|
||||
// We must be careful not to instantiate beans eagerly as in this
|
||||
// case they would be cached by the Spring container but would not
|
||||
// have been weaved
|
||||
Class beanType = this.beanFactory.getType(beanName);
|
||||
if (beanType == null) {
|
||||
continue;
|
||||
}
|
||||
if (this.advisorFactory.isAspect(beanType)) {
|
||||
aspectNames.add(beanName);
|
||||
AspectMetadata amd = new AspectMetadata(beanType, beanName);
|
||||
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
|
||||
MetadataAwareAspectInstanceFactory factory =
|
||||
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
|
||||
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
|
||||
if (this.beanFactory.isSingleton(beanName)) {
|
||||
this.advisorsCache.put(beanName, classAdvisors);
|
||||
}
|
||||
else {
|
||||
this.aspectFactoryCache.put(beanName, factory);
|
||||
}
|
||||
advisors.addAll(classAdvisors);
|
||||
}
|
||||
else {
|
||||
// Per target or per this.
|
||||
if (this.beanFactory.isSingleton(beanName)) {
|
||||
throw new IllegalArgumentException("Bean with name '" + beanName +
|
||||
"' is a singleton, but aspect instantiation model is not singleton");
|
||||
}
|
||||
MetadataAwareAspectInstanceFactory factory =
|
||||
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
|
||||
this.aspectFactoryCache.put(beanName, factory);
|
||||
advisors.addAll(this.advisorFactory.getAdvisors(factory));
|
||||
}
|
||||
}
|
||||
}
|
||||
this.aspectBeanNames = aspectNames;
|
||||
return advisors;
|
||||
}
|
||||
}
|
||||
|
||||
if (aspectNames.isEmpty()) {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
for (String aspectName : aspectNames) {
|
||||
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
|
||||
if (cachedAdvisors != null) {
|
||||
advisors.addAll(cachedAdvisors);
|
||||
}
|
||||
else {
|
||||
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
|
||||
advisors.addAll(this.advisorFactory.getAdvisors(factory));
|
||||
}
|
||||
}
|
||||
return advisors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the aspect bean with the given name is eligible.
|
||||
* @param beanName the name of the aspect bean
|
||||
* @return whether the bean is eligible
|
||||
*/
|
||||
protected boolean isEligibleBean(String beanName) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
-263
@@ -1,263 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
import org.aspectj.lang.reflect.PerClauseKind;
|
||||
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
|
||||
import org.springframework.aop.aspectj.AspectJPrecedenceInformation;
|
||||
import org.springframework.aop.aspectj.InstantiationModelAwarePointcutAdvisor;
|
||||
import org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory.AspectJAnnotation;
|
||||
import org.springframework.aop.support.DynamicMethodMatcherPointcut;
|
||||
import org.springframework.aop.support.Pointcuts;
|
||||
|
||||
/**
|
||||
* Internal implementation of AspectJPointcutAdvisor.
|
||||
* Note that there will be one instance of this advisor for each target method.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
class InstantiationModelAwarePointcutAdvisorImpl
|
||||
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation {
|
||||
|
||||
private final AspectJExpressionPointcut declaredPointcut;
|
||||
|
||||
private Pointcut pointcut;
|
||||
|
||||
private final MetadataAwareAspectInstanceFactory aspectInstanceFactory;
|
||||
|
||||
private final Method method;
|
||||
|
||||
private final boolean lazy;
|
||||
|
||||
private final AspectJAdvisorFactory atAspectJAdvisorFactory;
|
||||
|
||||
private Advice instantiatedAdvice;
|
||||
|
||||
private int declarationOrder;
|
||||
|
||||
private String aspectName;
|
||||
|
||||
private Boolean isBeforeAdvice = null;
|
||||
|
||||
private Boolean isAfterAdvice = null;
|
||||
|
||||
|
||||
public InstantiationModelAwarePointcutAdvisorImpl(
|
||||
AspectJAdvisorFactory af,
|
||||
AspectJExpressionPointcut ajexp,
|
||||
MetadataAwareAspectInstanceFactory aif,
|
||||
Method method,
|
||||
int declarationOrderInAspect,
|
||||
String aspectName) {
|
||||
|
||||
this.declaredPointcut = ajexp;
|
||||
this.method = method;
|
||||
this.atAspectJAdvisorFactory = af;
|
||||
this.aspectInstanceFactory = aif;
|
||||
this.declarationOrder = declarationOrderInAspect;
|
||||
this.aspectName = aspectName;
|
||||
|
||||
if (aif.getAspectMetadata().isLazilyInstantiated()) {
|
||||
// Static part of the pointcut is a lazy type.
|
||||
Pointcut preInstantiationPointcut =
|
||||
Pointcuts.union(aif.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
|
||||
|
||||
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
|
||||
// If it's not a dynamic pointcut, it may be optimized out
|
||||
// by the Spring AOP infrastructure after the first evaluation.
|
||||
this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aif);
|
||||
this.lazy = true;
|
||||
}
|
||||
else {
|
||||
// A singleton aspect.
|
||||
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
|
||||
this.pointcut = declaredPointcut;
|
||||
this.lazy = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The pointcut for Spring AOP to use. Actual behaviour of the pointcut will change
|
||||
* depending on the state of the advice.
|
||||
*/
|
||||
public Pointcut getPointcut() {
|
||||
return this.pointcut;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is only of interest for Spring AOP: AspectJ instantiation semantics
|
||||
* are much richer. In AspectJ terminology, all a return of <code>true</code>
|
||||
* means here is that the aspect is not a SINGLETON.
|
||||
*/
|
||||
public boolean isPerInstance() {
|
||||
return (getAspectMetadata().getAjType().getPerClause().getKind() != PerClauseKind.SINGLETON);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the AspectJ AspectMetadata for this advisor.
|
||||
*/
|
||||
public AspectMetadata getAspectMetadata() {
|
||||
return this.aspectInstanceFactory.getAspectMetadata();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily instantiate advice if necessary.
|
||||
*/
|
||||
public synchronized Advice getAdvice() {
|
||||
if (this.instantiatedAdvice == null) {
|
||||
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
|
||||
}
|
||||
return this.instantiatedAdvice;
|
||||
}
|
||||
|
||||
public boolean isLazy() {
|
||||
return this.lazy;
|
||||
}
|
||||
|
||||
public synchronized boolean isAdviceInstantiated() {
|
||||
return (this.instantiatedAdvice != null);
|
||||
}
|
||||
|
||||
|
||||
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
|
||||
return this.atAspectJAdvisorFactory.getAdvice(
|
||||
this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
|
||||
}
|
||||
|
||||
public MetadataAwareAspectInstanceFactory getAspectInstanceFactory() {
|
||||
return this.aspectInstanceFactory;
|
||||
}
|
||||
|
||||
public AspectJExpressionPointcut getDeclaredPointcut() {
|
||||
return this.declaredPointcut;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return this.aspectInstanceFactory.getOrder();
|
||||
}
|
||||
|
||||
public String getAspectName() {
|
||||
return this.aspectName;
|
||||
}
|
||||
|
||||
public int getDeclarationOrder() {
|
||||
return this.declarationOrder;
|
||||
}
|
||||
|
||||
public boolean isBeforeAdvice() {
|
||||
if (this.isBeforeAdvice == null) {
|
||||
determineAdviceType();
|
||||
}
|
||||
return this.isBeforeAdvice;
|
||||
}
|
||||
|
||||
public boolean isAfterAdvice() {
|
||||
if (this.isAfterAdvice == null) {
|
||||
determineAdviceType();
|
||||
}
|
||||
return this.isAfterAdvice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicates some logic from getAdvice, but importantly does not force
|
||||
* creation of the advice.
|
||||
*/
|
||||
private void determineAdviceType() {
|
||||
AspectJAnnotation<?> aspectJAnnotation =
|
||||
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.method);
|
||||
if (aspectJAnnotation == null) {
|
||||
this.isBeforeAdvice = false;
|
||||
this.isAfterAdvice = false;
|
||||
}
|
||||
else {
|
||||
switch (aspectJAnnotation.getAnnotationType()) {
|
||||
case AtAfter:
|
||||
case AtAfterReturning:
|
||||
case AtAfterThrowing:
|
||||
this.isAfterAdvice = true;
|
||||
this.isBeforeAdvice = false;
|
||||
break;
|
||||
case AtAround:
|
||||
case AtPointcut:
|
||||
this.isAfterAdvice = false;
|
||||
this.isBeforeAdvice = false;
|
||||
break;
|
||||
case AtBefore:
|
||||
this.isAfterAdvice = false;
|
||||
this.isBeforeAdvice = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() +
|
||||
"]; advice method [" + this.method + "]; perClauseKind=" +
|
||||
this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pointcut implementation that changes its behaviour when the advice is instantiated.
|
||||
* Note that this is a <i>dynamic</i> pointcut. Otherwise it might
|
||||
* be optimized out if it does not at first match statically.
|
||||
*/
|
||||
private class PerTargetInstantiationModelPointcut extends DynamicMethodMatcherPointcut {
|
||||
|
||||
private final AspectJExpressionPointcut declaredPointcut;
|
||||
|
||||
private final Pointcut preInstantiationPointcut;
|
||||
|
||||
private LazySingletonAspectInstanceFactoryDecorator aspectInstanceFactory;
|
||||
|
||||
private PerTargetInstantiationModelPointcut(AspectJExpressionPointcut declaredPointcut,
|
||||
Pointcut preInstantiationPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
|
||||
this.declaredPointcut = declaredPointcut;
|
||||
this.preInstantiationPointcut = preInstantiationPointcut;
|
||||
if (aspectInstanceFactory instanceof LazySingletonAspectInstanceFactoryDecorator) {
|
||||
this.aspectInstanceFactory = (LazySingletonAspectInstanceFactoryDecorator) aspectInstanceFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class targetClass) {
|
||||
// We're either instantiated and matching on declared pointcut, or uninstantiated matching on either pointcut
|
||||
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass)) ||
|
||||
this.preInstantiationPointcut.getMethodMatcher().matches(method, targetClass);
|
||||
}
|
||||
|
||||
public boolean matches(Method method, Class targetClass, Object[] args) {
|
||||
// This can match only on declared pointcut.
|
||||
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass));
|
||||
}
|
||||
|
||||
private boolean isAspectMaterialized() {
|
||||
return (this.aspectInstanceFactory == null || this.aspectInstanceFactory.isMaterialized());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-77
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Decorator to cause a MetadataAwareAspectInstanceFactory to instantiate only once.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwareAspectInstanceFactory {
|
||||
|
||||
private final MetadataAwareAspectInstanceFactory maaif;
|
||||
|
||||
private Object materialized;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new lazily initializing decorator for the given AspectInstanceFactory.
|
||||
* @param maaif the MetadataAwareAspectInstanceFactory to decorate
|
||||
*/
|
||||
public LazySingletonAspectInstanceFactoryDecorator(MetadataAwareAspectInstanceFactory maaif) {
|
||||
Assert.notNull(maaif, "AspectInstanceFactory must not be null");
|
||||
this.maaif = maaif;
|
||||
}
|
||||
|
||||
public synchronized Object getAspectInstance() {
|
||||
if (this.materialized == null) {
|
||||
this.materialized = this.maaif.getAspectInstance();
|
||||
}
|
||||
return this.materialized;
|
||||
}
|
||||
|
||||
public ClassLoader getAspectClassLoader() {
|
||||
return this.maaif.getAspectClassLoader();
|
||||
}
|
||||
|
||||
public boolean isMaterialized() {
|
||||
return (this.materialized != null);
|
||||
}
|
||||
|
||||
public AspectMetadata getAspectMetadata() {
|
||||
return this.maaif.getAspectMetadata();
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
if (this.maaif instanceof Ordered) {
|
||||
return ((Ordered) this.maaif).getOrder();
|
||||
}
|
||||
return Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LazySingletonAspectInstanceFactoryDecorator: decorating " + this.maaif;
|
||||
}
|
||||
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import org.springframework.aop.aspectj.AspectInstanceFactory;
|
||||
|
||||
/**
|
||||
* Subinterface of {@link org.springframework.aop.aspectj.AspectInstanceFactory}
|
||||
* that returns {@link AspectMetadata} associated with AspectJ-annotated classes.
|
||||
*
|
||||
* <p>Ideally, AspectInstanceFactory would include this method itself, but because
|
||||
* AspectMetadata uses Java-5-only {@link org.aspectj.lang.reflect.AjType},
|
||||
* we need to split out this subinterface.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
* @see AspectMetadata
|
||||
* @see org.aspectj.lang.reflect.AjType
|
||||
*/
|
||||
public interface MetadataAwareAspectInstanceFactory extends AspectInstanceFactory {
|
||||
|
||||
/**
|
||||
* Return the AspectJ AspectMetadata for this factory's aspect.
|
||||
* @return the aspect metadata
|
||||
*/
|
||||
AspectMetadata getAspectMetadata();
|
||||
|
||||
}
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
|
||||
/**
|
||||
* Extension of AopConfigException thrown when trying to perform
|
||||
* an advisor generation operation on a class that is not an
|
||||
* AspectJ annotation-style aspect.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
*/
|
||||
public class NotAnAtAspectException extends AopConfigException {
|
||||
|
||||
private Class<?> nonAspectClass;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new NotAnAtAspectException for the given class.
|
||||
* @param nonAspectClass the offending class
|
||||
*/
|
||||
public NotAnAtAspectException(Class<?> nonAspectClass) {
|
||||
super(nonAspectClass.getName() + " is not an @AspectJ aspect");
|
||||
this.nonAspectClass = nonAspectClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the offending class.
|
||||
*/
|
||||
public Class<?> getNonAspectClass() {
|
||||
return this.nonAspectClass;
|
||||
}
|
||||
|
||||
}
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
|
||||
/**
|
||||
* AspectInstanceFactory backed by a BeanFactory-provided prototype,
|
||||
* enforcing prototype semantics.
|
||||
*
|
||||
* <p>Note that this may instantiate multiple times, which probably won't give the
|
||||
* semantics you expect. Use a {@link LazySingletonAspectInstanceFactoryDecorator}
|
||||
* to wrap this to ensure only one new aspect comes back.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see LazySingletonAspectInstanceFactoryDecorator
|
||||
*/
|
||||
public class PrototypeAspectInstanceFactory extends BeanFactoryAspectInstanceFactory {
|
||||
|
||||
/**
|
||||
* Create a PrototypeAspectInstanceFactory. AspectJ will be called to
|
||||
* introspect to create AJType metadata using the type returned for the
|
||||
* given bean name from the BeanFactory.
|
||||
* @param beanFactory the BeanFactory to obtain instance(s) from
|
||||
* @param name the name of the bean
|
||||
*/
|
||||
public PrototypeAspectInstanceFactory(BeanFactory beanFactory, String name) {
|
||||
super(beanFactory, name);
|
||||
if (!beanFactory.isPrototype(name)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Cannot use PrototypeAspectInstanceFactory with bean named '" + name + "': not a prototype");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-239
@@ -1,239 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
import org.aspectj.lang.annotation.AfterReturning;
|
||||
import org.aspectj.lang.annotation.AfterThrowing;
|
||||
import org.aspectj.lang.annotation.DeclareParents;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.MethodBeforeAdvice;
|
||||
import org.springframework.aop.aspectj.AbstractAspectJAdvice;
|
||||
import org.springframework.aop.aspectj.AspectJAfterAdvice;
|
||||
import org.springframework.aop.aspectj.AspectJAfterReturningAdvice;
|
||||
import org.springframework.aop.aspectj.AspectJAfterThrowingAdvice;
|
||||
import org.springframework.aop.aspectj.AspectJAroundAdvice;
|
||||
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
|
||||
import org.springframework.aop.aspectj.AspectJMethodBeforeAdvice;
|
||||
import org.springframework.aop.aspectj.DeclareParentsAdvisor;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Factory that can create Spring AOP Advisors given AspectJ classes from
|
||||
* classes honoring the AspectJ 5 annotation syntax, using reflection to
|
||||
* invoke the corresponding advice methods.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Adrian Colyer
|
||||
* @author Juergen Hoeller
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory {
|
||||
|
||||
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) {
|
||||
final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass();
|
||||
final String aspectName = maaif.getAspectMetadata().getAspectName();
|
||||
validate(aspectClass);
|
||||
|
||||
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
|
||||
// so that it will only instantiate once.
|
||||
final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
|
||||
new LazySingletonAspectInstanceFactoryDecorator(maaif);
|
||||
|
||||
final List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
|
||||
public void doWith(Method method) throws IllegalArgumentException {
|
||||
// Exclude pointcuts
|
||||
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
|
||||
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
|
||||
if (advisor != null) {
|
||||
advisors.add(advisor);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// If it's a per target aspect, emit the dummy instantiating aspect.
|
||||
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
|
||||
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
|
||||
advisors.add(0, instantiationAdvisor);
|
||||
}
|
||||
|
||||
// Find introduction fields.
|
||||
for (Field field : aspectClass.getDeclaredFields()) {
|
||||
Advisor advisor = getDeclareParentsAdvisor(field);
|
||||
if (advisor != null) {
|
||||
advisors.add(advisor);
|
||||
}
|
||||
}
|
||||
|
||||
return advisors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a {@link org.springframework.aop.aspectj.DeclareParentsAdvisor}
|
||||
* for the given introduction field.
|
||||
* <p>Resulting Advisors will need to be evaluated for targets.
|
||||
* @param introductionField the field to introspect
|
||||
* @return <code>null</code> if not an Advisor
|
||||
*/
|
||||
private Advisor getDeclareParentsAdvisor(Field introductionField) {
|
||||
DeclareParents declareParents = (DeclareParents) introductionField.getAnnotation(DeclareParents.class);
|
||||
if (declareParents == null) {
|
||||
// Not an introduction field
|
||||
return null;
|
||||
}
|
||||
|
||||
if (DeclareParents.class.equals(declareParents.defaultImpl())) {
|
||||
// This is what comes back if it wasn't set. This seems bizarre...
|
||||
// TODO this restriction possibly should be relaxed
|
||||
throw new IllegalStateException("defaultImpl must be set on DeclareParents");
|
||||
}
|
||||
|
||||
return new DeclareParentsAdvisor(
|
||||
introductionField.getType(), declareParents.value(), declareParents.defaultImpl());
|
||||
}
|
||||
|
||||
|
||||
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aif,
|
||||
int declarationOrderInAspect, String aspectName) {
|
||||
|
||||
validate(aif.getAspectMetadata().getAspectClass());
|
||||
|
||||
AspectJExpressionPointcut ajexp =
|
||||
getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass());
|
||||
if (ajexp == null) {
|
||||
return null;
|
||||
}
|
||||
return new InstantiationModelAwarePointcutAdvisorImpl(
|
||||
this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName);
|
||||
}
|
||||
|
||||
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
|
||||
AspectJAnnotation<?> aspectJAnnotation =
|
||||
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
|
||||
if (aspectJAnnotation == null) {
|
||||
return null;
|
||||
}
|
||||
AspectJExpressionPointcut ajexp =
|
||||
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class[0]);
|
||||
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
|
||||
return ajexp;
|
||||
}
|
||||
|
||||
|
||||
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp,
|
||||
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) {
|
||||
|
||||
Class<?> candidateAspectClass = aif.getAspectMetadata().getAspectClass();
|
||||
validate(candidateAspectClass);
|
||||
|
||||
AspectJAnnotation<?> aspectJAnnotation =
|
||||
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
|
||||
if (aspectJAnnotation == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If we get here, we know we have an AspectJ method.
|
||||
// Check that it's an AspectJ-annotated class
|
||||
if (!isAspect(candidateAspectClass)) {
|
||||
throw new AopConfigException("Advice must be declared inside an aspect type: " +
|
||||
"Offending method '" + candidateAdviceMethod + "' in class [" +
|
||||
candidateAspectClass.getName() + "]");
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found AspectJ method: " + candidateAdviceMethod);
|
||||
}
|
||||
|
||||
AbstractAspectJAdvice springAdvice;
|
||||
|
||||
switch (aspectJAnnotation.getAnnotationType()) {
|
||||
case AtBefore:
|
||||
springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif);
|
||||
break;
|
||||
case AtAfter:
|
||||
springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif);
|
||||
break;
|
||||
case AtAfterReturning:
|
||||
springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, ajexp, aif);
|
||||
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
|
||||
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
|
||||
springAdvice.setReturningName(afterReturningAnnotation.returning());
|
||||
}
|
||||
break;
|
||||
case AtAfterThrowing:
|
||||
springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, ajexp, aif);
|
||||
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
|
||||
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
|
||||
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
|
||||
}
|
||||
break;
|
||||
case AtAround:
|
||||
springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif);
|
||||
break;
|
||||
case AtPointcut:
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
|
||||
}
|
||||
return null;
|
||||
default:
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported advice type on method " + candidateAdviceMethod);
|
||||
}
|
||||
|
||||
// Now to configure the advice...
|
||||
springAdvice.setAspectName(aspectName);
|
||||
springAdvice.setDeclarationOrder(declarationOrderInAspect);
|
||||
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
|
||||
if (argNames != null) {
|
||||
springAdvice.setArgumentNamesFromStringArray(argNames);
|
||||
}
|
||||
springAdvice.calculateArgumentBindings();
|
||||
return springAdvice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Synthetic advisor that instantiates the aspect.
|
||||
* Triggered by per-clause pointcut on non-singleton aspect.
|
||||
* The advice has no effect.
|
||||
*/
|
||||
protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor {
|
||||
|
||||
public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) {
|
||||
super(aif.getAspectMetadata().getPerClausePointcut(), new MethodBeforeAdvice() {
|
||||
public void before(Method method, Object[] args, Object target) {
|
||||
// Simply instantiate the aspect
|
||||
aif.getAspectInstance();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-69
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import org.springframework.aop.aspectj.SimpleAspectInstanceFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
/**
|
||||
* Implementation of {@link MetadataAwareAspectInstanceFactory} that
|
||||
* creates a new instance of the specified aspect class for every
|
||||
* {@link #getAspectInstance()} call.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0.4
|
||||
*/
|
||||
public class SimpleMetadataAwareAspectInstanceFactory extends SimpleAspectInstanceFactory
|
||||
implements MetadataAwareAspectInstanceFactory {
|
||||
|
||||
private final AspectMetadata metadata;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new SimpleMetadataAwareAspectInstanceFactory for the given aspect class.
|
||||
* @param aspectClass the aspect class
|
||||
* @param aspectName the aspect name
|
||||
*/
|
||||
public SimpleMetadataAwareAspectInstanceFactory(Class aspectClass, String aspectName) {
|
||||
super(aspectClass);
|
||||
this.metadata = new AspectMetadata(aspectClass, aspectName);
|
||||
}
|
||||
|
||||
|
||||
public final AspectMetadata getAspectMetadata() {
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine a fallback order for the case that the aspect instance
|
||||
* does not express an instance-specific order through implementing
|
||||
* the {@link org.springframework.core.Ordered} interface.
|
||||
* <p>The default implementation simply returns <code>Ordered.LOWEST_PRECEDENCE</code>.
|
||||
* @param aspectClass the aspect class
|
||||
*/
|
||||
@Override
|
||||
protected int getOrderForAspectClass(Class aspectClass) {
|
||||
Order order = (Order) aspectClass.getAnnotation(Order.class);
|
||||
if (order != null) {
|
||||
return order.value();
|
||||
}
|
||||
return Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-69
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import org.springframework.aop.aspectj.SingletonAspectInstanceFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
/**
|
||||
* Implementation of {@link MetadataAwareAspectInstanceFactory} that is backed
|
||||
* by a specified singleton object, returning the same instance for every
|
||||
* {@link #getAspectInstance()} call.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see SimpleMetadataAwareAspectInstanceFactory
|
||||
*/
|
||||
public class SingletonMetadataAwareAspectInstanceFactory extends SingletonAspectInstanceFactory
|
||||
implements MetadataAwareAspectInstanceFactory {
|
||||
|
||||
private final AspectMetadata metadata;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new SingletonMetadataAwareAspectInstanceFactory for the given aspect.
|
||||
* @param aspectInstance the singleton aspect instance
|
||||
* @param aspectName the name of the aspect
|
||||
*/
|
||||
public SingletonMetadataAwareAspectInstanceFactory(Object aspectInstance, String aspectName) {
|
||||
super(aspectInstance);
|
||||
this.metadata = new AspectMetadata(aspectInstance.getClass(), aspectName);
|
||||
}
|
||||
|
||||
|
||||
public final AspectMetadata getAspectMetadata() {
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the aspect class carries an
|
||||
* {@link org.springframework.core.annotation.Order} annotation,
|
||||
* falling back to <code>Ordered.LOWEST_PRECEDENCE</code>.
|
||||
* @see org.springframework.core.annotation.Order
|
||||
*/
|
||||
@Override
|
||||
protected int getOrderForAspectClass(Class aspectClass) {
|
||||
Order order = (Order) aspectClass.getAnnotation(Order.class);
|
||||
if (order != null) {
|
||||
return order.value();
|
||||
}
|
||||
return Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
}
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
|
||||
Classes enabling AspectJ 5 @Annotated classes to be used in Spring AOP.
|
||||
|
||||
<p>Normally to be used through an AspectJAutoProxyCreator rather than directly.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
-165
@@ -1,165 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.autoproxy;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
import org.aspectj.util.PartialOrder;
|
||||
import org.aspectj.util.PartialOrder.PartialComparable;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.aspectj.AbstractAspectJAdvice;
|
||||
import org.springframework.aop.aspectj.AspectJPointcutAdvisor;
|
||||
import org.springframework.aop.aspectj.AspectJProxyUtils;
|
||||
import org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator;
|
||||
import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator}
|
||||
* subclass that exposes AspectJ's invocation context and understands AspectJ's rules
|
||||
* for advice precedence when multiple pieces of advice come from the same aspect.
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @author Juergen Hoeller
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
|
||||
|
||||
private static final Comparator DEFAULT_PRECEDENCE_COMPARATOR = new AspectJPrecedenceComparator();
|
||||
|
||||
|
||||
/**
|
||||
* Sort the rest by AspectJ precedence. If two pieces of advice have
|
||||
* come from the same aspect they will have the same order.
|
||||
* Advice from the same aspect is then further ordered according to the
|
||||
* following rules:
|
||||
* <ul>
|
||||
* <li>if either of the pair is after advice, then the advice declared
|
||||
* last gets highest precedence (runs last)</li>
|
||||
* <li>otherwise the advice declared first gets highest precedence (runs first)</li>
|
||||
* </ul>
|
||||
* <p><b>Important:</b> Advisors are sorted in precedence order, from highest
|
||||
* precedence to lowest. "On the way in" to a join point, the highest precedence
|
||||
* advisor should run first. "On the way out" of a join point, the highest precedence
|
||||
* advisor should run last.
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
|
||||
// build list for sorting
|
||||
List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors =
|
||||
new LinkedList<PartiallyComparableAdvisorHolder>();
|
||||
for (Advisor element : advisors) {
|
||||
partiallyComparableAdvisors.add(
|
||||
new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR));
|
||||
}
|
||||
|
||||
// sort it
|
||||
List<PartiallyComparableAdvisorHolder> sorted =
|
||||
(List<PartiallyComparableAdvisorHolder>) PartialOrder.sort(partiallyComparableAdvisors);
|
||||
if (sorted == null) {
|
||||
// TODO: work harder to give a better error message here.
|
||||
throw new IllegalArgumentException("Advice precedence circularity error");
|
||||
}
|
||||
|
||||
// extract results again
|
||||
List<Advisor> result = new LinkedList<Advisor>();
|
||||
for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
|
||||
result.add(pcAdvisor.getAdvisor());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an {@link ExposeInvocationInterceptor} to the beginning of the advice chain.
|
||||
* These additional advices are needed when using AspectJ expression pointcuts
|
||||
* and when using AspectJ-style advice.
|
||||
*/
|
||||
@Override
|
||||
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
|
||||
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldSkip(Class beanClass, String beanName) {
|
||||
// TODO: Consider optimization by caching the list of the aspect names
|
||||
List<Advisor> candidateAdvisors = findCandidateAdvisors();
|
||||
for (Advisor advisor : candidateAdvisors) {
|
||||
if (advisor instanceof AspectJPointcutAdvisor) {
|
||||
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.shouldSkip(beanClass, beanName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implements AspectJ PartialComparable interface for defining partial orderings.
|
||||
*/
|
||||
private static class PartiallyComparableAdvisorHolder implements PartialComparable {
|
||||
|
||||
private final Advisor advisor;
|
||||
|
||||
private final Comparator<Advisor> comparator;
|
||||
|
||||
public PartiallyComparableAdvisorHolder(Advisor advisor, Comparator<Advisor> comparator) {
|
||||
this.advisor = advisor;
|
||||
this.comparator = comparator;
|
||||
}
|
||||
|
||||
public int compareTo(Object obj) {
|
||||
Advisor otherAdvisor = ((PartiallyComparableAdvisorHolder) obj).advisor;
|
||||
return this.comparator.compare(this.advisor, otherAdvisor);
|
||||
}
|
||||
|
||||
public int fallbackCompareTo(Object obj) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Advisor getAdvisor() {
|
||||
return this.advisor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Advice advice = this.advisor.getAdvice();
|
||||
sb.append(ClassUtils.getShortName(advice.getClass()));
|
||||
sb.append(": ");
|
||||
if (this.advisor instanceof Ordered) {
|
||||
sb.append("order ").append(((Ordered) this.advisor).getOrder()).append(", ");
|
||||
}
|
||||
if (advice instanceof AbstractAspectJAdvice) {
|
||||
AbstractAspectJAdvice ajAdvice = (AbstractAspectJAdvice) advice;
|
||||
sb.append(ajAdvice.getAspectName());
|
||||
sb.append(", declaration order ");
|
||||
sb.append(ajAdvice.getDeclarationOrder());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-166
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.autoproxy;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.aspectj.AspectJAopUtils;
|
||||
import org.springframework.aop.aspectj.AspectJPrecedenceInformation;
|
||||
import org.springframework.core.OrderComparator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Orders AspectJ advice/advisors by precedence (<i>not</i> invocation order).
|
||||
*
|
||||
* <p>Given two pieces of advice, <code>a</code> and <code>b</code>:
|
||||
* <ul>
|
||||
* <li>if <code>a</code> and <code>b</code> are defined in different
|
||||
* aspects, then the advice in the aspect with the lowest order
|
||||
* value has the highest precedence</li>
|
||||
* <li>if <code>a</code> and <code>b</code> are defined in the same
|
||||
* aspect, then if one of <code>a</code> or <code>b</code> is a form of
|
||||
* after advice, then the advice declared last in the aspect has the
|
||||
* highest precedence. If neither <code>a</code> nor <code>b</code> is a
|
||||
* form of after advice, then the advice declared first in the aspect has
|
||||
* the highest precedence.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>Important: Note that unlike a normal comparator a return of 0 means
|
||||
* we don't care about the ordering, not that the two elements must be sorted
|
||||
* identically. Used with AspectJ PartialOrder class.
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
class AspectJPrecedenceComparator implements Comparator {
|
||||
|
||||
private static final int HIGHER_PRECEDENCE = -1;
|
||||
private static final int SAME_PRECEDENCE = 0;
|
||||
private static final int LOWER_PRECEDENCE = 1;
|
||||
private static final int NOT_COMPARABLE = 0;
|
||||
|
||||
private final Comparator<? super Advisor> advisorComparator;
|
||||
|
||||
|
||||
/**
|
||||
* Create a default AspectJPrecedenceComparator.
|
||||
*/
|
||||
public AspectJPrecedenceComparator() {
|
||||
this.advisorComparator = OrderComparator.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a AspectJPrecedenceComparator, using the given Comparator
|
||||
* for comparing {@link org.springframework.aop.Advisor} instances.
|
||||
* @param advisorComparator the Comparator to use for Advisors
|
||||
*/
|
||||
public AspectJPrecedenceComparator(Comparator<? super Advisor> advisorComparator) {
|
||||
Assert.notNull(advisorComparator, "Advisor comparator must not be null");
|
||||
this.advisorComparator = advisorComparator;
|
||||
}
|
||||
|
||||
|
||||
public int compare(Object o1, Object o2) {
|
||||
if (!(o1 instanceof Advisor && o2 instanceof Advisor)) {
|
||||
throw new IllegalArgumentException(
|
||||
"AspectJPrecedenceComparator can only compare the order of Advisors, " +
|
||||
"but was passed [" + o1 + "] and [" + o2 + "]");
|
||||
}
|
||||
|
||||
Advisor advisor1 = (Advisor) o1;
|
||||
Advisor advisor2 = (Advisor) o2;
|
||||
|
||||
boolean oneOrOtherIsAfterAdvice =
|
||||
(AspectJAopUtils.isAfterAdvice(advisor1) || AspectJAopUtils.isAfterAdvice(advisor2));
|
||||
boolean oneOrOtherIsBeforeAdvice =
|
||||
(AspectJAopUtils.isBeforeAdvice(advisor1) || AspectJAopUtils.isBeforeAdvice(advisor2));
|
||||
if (oneOrOtherIsAfterAdvice && oneOrOtherIsBeforeAdvice) {
|
||||
return NOT_COMPARABLE;
|
||||
}
|
||||
else {
|
||||
int advisorPrecedence = this.advisorComparator.compare(advisor1, advisor2);
|
||||
if (advisorPrecedence == SAME_PRECEDENCE && declaredInSameAspect(advisor1, advisor2)) {
|
||||
advisorPrecedence = comparePrecedenceWithinAspect(advisor1, advisor2);
|
||||
}
|
||||
return advisorPrecedence;
|
||||
}
|
||||
}
|
||||
|
||||
private int comparePrecedenceWithinAspect(Advisor advisor1, Advisor advisor2) {
|
||||
boolean oneOrOtherIsAfterAdvice =
|
||||
(AspectJAopUtils.isAfterAdvice(advisor1) || AspectJAopUtils.isAfterAdvice(advisor2));
|
||||
int adviceDeclarationOrderDelta = getAspectDeclarationOrder(advisor1) - getAspectDeclarationOrder(advisor2);
|
||||
|
||||
if (oneOrOtherIsAfterAdvice) {
|
||||
// the advice declared last has higher precedence
|
||||
if (adviceDeclarationOrderDelta < 0) {
|
||||
// advice1 was declared before advice2
|
||||
// so advice1 has lower precedence
|
||||
return LOWER_PRECEDENCE;
|
||||
}
|
||||
else if (adviceDeclarationOrderDelta == 0) {
|
||||
return SAME_PRECEDENCE;
|
||||
}
|
||||
else {
|
||||
return HIGHER_PRECEDENCE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// the advice declared first has higher precedence
|
||||
if (adviceDeclarationOrderDelta < 0) {
|
||||
// advice1 was declared before advice2
|
||||
// so advice1 has higher precedence
|
||||
return HIGHER_PRECEDENCE;
|
||||
}
|
||||
else if (adviceDeclarationOrderDelta == 0) {
|
||||
return SAME_PRECEDENCE;
|
||||
}
|
||||
else {
|
||||
return LOWER_PRECEDENCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean declaredInSameAspect(Advisor advisor1, Advisor advisor2) {
|
||||
return (hasAspectName(advisor1) && hasAspectName(advisor2) &&
|
||||
getAspectName(advisor1).equals(getAspectName(advisor2)));
|
||||
}
|
||||
|
||||
private boolean hasAspectName(Advisor anAdvisor) {
|
||||
return (anAdvisor instanceof AspectJPrecedenceInformation ||
|
||||
anAdvisor.getAdvice() instanceof AspectJPrecedenceInformation);
|
||||
}
|
||||
|
||||
// pre-condition is that hasAspectName returned true
|
||||
private String getAspectName(Advisor anAdvisor) {
|
||||
return AspectJAopUtils.getAspectJPrecedenceInformationFor(anAdvisor).getAspectName();
|
||||
}
|
||||
|
||||
private int getAspectDeclarationOrder(Advisor anAdvisor) {
|
||||
AspectJPrecedenceInformation precedenceInfo =
|
||||
AspectJAopUtils.getAspectJPrecedenceInformationFor(anAdvisor);
|
||||
if (precedenceInfo != null) {
|
||||
return precedenceInfo.getDeclarationOrder();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
|
||||
Base classes enabling auto-proxying based on AspectJ.
|
||||
Support for AspectJ annotation aspects resides in the "aspectj.annotation" package.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,14 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
|
||||
AspectJ integration package. Includes Spring AOP advice implementations for AspectJ 5
|
||||
annotation-style methods, and an AspectJExpressionPointcut: a Spring AOP Pointcut
|
||||
implementation that allows use of the AspectJ pointcut expression language with the Spring AOP
|
||||
runtime framework.
|
||||
|
||||
<p>Note that use of this package does <i>not</i> require the use of the <code>ajc</code> compiler
|
||||
or AspectJ load-time weaver. It is intended to enable the use of a valuable subset of AspectJ
|
||||
functionality, with consistent semantics, with the proxy-based Spring AOP framework.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
-120
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.config;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactoryBean;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Base implementation for {@link org.springframework.beans.factory.xml.BeanDefinitionDecorator BeanDefinitionDecorators} wishing
|
||||
* to add an {@link org.aopalliance.intercept.MethodInterceptor interceptor} to the resulting
|
||||
* bean.
|
||||
*
|
||||
* <p>This base class controls the creation of the {@link ProxyFactoryBean} bean definition
|
||||
* and wraps the original as an inner-bean definition for the <code>target</code> property of
|
||||
* {@link ProxyFactoryBean}.
|
||||
*
|
||||
* <p>Chaining is correctly handled, ensuring that only one {@link ProxyFactoryBean} definition
|
||||
* is created. If a previous {@link org.springframework.beans.factory.xml.BeanDefinitionDecorator} already created the {@link org.springframework.aop.framework.ProxyFactoryBean}
|
||||
* then the interceptor is simply added to the existing definition.
|
||||
*
|
||||
* <p>Subclasses have only to create the <code>BeanDefinition</code> to the interceptor they
|
||||
* wish to add.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @since 2.0
|
||||
* @see org.aopalliance.intercept.MethodInterceptor
|
||||
*/
|
||||
public abstract class AbstractInterceptorDrivenBeanDefinitionDecorator implements BeanDefinitionDecorator {
|
||||
|
||||
public final BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definitionHolder, ParserContext parserContext) {
|
||||
BeanDefinitionRegistry registry = parserContext.getRegistry();
|
||||
|
||||
// get the root bean name - will be the name of the generated proxy factory bean
|
||||
String existingBeanName = definitionHolder.getBeanName();
|
||||
BeanDefinition existingDefinition = definitionHolder.getBeanDefinition();
|
||||
|
||||
// delegate to subclass for interceptor def
|
||||
BeanDefinition interceptorDefinition = createInterceptorDefinition(node);
|
||||
|
||||
// generate name and register the interceptor
|
||||
String interceptorName = existingBeanName + "." + getInterceptorNameSuffix(interceptorDefinition);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(new BeanDefinitionHolder(interceptorDefinition, interceptorName), registry);
|
||||
|
||||
BeanDefinitionHolder result = definitionHolder;
|
||||
|
||||
if (!isProxyFactoryBeanDefinition(existingDefinition)) {
|
||||
|
||||
// create the proxy definitionHolder
|
||||
RootBeanDefinition proxyDefinition = new RootBeanDefinition();
|
||||
// create proxy factory bean definitionHolder
|
||||
proxyDefinition.setBeanClass(ProxyFactoryBean.class);
|
||||
|
||||
// set up property values
|
||||
MutablePropertyValues mpvs = new MutablePropertyValues();
|
||||
proxyDefinition.setPropertyValues(mpvs);
|
||||
|
||||
// set the target
|
||||
mpvs.addPropertyValue("target", existingDefinition);
|
||||
|
||||
// create the interceptor names list
|
||||
ManagedList interceptorList = new ManagedList();
|
||||
mpvs.addPropertyValue("interceptorNames", interceptorList);
|
||||
|
||||
result = new BeanDefinitionHolder(proxyDefinition, existingBeanName);
|
||||
}
|
||||
|
||||
addInterceptorNameToList(interceptorName, result.getBeanDefinition());
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
private void addInterceptorNameToList(String interceptorName, BeanDefinition beanDefinition) {
|
||||
List list = (List) beanDefinition.getPropertyValues().getPropertyValue("interceptorNames").getValue();
|
||||
list.add(interceptorName);
|
||||
}
|
||||
|
||||
private boolean isProxyFactoryBeanDefinition(BeanDefinition existingDefinition) {
|
||||
return existingDefinition.getBeanClassName().equals(ProxyFactoryBean.class.getName());
|
||||
}
|
||||
|
||||
protected String getInterceptorNameSuffix(BeanDefinition interceptorDefinition) {
|
||||
return StringUtils.uncapitalize(ClassUtils.getShortName(interceptorDefinition.getBeanClassName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses should implement this method to return the <code>BeanDefinition</code>
|
||||
* for the interceptor they wish to apply to the bean being decorated.
|
||||
*/
|
||||
protected abstract BeanDefinition createInterceptorDefinition(Node node);
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user