Compare commits

..

363 Commits

Author SHA1 Message Date
Sam Brannen a636420239 Manual URL Cleanup
See gh-22517
2019-03-12 17:44:26 +01:00
Sam Brannen e68a7ae776 Merge branch 'spring-operator-polish-urls-build-4.0.x' into 4.0.x 2019-03-11 22:40:02 +01:00
Sam Brannen 0dedba016c Manual URL Cleanup
Closes gh-22517
2019-03-11 20:34:33 +01:00
Spring Operator 82ee0bef93 URL Cleanup
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# HTTP URLs that Could Not Be Fixed
These URLs were unable to be fixed. Please review them to see if they can be manually resolved.

* http://aopalliance.sourceforge.net/doc/ (200) migrated to:
  http://aopalliance.sourceforge.net/doc/ ([https](https://aopalliance.sourceforge.net/doc/) result AnnotatedConnectException).

# Fixed URLs

## Fixed But Review Recommended
These URLs were fixed, but the https status was not OK. However, the https status was the same as the http request or http redirected to an https URL, so they were migrated. Your review is recommended.

* http://jackson.codehaus.org/1.9.4/javadoc/ (UnknownHostException) migrated to:
  https://jackson.codehaus.org/1.9.4/javadoc/ ([https](https://jackson.codehaus.org/1.9.4/javadoc/) result UnknownHostException).
* http://jira.codehaus.org/browse/JIBX-465 (UnknownHostException) migrated to:
  https://jira.codehaus.org/browse/JIBX-465 ([https](https://jira.codehaus.org/browse/JIBX-465) result UnknownHostException).
* http://quartz-scheduler.org/api/2.2.0/ (301) migrated to:
  https://www.quartz-scheduler.org/api/2.2.0/ ([https](https://quartz-scheduler.org/api/2.2.0/) result 404).

## Fixed Success
These URLs were fixed successfully.

* http://commons.apache.org/proper/commons-codec/apidocs/ migrated to:
  https://commons.apache.org/proper/commons-codec/apidocs/ ([https](https://commons.apache.org/proper/commons-codec/apidocs/) result 200).
* http://commons.apache.org/proper/commons-dbcp/apidocs/ migrated to:
  https://commons.apache.org/proper/commons-dbcp/apidocs/ ([https](https://commons.apache.org/proper/commons-dbcp/apidocs/) result 200).
* http://commons.apache.org/proper/commons-lang/javadocs/api-2.5/ migrated to:
  https://commons.apache.org/proper/commons-lang/javadocs/api-2.5/ ([https](https://commons.apache.org/proper/commons-lang/javadocs/api-2.5/) result 200).
* http://docs.jboss.org/jbossas/javadoc/4.0.5/connector/ migrated to:
  https://docs.jboss.org/jbossas/javadoc/4.0.5/connector/ ([https](https://docs.jboss.org/jbossas/javadoc/4.0.5/connector/) result 200).
* http://docs.jboss.org/jbossas/javadoc/7.1.2.Final/ migrated to:
  https://docs.jboss.org/jbossas/javadoc/7.1.2.Final/ ([https](https://docs.jboss.org/jbossas/javadoc/7.1.2.Final/) result 200).
* http://docs.oracle.com/cd/E13222_01/wls/docs90/javadocs/ migrated to:
  https://docs.oracle.com/cd/E13222_01/wls/docs90/javadocs/ ([https](https://docs.oracle.com/cd/E13222_01/wls/docs90/javadocs/) result 200).
* http://docs.oracle.com/javaee/7/api/ migrated to:
  https://docs.oracle.com/javaee/7/api/ ([https](https://docs.oracle.com/javaee/7/api/) result 200).
* http://docs.oracle.com/javase/7/docs/api/ migrated to:
  https://docs.oracle.com/javase/7/docs/api/ ([https](https://docs.oracle.com/javase/7/docs/api/) result 200).
* http://portals.apache.org/pluto/portlet-2.0-apidocs/ migrated to:
  https://portals.apache.org/pluto/portlet-2.0-apidocs/ ([https](https://portals.apache.org/pluto/portlet-2.0-apidocs/) result 200).
* http://tiles.apache.org/framework/apidocs/ migrated to:
  https://tiles.apache.org/framework/apidocs/ ([https](https://tiles.apache.org/framework/apidocs/) result 200).
* http://tiles.apache.org/tiles-request/apidocs/ migrated to:
  https://tiles.apache.org/tiles-request/apidocs/ ([https](https://tiles.apache.org/tiles-request/apidocs/) result 200).
* http://www.apache.org/licenses/LICENSE-2.0.txt migrated to:
  https://www.apache.org/licenses/LICENSE-2.0.txt ([https](https://www.apache.org/licenses/LICENSE-2.0.txt) result 200).
* http://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/ migrated to:
  https://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/ ([https](https://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/) result 200).
* http://ehcache.org/apidocs/ (301) migrated to:
  https://www.ehcache.org/apidocs/ ([https](https://ehcache.org/apidocs/) result 200).
* http://static.springframework.org/spring-framework/docs (301) migrated to:
  https://docs.spring.io/spring-framework/docs ([https](https://static.springframework.org/spring-framework/docs) result 301).
* http://fasterxml.github.com/jackson-core/javadoc/2.3.0/ migrated to:
  https://fasterxml.github.com/jackson-core/javadoc/2.3.0/ ([https](https://fasterxml.github.com/jackson-core/javadoc/2.3.0/) result 301).
* http://fasterxml.github.com/jackson-databind/javadoc/2.3.0/ migrated to:
  https://fasterxml.github.com/jackson-databind/javadoc/2.3.0/ ([https](https://fasterxml.github.com/jackson-databind/javadoc/2.3.0/) result 301).
* http://glassfish.java.net/nonav/docs/v3/api/ migrated to:
  https://glassfish.java.net/nonav/docs/v3/api/ ([https](https://glassfish.java.net/nonav/docs/v3/api/) result 301).
* http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs migrated to:
  https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs ([https](https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs) result 301).
* http://pic.dhe.ibm.com/infocenter/wasinfo/v7r0/topic/com.ibm.websphere.javadoc.doc/web/apidocs/ migrated to:
  https://pic.dhe.ibm.com/infocenter/wasinfo/v7r0/topic/com.ibm.websphere.javadoc.doc/web/apidocs/ ([https](https://pic.dhe.ibm.com/infocenter/wasinfo/v7r0/topic/com.ibm.websphere.javadoc.doc/web/apidocs/) result 301).
* http://projects.spring.io/spring-framework migrated to:
  https://projects.spring.io/spring-framework ([https](https://projects.spring.io/spring-framework) result 301).
* http://springframework.org/schema migrated to:
  https://springframework.org/schema ([https](https://springframework.org/schema) result 301).
* http://spring.io/tools/sts/all migrated to:
  https://spring.io/tools/sts/all ([https](https://spring.io/tools/sts/all) result 302).
2019-03-05 21:55:52 -06:00
Rossen Stoyanchev b8a133d2f4 Remove section on spring-framework-contrib group 2016-04-08 15:44:51 -04:00
Sam Brannen f2e5e5aa86 Eclipse project deps come after third-party libs
This commit is a backport of SPR-11836.

Prior to this commit, the ordering of classpath entries in the
generated Eclipse .classpath files did not align with the intended
dependency management configured in the Gradle build. Specifically,
project dependencies often came before dependencies on third-party
libraries required for the given project, causing the project not to
compile in Eclipse.

This commit fixes this issue by introducing new functionality in the
ide.gradle script that moves all project dependencies to the end of the
generated classpath.

Issue: SPR-12947, SPR-11836
2015-04-24 21:39:57 +02:00
Spring Buildmaster b6083c7f77 Next Development Version 2014-12-30 07:16:48 -08:00
Juergen Hoeller 8575533081 Latest dependency updates (SLF4J 1.7.9, JRuby 1.7.17, Reactor 1.1.5) 2014-12-30 13:23:46 +01:00
Juergen Hoeller 5528c8a93b Polishing 2014-12-30 13:11:46 +01:00
Juergen Hoeller c9912f0d2d Polishing
Issue: SPR-12502
(cherry picked from commit 26845f6)
2014-12-30 10:09:00 +01:00
Juergen Hoeller 8e14a5d640 Prevent NPE in AbstractApplicationEventMulticaster's non-caching code path
Issue: SPR-12545
(cherry picked from commit 1cefeb2)
2014-12-30 10:08:42 +01:00
Juergen Hoeller 230aa07fbb Polishing 2014-12-29 20:15:54 +01:00
Juergen Hoeller b9aa471def TimeZone and ZoneId as supported arguments for MVC handler methods
Issue: SPR-12575
(cherry picked from commit 3791e7f)
2014-12-29 19:03:15 +01:00
Juergen Hoeller 39fbfbd343 Doc: base-packages can be comma/semicolon/space/tab/linefeed-separated
Issue: SPR-12523
(cherry picked from commit 6f2de28)
2014-12-29 19:02:24 +01:00
Juergen Hoeller e9d24d5336 Polishing
(cherry picked from commit 86b8112)
2014-12-29 18:59:17 +01:00
Juergen Hoeller 4a27a98702 Spring's JMX support can rely on native MXBean detection on Java 6+
Issue: SPR-12574
(cherry picked from commit 0919a15)
2014-12-29 18:59:07 +01:00
Juergen Hoeller 929c596b55 AnnotationJmxAttributeSource uses AnnotationUtils for consistent meta-annotation handling and diagnostics
Issue: SPR-12572
(cherry picked from commit d4a5059)
2014-12-29 18:59:00 +01:00
Juergen Hoeller 9362d0d547 PayloadArgumentResolver does not insist on configured Validator anymore
Issue: SPR-12567
(cherry picked from commit ed0e2f4)
2014-12-29 18:58:50 +01:00
Juergen Hoeller 37713ae9dd HandlerExecutionChain prevents re-adding the interceptors array to the list (and declares varargs now)
Issue: SPR-12566
(cherry picked from commit 6b3023c)
2014-12-29 18:58:41 +01:00
Juergen Hoeller e118086bd1 Annotation post-processors clear old InjectionMetadata registrations on refresh
Issue: SPR-12526
(cherry picked from commit 809ee0d)
2014-12-29 18:56:44 +01:00
Stephane Nicoll 0c7fa9e786 Fix scope inheritance documentation
Issue: SPR-12570
2014-12-29 10:55:01 +01:00
Juergen Hoeller dc15070877 Consistent bridge method handling in annotation post-processors
Issue: SPR-12495
2014-12-22 16:42:47 +01:00
Juergen Hoeller 61a6bc0139 AbstractApplicationEventMulticaster populates ListenerRetriever cache in fully synchronized fashion
Issue: SPR-12545
(cherry picked from commit 2b0ada9)
2014-12-22 16:39:25 +01:00
Juergen Hoeller c087e51b80 AbstractFallbackTransactionAttributeSource's DefaultCacheKey takes targetClass into account (again)
Issue: SPR-12536
(cherry picked from commit 4efe6a8)
2014-12-22 16:26:25 +01:00
Rossen Stoyanchev 9cb1569e67 Synchronize message sending
Issue: SPR-12516
(backport for commit b796c1)
2014-12-08 12:02:19 -05:00
Rossen Stoyanchev ac5c361688 Check the user of a SockJS request
Issue: SPR-12497
(backport of commit dc5b5c)
2014-12-08 11:22:45 -05:00
Juergen Hoeller 328ba7b6d4 Polishing 2014-12-07 23:24:38 +01:00
Juergen Hoeller d97add075a Consistent bridge method handling in annotation post-processors
Issue: SPR-12495
(cherry picked from commit 03d4e1b)
2014-12-07 23:24:02 +01:00
Juergen Hoeller c8ff562d1f DefaultSingletonBeanRegistry's isDependent defensively checks for circular recursion
Issue: SPR-10787
(cherry picked from commit 15d3b88)
2014-12-07 22:21:55 +01:00
Juergen Hoeller 1d6978afd5 Revised ControllerAdvice basePackages handling (based on package names instead of java.lang.Package)
Issue: SPR-12506
(cherry picked from commit 4013fe0)
2014-12-07 22:20:32 +01:00
Juergen Hoeller 4660e61cf9 Consistent resolution of Class methods and static methods
Issue: SPR-12502
(cherry picked from commit 9ef0bdc)
2014-12-07 22:13:13 +01:00
Juergen Hoeller dfc79721cb AnnotationAttributesReadingVisitor defensively handles meta-annotation retrieval failure
Issue: SPR-12493
(cherry picked from commit 5018889)
2014-12-07 22:13:08 +01:00
Juergen Hoeller 90ae073854 Relaxed final declarations and protected doInvoke methods
Issue: SPR-12484
(cherry picked from commit 2496d68)
2014-12-07 22:13:03 +01:00
Juergen Hoeller 50c578c5a0 Polishing 2014-11-28 20:59:35 +01:00
Juergen Hoeller c89d8ec382 Polishing
Issue: SPR-12476
(cherry picked from commit 3b15849)
2014-11-27 20:56:41 +01:00
Juergen Hoeller 7e07f3d083 Polishing 2014-11-27 18:28:16 +01:00
Juergen Hoeller e039185fec Revised SqlRowSet javadoc
Issue: SPR-12476
(cherry picked from commit a6a837b)
2014-11-27 18:01:19 +01:00
Juergen Hoeller b45f1aa26f ExtendedBeanInfo ignores invalid bean properties (analogous to the JavaBeans Introspector)
Issue: SPR-12434
(cherry picked from commit eacd4a1)
2014-11-27 01:48:33 +01:00
Juergen Hoeller 054464709f Latest dependency updates (Tomcat 8.0.15, JRuby 1.7.16.1) 2014-11-26 16:07:21 +01:00
Juergen Hoeller 5ac868036f Clarified getAllAnnotationAttributes behavior
Issue: SPR-12473
2014-11-26 15:35:24 +01:00
Juergen Hoeller 58bea23f1d NotReadablePropertyException accepts root cause (analogous to NotWritablePropertyException)
Issue: SPR-12467
(cherry picked from commit feb91e8)
2014-11-26 12:11:40 +01:00
Juergen Hoeller 98569045cb Tracking ASM 5.0.4 development: Fix for ASM issue 317545
Issue: SPR-12470
(cherry picked from commit ab5856b)
2014-11-26 12:11:13 +01:00
Stephane Nicoll c2ffbf28c5 Fix typo 2014-11-24 21:01:53 +01:00
Stephane Nicoll a5e2afc980 Fix documentation formatting
Using the "quotes" substitution group by default leads to side effect
when the "*" character is used. This is especially true for AOP pointcut
or for MVC mappings.

Plain verbatim might work most of the time unless you intend to highlight
a piece of code or a comment.

Issue: SPR-12456
(cherry picked from commit 0d00b674f4)
2014-11-24 21:01:53 +01:00
Juergen Hoeller 5be50c8e5e Polishing
Issue: SPR-12462
2014-11-24 17:41:43 +01:00
Brian Clozel 1214624265 Fix location checks for servlet 3 resources
SPR-12354 applied new checks to make sure that served static resources
are under authorized locations.

Prior to this change, serving static resources from Servlet 3 locations
such as "/webjars/" would not work since those locations can be within
one of the JARs on path. In that case, the checkLocation method would
return false and disallow serving that static resource.

This change fixes this issue by making sure to call the
`ServletContextResource.getPath()` method for servlet context resources.

Note that there's a known workaround for this issue, which is using a
classpath scheme as location, such as:
"classpath:/META-INF/resources/webjars/" instead of "/webjars".

Issue: SPR-12432
(cherry picked from commit 161d3e3)
2014-11-24 17:41:11 +01:00
Brian Clozel 493e8463fa Use https for maven repositories
(cherry picked from commit 44ff143)
2014-11-23 00:07:51 +01:00
Juergen Hoeller 6d3a0d5735 Polishing 2014-11-23 00:05:27 +01:00
Juergen Hoeller 5f58cd3b79 Polishing
(cherry picked from commit 2675ce7)
2014-11-22 22:47:24 +01:00
Juergen Hoeller 8854c33bf7 Rearranged WebAsyncTask constructor interdependencies and assertions
Issue: SPR-12457
(cherry picked from commit aadb93f)
2014-11-22 22:45:24 +01:00
Juergen Hoeller f093a5f749 RequestMappingHandlerAdapter allows for overriding handleInternal
Issue: SPR-12460
(cherry picked from commit ece2c90)
2014-11-22 22:45:19 +01:00
Juergen Hoeller 1f45dd297d Unit test for JavaBeans introspection against FreeMarker Configuration class
Issue: SPR-12448
(cherry picked from commit 282aded)
2014-11-22 22:45:12 +01:00
Juergen Hoeller 21b8ce5284 MethodParameter generally uses volatile variables where applicable now (as well as a local copy of the parameterNameDiscoverer field)
Issue: SPR-12453
(cherry picked from commit 7fcadaa)
2014-11-22 22:44:38 +01:00
Juergen Hoeller 2490d1b38d MutablePropertySources uses an internal CopyOnWriteArrayList for defensiveness against concurrent modifications
Issue: SPR-12428
(cherry picked from commit 1ef06cc)
2014-11-22 22:44:30 +01:00
Spring Buildmaster ffa4736895 Next Development Version 2014-11-10 22:50:00 -08:00
Rossen Stoyanchev 9beae9ae42 Apply extra checks to static resource handling
- remove leading '/' and control chars
- improve url and relative path checks
- account for URL encoding
- add isResourceUnderLocation final verification

Issue: SPR-12354
2014-11-11 06:31:57 +01:00
Juergen Hoeller e42e2330b3 Polishing 2014-11-11 03:21:43 +01:00
Sebastien Deleuze b331d65019 Check STOMP headers against ending backslash
Issue: SPR-12418
(cherry picked from commit 1803348)
2014-11-11 03:02:25 +01:00
Juergen Hoeller 1823ce1fad ShallowEtagHeaderFilter skips "Cache-Control" header check on Servlet 2.5
Issue: SPR-12414
(cherry picked from commit bf9295b)
2014-11-06 23:19:33 +01:00
Rossen Stoyanchev 2d0a677117 Improve exception message
Issue: SPR-12230
(cherry picked from commit 7f4bf41)
2014-11-06 16:15:04 +01:00
Sam Brannen a09bc9b1c1 Log context cache statistics in the TCF
Prior to this commit, finding out how many application contexts had
been loaded within a test suite required the use of reflection and a
bit of hacking.

This commit addresses this issue by logging ContextCache statistics
whenever an application context is loaded by the Spring TestContext
Framework (TCF).

The log output can be enabled by setting the
"org.springframework.test.context.cache" logging category to DEBUG.

Issue: SPR-12409
(cherry picked from commit da04362)
2014-11-06 16:13:37 +01:00
Stephane Nicoll 260b451d5f Add documentation for the keep-alive flag
This commit updates the documentation of the task:executor element to
reference the keep-alive flag.

Issue: SPR-12407
(cherry picked from commit 6534d00)
2014-11-06 15:28:38 +01:00
Juergen Hoeller acefd8381d Polishing 2014-11-02 11:38:35 +01:00
Juergen Hoeller 7fa3e65d04 Test for cyclic type declaration handling in TypeDescriptor
Issue: SPR-9735
2014-11-02 11:38:28 +01:00
Juergen Hoeller 329ba2a913 Removed outdated TimerTaskExecutor reference (and other minor doc updates)
Issue: SPR-12389
2014-11-01 13:02:36 +01:00
Juergen Hoeller f691618967 Polishing 2014-11-01 13:00:54 +01:00
Juergen Hoeller fde0713a94 Upgrade to Hibernate 4.2.16 (and AspectJ 1.8.3) 2014-11-01 13:00:39 +01:00
Juergen Hoeller 4729483804 HibernateJpaSessionFactoryBean is compatible with Hibernate 4.3 as well now
Issue: SPR-12401
(cherry picked from commit bf5739c)
2014-11-01 12:59:15 +01:00
Juergen Hoeller d3ec48f490 PersistenceAnnotationBeanPostProcessor correctly detects JPA 2.1 synchronization attribute
Issue: SPR-12396
(cherry picked from commit a181b40)
2014-11-01 12:58:38 +01:00
Juergen Hoeller 2d874d724b SimpleMetadataReaderFactory is capable of resolving inner class names with dot syntax now (analogous to ClassUtils.forName)
Issue: SPR-12390
(cherry picked from commit 725ad0d)
2014-11-01 12:58:08 +01:00
Juergen Hoeller 91940f212e Normalized AnnotationAttributesReadingVisitor class layout and improved diagnostics through delegating to AnnotationUtils
Issue: SPR-12387
(cherry picked from commit b70c5d1)
2014-11-01 12:57:10 +01:00
Juergen Hoeller de8645b30c Test for <util:map> with LinkedCaseInsensitiveMap and specified key/value types
Issue: SPR-10994
(cherry picked from commit 9243869)
2014-11-01 12:56:24 +01:00
Juergen Hoeller c8b8dc5f97 TilesConfigurer defensively expects null from getResources in case of no resources found
Also includes order preservation for resource results with Tiles 2 as well as retrieval failure logging with Tiles 3.

Issue: SPR-12362
(cherry picked from commit cb86036)
2014-11-01 12:55:53 +01:00
Juergen Hoeller aa82da8507 Set ResponseStatusExceptionResolver.messageSource in the MVC Java config
Issue: SPR-12380
(cherry picked from commit 17b9bde)
2014-11-01 12:55:03 +01:00
Juergen Hoeller 16a4fe70f2 Polishing
(cherry picked from commit 2956049)
2014-10-22 17:14:23 +02:00
Juergen Hoeller 6117311906 QualifierAnnotationAutowireCandidateResolver calls BeanFactory.getType defensively
Issue: SPR-12191
(cherry picked from commit 73ce3b5)
2014-10-22 17:14:02 +02:00
Juergen Hoeller 6e5711a7fb Revised test for ImportBeanDefinitionRegistrar double scan
Issue: SPR-12334
2014-10-22 02:16:39 +02:00
Juergen Hoeller 15c8987cc4 Polishing 2014-10-22 01:10:01 +02:00
Juergen Hoeller 0e907764a4 Test for ImportBeanDefinitionRegistrar double scan
Issue: SPR-12334
(cherry picked from commit 38030ef)
2014-10-22 01:09:47 +02:00
Juergen Hoeller a305bf7ad1 Latest dependency updates (Hibernate 4.2.15, Tiles 3.0.5) 2014-10-22 01:09:31 +02:00
Juergen Hoeller e16f21c281 AnnotationUtils consistently logs introspection failures via lazily initialized logger
Issue: SPR-12325
Issue: SPR-12329
2014-10-22 01:08:41 +02:00
Juergen Hoeller 7507560e75 Reimplemented ServerEndpointExporter to avoid BeanPostProcessor role
Issue: SPR-12340
(cherry picked from commit 10328f1)
2014-10-22 01:05:19 +02:00
Juergen Hoeller a1c0905a7c Consistently accept empty Content-Type header and empty character encoding
Issue: SPR-12173
(cherry picked from commit d501137)
2014-10-22 01:04:22 +02:00
Juergen Hoeller 6f9d7da59e Consistent use of LinkedHashSet for interfaces (since interface order may matter in subtle cases)
(cherry picked from commit 5a63117)
2014-10-07 17:26:48 +02:00
Juergen Hoeller 47ed4d634b Explicitly detect (and log) private @Scheduled methods on CGLIB proxies
Issue: SPR-12308
(cherry picked from commit 01724d3)
2014-10-07 17:26:35 +02:00
Juergen Hoeller da2c30cd0c TextMessage.toString() does not throw StringIndexOutOfBoundsException for payload with multibyte characters
Issue: SPR-12307
(cherry picked from commit da14aee)
2014-10-07 17:15:23 +02:00
Juergen Hoeller a7eeedaf6a Fix outdated references to JobDetailBean
Issue: SPR-12306
(cherry picked from commit aaf69eb)
2014-10-07 17:13:53 +02:00
Juergen Hoeller 578c3dd853 Polishing
(cherry picked from commit d6be433)
2014-10-07 00:53:01 +02:00
Juergen Hoeller 9758bc7833 Consistent reset of resource holders on doBegin failure
Issue: SPR-12280
(cherry picked from commit e58b33a)
2014-10-07 00:06:49 +02:00
Juergen Hoeller c672678423 Provider declaration for @Value method argument works again
Issue: SPR-12297
(cherry picked from commit 70fec47)
2014-10-07 00:02:03 +02:00
Juergen Hoeller ac4103d1b9 Further locking optimizations for the retrieval of non-singleton beans
Issue: SPR-12250
(cherry picked from commit 9d83281)
2014-10-07 00:01:40 +02:00
Juergen Hoeller d23b033f61 Polishing 2014-10-01 01:20:01 +02:00
Juergen Hoeller c74bad6e07 Remove outdated references to ContextLoaderServlet
Issue: SPR-7725
(cherry picked from commit 69998e3)
2014-10-01 01:14:57 +02:00
Juergen Hoeller f41e0bc796 Latest dependency updates (POI 3.10.1, JRuby 1.7.16) 2014-09-30 20:27:19 +02:00
Stephane Nicoll c7b6b72e73 Optimize ResolvableType cache
Prior to this commit, the ResolvableType static cache was holding a lot
of duplicates for simple types. We are using too much metadata to compute
the key when the class has no generic information. so setFoo(String foo)
and setBar(String bar) would result in two entries in the cache because
the TypeProvider is different. On a very simple application 65% of the
entries in the cache were duplicate.

When the type is a Class with no generic information, the ResolvableType
instance is a simple wrapper around it so we might just as well not cache
it at all as the cost of finding it back from the cache is higher than
creating that simple wrapper.

This commit adds an explicit check; if the type is a simple Class we just
return a "resolved" ResolvableType instance for it. On a few test cases,
this reduces the size of the cache by 85%

Issue: SPR-12275
(cherry picked from commit 6f1acdd)
2014-09-30 20:22:51 +02:00
Anders D. Johnson 1df8133237 Fix condition vs. conditional typo in documenation
Issue: SPR-12273
(cherry picked from commit bc0e59f)
2014-09-30 09:53:21 +02:00
Juergen Hoeller 43d40187d9 Polishing 2014-09-29 23:40:32 +02:00
Juergen Hoeller b91cab1fde Polishing 2014-09-26 22:18:15 +02:00
Juergen Hoeller d46c3fc7bf Deprecated BeanDefinitionDocumentReader's setEnvironment method in favor of access via XmlReaderContext
Issue: SPR-12248
2014-09-26 22:17:58 +02:00
Brian Clozel 3267e5aa33 Update default SockJS CDN location
This commit updates the default location of the SockJS' client library.
The previous location is being retired by the project maintainers.

The new default location is backed by several CDN providers:
* https://cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js

See sockjs/sockjs-client#198

Issue: SPR-12254
(cherry picked from commit a6e1c53)
2014-09-26 22:17:04 +02:00
Juergen Hoeller 251970a2f9 Tracking ASM 5.0.4 development: Fix for ASM issue 317539
Issue: SPR-12255
(cherry picked from commit e8486e2)
2014-09-26 21:47:41 +02:00
Juergen Hoeller 901346eb7d WebAsyncManager avoids concurrentResult.toString() and builds correct DeferredResultProcessingInterceptor keys
Issue: SPR-12253
(cherry picked from commit bf99d6a)
2014-09-26 21:47:30 +02:00
Juergen Hoeller 1ffefcb548 LiveBeansView escapes double quotes in resource descriptions
Issue: SPR-12252
(cherry picked from commit 92f7121)
2014-09-26 21:47:21 +02:00
Juergen Hoeller 0c680d6d03 Defensively use setRemoveOnCancelPolicy for JDK 6 compatibility
Issue: SPR-12238
(cherry picked from commit e003d21)
2014-09-26 21:47:01 +02:00
Juergen Hoeller b87329cda7 Remove outdated references to ContextLoaderServlet
Issue: SPR-7725
(cherry picked from commit 94e26fd)
2014-09-26 21:40:28 +02:00
Juergen Hoeller f21c8c37fb Avoid use of fragile Swing classes in tests (for compatibility with JDK 8u40)
Issue: SPR-12235
(cherry picked from commit a80495b)
2014-09-26 21:40:09 +02:00
Juergen Hoeller 50e50d0c18 Polishing
(cherry picked from commit 16325c2)
2014-09-20 00:51:19 +02:00
Juergen Hoeller 205e681295 Backported tests for property source ordering
Issue: SPR-12198
(cherry picked from commit 90b93ff)
2014-09-19 00:20:00 +02:00
Juergen Hoeller 29abca5399 Explicit exclusion of bridge methods in annotation post-processors (for Java 8 compatibility)
Issue: SPR-12187
(cherry picked from commit f4219ca)
2014-09-19 00:11:44 +02:00
Juergen Hoeller 60d5ff8dd5 Polishing
(cherry picked from commit a833889)
2014-09-17 22:10:08 +02:00
Juergen Hoeller d2e8b7e6ee ScheduledAnnotationBeanPostProcessor avoids needless re-scanning of non-annotated classes
Issue: SPR-12189
(cherry picked from commit 58b22ce)
2014-09-17 22:09:43 +02:00
Juergen Hoeller 7d55715213 Polishing 2014-09-17 13:53:12 +02:00
Juergen Hoeller d07230cf6a BeanDefinitionParserDelegate does not silently ignore 1.x 'singleton' attribute
Issue: SPR-12167
(cherry picked from commit 0cf472b)
2014-09-17 13:36:54 +02:00
Juergen Hoeller bf881e4544 Log warning for single optional constructor when no default constructor to fall back to
Issue: SPR-12161
(cherry picked from commit 80cec01)
2014-09-17 13:35:12 +02:00
Juergen Hoeller 36a1d6242e Latest dependency updates (Reactor 1.1.4) 2014-09-17 02:39:16 +02:00
Juergen Hoeller 10d4888408 Polishing 2014-09-17 02:37:32 +02:00
Juergen Hoeller f8b729aa5f Polishing 2014-09-17 01:51:23 +02:00
Juergen Hoeller b39e66b897 GenericTypeAwarePropertyDescriptor implements equals/hashCode for proper lookups on IBM JVM 6
Issue: SPR-12185
2014-09-17 01:42:30 +02:00
Juergen Hoeller 64849a46b4 Client request implementations enforce RFC 6265 (cookies in a single header)
Issue: SPR-12196
(cherry picked from commit 26a93b6)
2014-09-17 00:44:30 +02:00
Juergen Hoeller afb0342924 Accept empty Content-Type header
Issue: SPR-12173
(cherry picked from commit 70412a9)
2014-09-17 00:37:38 +02:00
Sam Brannen bea9f3ff76 Make SocketUtils a concrete class
Per the Javadoc for the SocketUtils() constructor, SocketUtils can be
instantiated as a Spring Bean in XML configuration files; however,
SocketUtils is currently abstract which prevents such usage.

This commit removes the 'abstract' declaration thereby allowing
SocketUtils to be instantiated as a Spring bean.

Issue: SPR-12169
(cherry picked from commit 559e81b)
2014-09-17 00:36:21 +02:00
Spring Buildmaster 31094f3ef6 Next Development Version 2014-09-04 01:18:19 -07:00
Juergen Hoeller d765698ac3 Polishing 2014-09-04 03:06:37 +02:00
Juergen Hoeller d081a4530c Polishing 2014-09-04 02:37:36 +02:00
Juergen Hoeller 97bd0ccfec Polishing 2014-09-04 01:43:15 +02:00
Juergen Hoeller 8543a5548e CachingConnectionFactory proceeds to physicalClose in case of logicalClose exceptions
Issue: SPR-12148
(cherry picked from commit 82f8b43)
2014-09-04 00:58:50 +02:00
Juergen Hoeller d2ef6dcb8d Polishing 2014-09-03 13:49:37 +02:00
Juergen Hoeller bff2bf2cdb AbstractAutowireCapableBeanFactory avoids early FactoryBean instantiation on currently created configuration bean
Issue: SPR-12141
(cherry picked from commit 4432c41)
2014-09-03 13:48:47 +02:00
Juergen Hoeller 72d62a7113 Cache.get(key, type) explicitly defines an IllegalStateException in case of a type mismatch
Issue: SPR-12145
(cherry picked from commit 2f93759)
2014-09-03 13:48:19 +02:00
Stephane Nicoll e1a01d4c3c Improve configuration changes in GuavaCacheManager
Prior to this commit, setting the parameters used to build the caches
was fragile in static mode as the caches were created right when the
setCacheNames setter was called.

This commit provides a better handling of such arguments and also
provide a way to restore the dynamic mode if necessary.

Issue: SPR-12120
(cherry picked from commit d47c543)
2014-09-01 14:08:14 +02:00
Sebastien Deleuze b7726ff48c Improve ResolvableType.hashCode() for better performance
Prior to this commit, when there was a lot of entries in the
ResolvableType.cache HashMap, getting a simple value could
take a lot of time due to a lot of calls to ResolvableType.equals().
ResolvableType.equals() used this.type, getSource(),
this.variableResolver.getSource() and this.componentType, but
ResolvableType.hashCode() used only this.type.

With this commit, ResolvableType.hashCode() now uses the same
fields than ResolvableType.equals().

Performance on the spring-resolvabletype-benchmark project:
 - 8000 us before this commit
 - 120 us with this commit

Issue: SPR-12122
(cherry picked from commit 7ea69fb)
2014-09-01 14:07:43 +02:00
Sam Brannen a52ff46fea Include ALL source artifacts in published sources jars
This commit updates the Gradle build to ensure that *all* source
artifacts are including in published 'sources' jars.

To achieve this, we are now assembling 'sources' jars from
'sourceSets.main.allSource' and not explicitly including or excluding
anything by default.

Issue: SPR-12085
(cherry picked from commit 07629a3c7c)
2014-08-26 16:51:26 +02:00
Juergen Hoeller eb3509a37c Polishing 2014-08-23 02:02:38 +02:00
Juergen Hoeller 93ad7f8def Polishing 2014-08-23 01:28:10 +02:00
Juergen Hoeller 54ba5c5e7b Polishing 2014-08-22 23:39:37 +02:00
Juergen Hoeller 249c688e9b DispatcherServlet's checkMultipart detects wrapped MultipartRequest as well
Issue: SPR-12114
(cherry picked from commit 786fd92)
2014-08-22 23:18:39 +02:00
Juergen Hoeller e324c2ab4a Polishing 2014-08-22 00:14:10 +02:00
Juergen Hoeller 39a23660fa PropertySource implementations perform conversion to String arrays via StringUtils (getting rid of EMPTY_NAMES_ARRAY)
(cherry picked from commit b73c531)
2014-08-22 00:09:53 +02:00
Juergen Hoeller 25971d9927 Consistent attribute documentation/formatting in spring-context and spring-mvc schemas
(cherry picked from commit b5763fe)
2014-08-22 00:04:12 +02:00
Juergen Hoeller 379e5abd83 ServerEndpointExporter can initialize itself based on a late-provided ServletContext as well (for Boot)
Also allows for direct setting of a ServerContainer and for custom triggering of endpoint registration.

Issue: SPR-12109
(cherry picked from commit 11805b6)
2014-08-22 00:02:14 +02:00
Juergen Hoeller 8fb7b694dd PersistenceAnnotationBeanPostProcessor defensively handles BeanDefinition access for extended EntityManagers
Issue: SPR-8834
(cherry picked from commit 592e344)
2014-08-22 00:01:39 +02:00
Juergen Hoeller 21d0ce5af8 DefaultListableBeanFactory defensively handles BeanDefinition access in getBean(Class)
Issue: SPR-10542
(cherry picked from commit 9d3d6d5)
2014-08-22 00:01:16 +02:00
Juergen Hoeller fb452fad7c Upgrade to Apache HttpComponents HttpClient 4.3.5 and HttpAsyncClient 4.0.2
Issue: SPR-12100
(cherry picked from commit 5cd1e6a)
2014-08-19 21:41:57 +02:00
Juergen Hoeller 2dd2b7175f ShallowEtagHeaderFilter supports Servlet 3.1's setContentLengthLong as well
Issue: SPR-12097
(cherry picked from commit 0c32d66)
2014-08-19 21:39:43 +02:00
Juergen Hoeller f418e6e981 Polishing 2014-08-18 22:24:43 +02:00
Juergen Hoeller 5e2b9b6f07 Latest dependency updates (AspectJ 1.8.2, Jackson 2.3.4) 2014-08-18 22:19:33 +02:00
Stephane Nicoll a95a3ae4ec Exclude infra modules from public distribution
Prior to this commit, spring-build-src and spring-framework-bom
internal artifacts were published as part of the distribution bundle.

This commit excludes those projects so that those unnecessary artifacts
are no longer shipped.

Issue: SPR-12087
2014-08-18 12:20:24 +02:00
Juergen Hoeller 0c0d23d0f4 Polishing 2014-08-15 00:58:05 +02:00
Juergen Hoeller a31ebb6c1e Polishing 2014-08-15 00:07:25 +02:00
Juergen Hoeller 42c090efa4 Polishing
Issue: SPR-12079
(cherry picked from commit 92bd240)
2014-08-13 15:28:36 +02:00
Juergen Hoeller 035a9b91d2 BeanNameViewResolver ignores non-View beans
Issue: SPR-12079
(cherry picked from commit 626a5fe)
2014-08-13 15:28:09 +02:00
Juergen Hoeller a7492fa55b Polishing 2014-08-12 22:24:50 +02:00
Juergen Hoeller ecf23ff6cd Remove outdated IDE, JIRA and Tomcat references
Issue: SPR-7521
(cherry picked from commit f1f1c4c)
2014-08-12 22:11:49 +02:00
Juergen Hoeller 4129f00a02 Polishing
(cherry picked from commit 4db258b)
2014-08-11 22:35:26 +02:00
Juergen Hoeller e2d71a8ccd Polishing 2014-08-11 15:45:54 +02:00
Juergen Hoeller 1034b0dae2 Tiles 3 TilesViewResolver allows for specifying custom TilesView subclasses as well
Issue: SPR-12075
(cherry picked from commit 7c57424)
2014-08-11 15:45:14 +02:00
Juergen Hoeller c08ded769a Polishing (includes varargs for selected String array setters) 2014-08-09 00:19:56 +02:00
Juergen Hoeller d61353db51 AnnotatedElementUtils adapts post-processed values to AnnotationAttributes as well
Issue: SPR-12065
(cherry picked from commit ef51d4d)
2014-08-09 00:19:28 +02:00
Rossen Stoyanchev 96efafef97 Fix documentation issue for user destinations.
Issue: SPR-11992
2014-07-31 17:15:52 -04:00
Rossen Stoyanchev fbf24a927d Update Javadoc (cherry-picked from 162734)
Issue: SPR-12028
2014-07-29 18:07:36 -04:00
Juergen Hoeller f2eea9d911 Polishing
(cherry picked from commit 8f484d3)
2014-07-29 11:50:50 +02:00
Juergen Hoeller cac0683dab Rearranged statement whitespace in Velocity macros
(cherry picked from commit 7bc9660)
2014-07-29 11:47:12 +02:00
Juergen Hoeller 9ad6618207 Polishing 2014-07-28 22:47:22 +02:00
Juergen Hoeller 84a4433898 AbstractTypeHierarchyTraversingFilter leniently ignores non-loadable super classes and interfaces
Issue: SPR-12042
(cherry picked from commit a3163ce)
2014-07-28 22:27:37 +02:00
Juergen Hoeller 44fac40a2f Latest dependency updates (Hibernate Validator 4.3.2, propdeps plugin 0.0.7) 2014-07-28 22:27:28 +02:00
Juergen Hoeller 6e95b2613e Polishing 2014-07-24 18:35:49 +02:00
Arjen Poutsma fca72f6b65 StaxStreamXMLReader ignores significant whitespace
The StaxStreamXMLReader no longer handles all whitespace as ignorable
whitespace.

Issue: SPR-12000
(cherry picked from commit d6950d8)
2014-07-24 17:57:14 +02:00
Juergen Hoeller 0dca31c39b Typo fixes and cleanup of outdated Java 5 references
Issue: SPR-12020
(cherry picked from commit d4fe732)
2014-07-24 17:56:35 +02:00
Juergen Hoeller d45f743248 TypeDescriptor's getResolvableType() and getSource() are @since 4.0
(cherry picked from commit 0ce90f1)
2014-07-24 17:55:39 +02:00
Juergen Hoeller acbd61b87a ConcurrentMapCacheManager recreates caches in case of setAllowNullValues change
Issue: SPR-12026
(cherry picked from commit 7848412)
2014-07-24 17:54:22 +02:00
Juergen Hoeller dcb83c2daf Autowiring rejects self references to a factory method on the same bean as well
Issue: SPR-12018
(cherry picked from commit 496492b)
2014-07-24 17:53:21 +02:00
Juergen Hoeller 5342d92db7 ResourceHttpMessageConverter does not call contentLength() on InputStreamResource
Issue: SPR-12017
(cherry picked from commit f0bcb77)
2014-07-24 17:50:31 +02:00
Juergen Hoeller 7af1e002bd AbstractMessageListenerContainer calls "Session.recover()" in case of rollback attempt on non-transacted Session
Issue: SPR-12015
(cherry picked from commit c082220)
2014-07-24 17:49:34 +02:00
Juergen Hoeller abd5f18e85 AbstractApplicationContext logs initialization exception before trying to cancel refresh attempt
Issue: SPR-12010
(cherry picked from commit 5e2fbe7)
2014-07-24 17:48:08 +02:00
Juergen Hoeller 940ae0c528 ClassUtils.isCacheSafe defensively catches SecurityException (for Google App Engine compatibility)
Issue: SPR-12002
(cherry picked from commit 48fea0b)
2014-07-24 17:46:42 +02:00
Juergen Hoeller 5f77dce1ee SelectedValueComparator defensively handles null values in exhaustiveCompare
Issue: SPR-12001
(cherry picked from commit 980f971)
2014-07-24 17:46:04 +02:00
Juergen Hoeller 0ef17a2f2c NestedIOException can use IOException constructor with cause argument on JDK 6+
(cherry picked from commit c18b6bf)
2014-07-24 17:44:57 +02:00
Juergen Hoeller 452260316e DefaultListableBeanFactory's registerBeanDefinition only calls resetBeanDefinition in case of pre-existing bean definition or pre-existing singleton instance
Issue: SPR-8318
(cherry picked from commit a4968b9)
2014-07-24 17:43:59 +02:00
Stephane Nicoll c0815407bb Revert ea16ce0
The latest build preview of jdk 1.8.0_20 does not exhibit the problem
anymore.

Issue: SPR-11973
2014-07-23 19:43:09 +02:00
Juergen Hoeller 845528a6cb Polishing 2014-07-10 18:18:44 +02:00
Juergen Hoeller ed88155f55 Reverted test for 1.8 bytecode parsing - 4.0.x tests are still on target 1.7
Issue: SPR-11979
2014-07-10 17:45:08 +02:00
Brian Clozel a3a76d8c15 Fix UriComponentsBuilder.fromUriString parsing error
This commit fixes cases where part of the URI was mistaken for the
userinfo when:
* the URI did not contain any path
* the query string contained the "@"

Issue: SPR-11970
(cherry picked from commit a4484bb)
2014-07-10 16:46:33 +02:00
Juergen Hoeller 10a039000b Test ASM5's bytecode parsing of INVOKESPECIAL/STATIC on interfaces
Issue: SPR-11979
(cherry picked from commit 29f6f3d)
2014-07-10 16:44:59 +02:00
Spring Buildmaster 7de42efaf2 Next development version 2014-07-07 20:49:34 -07:00
Phillip Webb 7dcc01e69b Disable processing javac warnings
Set `-Xlint:-processing` to disable annotation processing warnings.
Required when building on JDK 1.8.0_20-b05 due to JDK-8039469.

Issue: SPR-11973
(cherry picked from commit ea16ce0)
2014-07-07 19:22:07 -07:00
Juergen Hoeller adb73d5f35 Remaining polishing 2014-07-08 00:21:17 +02:00
Juergen Hoeller 7eee7d2e30 Polishing
Issue: SPR-8045
2014-07-08 00:04:19 +02:00
Juergen Hoeller d72ee809b7 Polishing
(cherry picked from commit b559f15)
2014-07-07 21:51:01 +02:00
Juergen Hoeller 31a251e44a Polishing 2014-07-07 20:53:26 +02:00
Brian Clozel ce6adfbe35 Remove Jackson dependency from TransportHandler hierarchy
Prior to this change, AbstractHttpReceivingTransportHandler had a direct
dependency on a Jacckson Exception (checking that exception in a catch
clause). This can cause issues for applications that don't have that
dependency.

This commit removes that direct dependency, still logging the
appropriate log messages using a parent exception (IOException) and
reflection.

Issue: SPR-11963
(cherry picked from commit e549103)
2014-07-07 20:39:29 +02:00
Juergen Hoeller 60d3a7f300 RestTemplate accepts getMessageConverters() List on setMessageConverters again
Issue: SPR-11962
(cherry picked from commit 1222ca3)
2014-07-07 20:37:35 +02:00
Juergen Hoeller 6dbb465585 TypedValue implements equals/hashCode based on value and TypeDescriptor
Issue: SPR-11960
(cherry picked from commit a8848cb)
2014-07-07 20:36:53 +02:00
Juergen Hoeller 47de943926 Upgraded to AspectJ 1.8.1 (also declared as recommended user version) and Tomcat 8.0.9 (first stable version)
Issue: SPR-11957
2014-07-05 11:14:34 +02:00
Juergen Hoeller 0164f8691a CachedSessionInvocationHandler includes durable flag in ConsumerCacheKey
Issue: SPR-11956
(cherry picked from commit 6fd0fc7)
2014-07-05 08:56:10 +02:00
Juergen Hoeller 077c624b73 ConstructorResolver's exception message on null factory-bean hints at potential BeanPostProcessor involvement
Issue: SPR-11951
(cherry picked from commit 6c41cc3)
2014-07-04 22:32:10 +02:00
Juergen Hoeller dae81fd5e6 CachedSessionInvocationHandler properly caches createSharedConsumer results
Issue: SPR-11956
(cherry picked from commit 7a7641b)
2014-07-04 22:31:38 +02:00
Juergen Hoeller 837f27851f Jms2MessageProducerInvocationHandler specifically delegates all CompletionListener-based send methods
Issue: SPR-11950
(cherry picked from commit b6a7957)
2014-07-04 16:13:14 +02:00
Juergen Hoeller c3b992c5c4 Jms2MessageProducerInvocationHandler properly delegates to CachedMessageProducer.this
Issue: SPR-11949
(cherry picked from commit 134e5a2)
2014-07-04 00:27:25 +02:00
Juergen Hoeller f8ab4f6980 Reference documentation backports
Issue: SPR-11944
Issue: SPR-11945
2014-07-03 22:40:02 +02:00
Juergen Hoeller 77406eded8 Refined DefaultJpaDialect's InvalidIsolationLevelException message
Issue: SPR-8325
(cherry picked from commit af13310)
2014-07-03 22:34:14 +02:00
Rossen Stoyanchev 977c5ca439 Synchronize request init in AbstractHttpSockJsSession
Although unlikely in practice (but not impossible), the SockJS
integration tests write a message while the request is initializing.
This change adds synchronization around request intiailization
for the SockJS HTTP sesion.

This is a backport of:
https://github.com/spring-projects/spring-framework/commit/59e02e63c427659e701cc371d210faf1a85c1d42

Issue: SPR-11916
2014-07-02 18:28:48 -04:00
Juergen Hoeller ede2150544 Polishing 2014-07-02 17:32:43 +02:00
Juergen Hoeller 07edf11e21 Defensively check for pre-resolved FactoryBean.getObject() results in circular reference scenarios
Issue: SPR-11937
(cherry picked from commit d870b38)
2014-07-02 00:23:32 +02:00
Juergen Hoeller f27b9498be CachedIntrospectionResults uses SoftReference instead of WeakReference for non-cache-safe entries
Issue: SPR-11867
2014-07-02 00:22:24 +02:00
Rossen Stoyanchev e9ecaf6f4a Fix issue with StompSubProtocolHandler initialization
This change ensures that StompSubProtocolHandler is injected with an
ApplicationEventPublisher for both the Java and XML config.

Backport for:
https://github.com/spring-projects/spring-framework/commit/0dddb6f3e19377cb397f0396e85734df2c19c2b6
https://github.com/spring-projects/spring-framework/commit/4372dac002be4dd9be9568fafb442cde5b6d1ada

Issue: SPR-11825
2014-07-01 14:59:51 -04:00
Rossen Stoyanchev 5092414842 Improve SubscriptionRegistry subscription removal
This a backport of:
https://github.com/spring-projects/spring-framework/commit/ce20abde51ac52dde2f318e28004af80cca886fe
https://github.com/spring-projects/spring-framework/commit/083d415fc4d54ce19f7939b3d837f1f1eda5732a

Issue: SPR-11931, SPR-11930
2014-07-01 14:35:22 -04:00
Rossen Stoyanchev 6438209557 Remove JDK 1.7 guards 2014-07-01 14:33:27 -04:00
Juergen Hoeller 7396210d40 Package javadoc cleanup for web.servlet.mvc, removing outdated references
Issue: SPR-11935
(cherry picked from commit ba522e5)
2014-07-01 18:12:42 +02:00
Juergen Hoeller b9935e9fe3 BeanFactoryAnnotationUtils consistently applies bean name fallback when no BeanDefinition present
Issue: SPR-11915
(cherry picked from commit f8b6114)
2014-07-01 18:12:23 +02:00
Juergen Hoeller 86ea3059b6 Polishing 2014-07-01 15:11:36 +02:00
Juergen Hoeller 4384c1ae50 Upgrade to Reactor 1.1.3 2014-07-01 15:10:09 +02:00
Juergen Hoeller 347b7313b8 Dependency updates (as appropriate for the 4.0.x line) 2014-07-01 12:31:47 +02:00
Juergen Hoeller 3fb05017a1 Reference documentation overhaul (backported from master)
Issue: SPR-11853
Issue: SPR-11906
2014-07-01 12:31:16 +02:00
Juergen Hoeller 48f753f368 Polishing (backported from master) 2014-07-01 12:12:42 +02:00
Juergen Hoeller c16032b98a Consistent declaration of private static final logger variables
Issue: SPR-11905
(cherry picked from commit 18131bf)
2014-07-01 12:09:29 +02:00
Juergen Hoeller c32d5592c7 AbstractAutowireCapableBeanFactory's createBean/autowireBean/configureBean use CacheUtils.isCacheSafe to re-enable PropertyDescriptor caching
Issue: SPR-11875
(cherry picked from commit 974bd43)
2014-07-01 12:07:26 +02:00
Juergen Hoeller 5f695a47db Cache Class.getDeclaredMethods() results and avoid pattern matching in isCglibRenamedMethod as far as possible
Issue: SPR-11882
Issue: SPR-11894
2014-07-01 12:06:34 +02:00
Juergen Hoeller 74c878ee0e AnnotationUtils defensively catches and logs unexpected exceptions from retrieval attempts (proceeding like the annotation wasn't there)
Issue: SPR-11874
(cherry picked from commit 2c0c081)
2014-07-01 12:05:38 +02:00
Juergen Hoeller 178d58cc75 ConfigurationClassParser falls back to ASM-based resolution of member classes in case of NoClassDefFoundError
Issue: SPR-11844
(cherry picked from commit 6aa9c40)
2014-07-01 12:02:27 +02:00
Juergen Hoeller 7b38b41bf5 ConfigurationClassPostProcessor skips pre-processed bean definitions now (avoiding side effects in case of multiple CCPPs)
Issue: SPR-11858
(cherry picked from commit b625512)
2014-07-01 12:01:50 +02:00
Juergen Hoeller 6403479902 TypeDescriptor's nested type traversal leniently returns null in case of unresolvable nested type
Issue: SPR-11898
(cherry picked from commit d663580)
2014-07-01 12:00:20 +02:00
Juergen Hoeller 5af1a691bc DefaultAdvisorChainFactory never passes null into ClassFilter, enabling async advisor to work without target class as well
Issue: SPR-11910
(cherry picked from commit a9b650f)
2014-07-01 11:59:43 +02:00
Juergen Hoeller 9f967b1d81 SharedEntityManagerCreator immediately throws TransactionRequiredException on persist, merge, remove etc (as required by JPA spec)
Issue: SPR-11923
(cherry picked from commit 045d735)
2014-07-01 11:59:11 +02:00
Juergen Hoeller e50507206f DefaultSubscriptionRegistry's removeSubscriptionInternal defensively handles non-existing destinations
Issue: SPR-11832
(cherry picked from commit 5a8e470)
2014-07-01 11:58:08 +02:00
Juergen Hoeller c73ac075c4 UriComponentBuilder allows for multiple independent build() calls on same builder instance
Issue: SPR-11885
(cherry picked from commit d239016)
2014-07-01 11:57:45 +02:00
Juergen Hoeller 0bf0901b8f SelectTag consistently checks specified 'multiple' attribute now, never falling back to forceMultiple in case of user-provided value
Issue: SPR-11903
(cherry picked from commit 779ca99)
2014-07-01 11:57:15 +02:00
Juergen Hoeller 7d94b5e853 FrameworkPortlet properly initializes StandardPortletEnvironment's property sources and exposes local PortletRequestAttributes in case of pre-bound ServletRequestAttributes as well
Issue: SPR-11816
Issue: SPR-11295
2014-07-01 11:55:19 +02:00
Juergen Hoeller 8ddbbc2e67 PathMatchingResourcePatternResolver's findPathMatchingResources needs to check for VFS before checking isJarResource
ResourceUtils isFileURL also detects "vfsfile" as a file system protocol (again).

Issue: SPR-11887
2014-07-01 11:54:16 +02:00
Juergen Hoeller 0a34f86333 MBeanExportConfiguration's SpecificPlatform properly calls afterPropertiesSet
Also makes the nested SpecificPlatform enum public for Spring Boot to reuse it.

Issue: SPR-11877
(cherry picked from commit 6f68b03)
2014-07-01 11:52:53 +02:00
Juergen Hoeller a0c86ae455 WebSphereUowTransactionManager exposes SmartTransactionObject
Issue: SPR-11876
(cherry picked from commit 03f3412)
2014-07-01 11:51:33 +02:00
Juergen Hoeller 0761ee99ae Workaround for WFLY-3474 NullPointerException
Prior to this commit, the ServletResponseHttpHeaders.get method
would throw an NPE when used under Wildfly 8.0.0.Final and 8.1.0.Final.
This can be traced to WFLY-3474, which throws an NPE when calling
HttpServletResponse.getHeaders("foo") and that header has not
been defined prior to that.
This would cause NPE being thrown by AbstractSockJsService when
checking for CORS HTTP headers in the server HTTP response.

This commit surrounds that method call in AbstractSockJsService and
guards against this issue.

Issue: SPR-11919
(cherry picked from commit 24cdefb)
2014-07-01 11:51:01 +02:00
Juergen Hoeller 9054f4fb58 HttpHeaders fails getAllow if set to EmptyCollection
Prior to this commit, calls to getAllow would fail is setAllow was set
to an EmptyCollection right before.

    java.lang.IllegalArgumentException: No enum constant
    org.springframework.http.HttpMethod

This commit fixes this by testing the header value for an empty value
before trying to use it to get a value from the Enum.

Issue: SPR-11917
(cherry picked from commit 9919a98)
2014-07-01 11:46:53 +02:00
Rossen Stoyanchev 41e78d0f50 Fix failing test 2014-06-29 22:08:25 -04:00
Rossen Stoyanchev 526d5ba253 Fix warnings from sniff task on master 2014-06-29 17:44:43 -04:00
Rossen Stoyanchev 40c203ca71 Minor fix in STOMP broker relay
This is a backport for a change made as part of:
https://github.com/spring-projects/spring-framework/commit/113fd1180a14656a89d6d6639d259c577d70fbc5

Issue: SPR-11884
2014-06-29 16:58:47 -04:00
Rossen Stoyanchev d18fc53148 Avoid multiple invocations of afterConnectionClosed
This change ensures the state of a SockJS session is set to CLOSED
immediately after close is invoked. This avoids duplicate invocations
of afterConnectionClosed in WebSocket transport.

This is a backport of:
https://github.com/spring-projects/spring-framework/commit/3af488a701834f61b89cd84040605a6252962e9c

Issue: SPR-11884
2014-06-29 16:58:13 -04:00
Rossen Stoyanchev 618771d59d Add check for unused WebSocket sessions
Sessions connected to a STOMP endpoint are expected to receive some
client messages. Having received none after successfully connecting
could be an indication of proxy or network issue. This change adds
periodic checks to see if we have not received any messages on a
session which is an indication the session isn't going anywhere
most likely due to a proxy issue (or unreliable network) and close
those sessions.

This is a backport for commit:
https://github.com/spring-projects/spring-framework/commit/a3fa9c979777e554efad0df429041767f05dfdb8

Issue: SPR-11884
2014-06-29 16:58:13 -04:00
Rossen Stoyanchev 87077d3fad Add support for setting removeOnCancelPolicy
This change introduces removeOnCancelPolicy on ThreadPoolTaskScheduler
and ScheduledExecutorFactoryBean and sets it to true for SockJS.
This ensures that cancelled tasks are removed immediately to avoid
the "unbounded retention of cancelled tasks" that is mentioned in
the Javadoc ScheduledThreadPoolExecutor:

"By default, such a cancelled task is not automatically removed from
the work queue until its delay elapses. While this enables further
inspection and monitoring, it may also cause unbounded retention of
cancelled tasks. To avoid this, set setRemoveOnCancelPolicy to true,
which causes tasks to be immediately removed from the work queue at
time of cancellation."

This is a backport for:
https://github.com/spring-projects/spring-framework/commit/7441f2301281049cff7224bf650646490388080e

Issue: SPR-11918
2014-06-29 16:57:58 -04:00
Rossen Stoyanchev c0c3618906 Fix concurrency issues in SockJS session impls
Cherry-picked from:
https://github.com/spring-projects/spring-framework/commit/fcf6ae83285890f2e8e7de77dcc6e633129978e8

Issue: SPR-11916
2014-06-29 15:50:55 -04:00
Spring Buildmaster 0405bb401a Next development version 2014-05-20 06:41:20 -07:00
Juergen Hoeller e3e71ba92a Servlet 3 multipart request implements getParameterMap defensively as well
Issue: SPR-11074
(cherry picked from commit c7d1c49)
2014-05-20 11:11:56 +02:00
Juergen Hoeller d4e1b9eb4c Polishing
(cherry picked from commit 6fef8b9)
2014-05-20 11:11:33 +02:00
Rossen Stoyanchev 44ee51a6c9 Disable URL resolution in DTD declarations
Issue: SPR-11768
2014-05-19 22:23:51 -04:00
Juergen Hoeller ba6d187b5c Consistent MvcUriComponentsBuilder assertion handling
(cherry picked from commit 61b47ba)
2014-05-20 01:51:33 +02:00
Juergen Hoeller 54636b3f7c Further UriComponentsBuilder javadoc revision 2014-05-20 01:13:18 +02:00
Juergen Hoeller 545c28fd4e Minor UriComponentsBuilder javadoc revision 2014-05-20 00:47:03 +02:00
Juergen Hoeller 95a7bfd327 Consistent use of IllegalStateException instead of InternalError for UnsupportedEncodingException cause
(cherry picked from commit d9b39ad)
2014-05-20 00:42:48 +02:00
Juergen Hoeller ccebbf74ec Latest patches from ASM trunk
(cherry picked from commit cfc720d)
2014-05-19 22:59:39 +02:00
Juergen Hoeller c350080f99 StringUtils.parseLocaleString parses variant correctly when variant contains country code
This commit also includes a JUnit 4 style revision of StringUtilsTests and ObjectUtilsTests.

Issue: SPR-11806
(cherry picked from commit 295a6ae)
2014-05-19 22:46:47 +02:00
Juergen Hoeller 6b9738fd68 Building against latest javax.el 2.2.x version
(cherry picked from commit f73a8ba)
2014-05-19 20:46:42 +02:00
Juergen Hoeller 1120680c65 Consistently log Class.getName() instead of Class.toString(), avoiding double class term in log message
Issue: SPR-11804
(cherry picked from commit 2619955)
2014-05-19 20:46:14 +02:00
Juergen Hoeller a2ef2c9d3e Refined check for NoClassDefFoundError in getTestExecutionListeners()
Issue: SPR-11804
(cherry picked from commit 41ed228)
2014-05-19 17:28:37 +02:00
Juergen Hoeller 1bbc032071 Backported proper updateAccessedAttributes test
Issue: SPR-11738
(cherry picked from commit 6188550)
2014-05-19 16:42:42 +02:00
Juergen Hoeller c70a81a805 Javadoc fixes 2014-05-19 00:08:46 +02:00
Juergen Hoeller 3c709a763d Servlet 3 multipart request implements getParameterNames defensively (for WebLogic 12 compatibility)
This commit also includes lazy resolution support for StandardServletMultipartResolver, along the lines of existing lazy mode in CommonsMultipartResolver.

Issue: SPR-11074
Issue: SPR-11730
(cherry picked from commit 82336c3)
2014-05-18 20:27:44 +02:00
Juergen Hoeller 7d78c65187 Properly evaluate @Conditional in case of multiple imports for same config class (fixing regression in Spring Boot)
Issue: SPR-11788
2014-05-18 02:00:11 +02:00
Rossen Stoyanchev 748167bfa3 Improve StringUtils.cleanPath
Issue: SPR-11793
2014-05-16 11:27:55 -04:00
Juergen Hoeller 3e70013b55 JmsResourceHolder checks for nested DataSource transactions as well (for Oracle AQ compatibility)
Issue: SPR-11791
(cherry picked from commit 5faacd5)
2014-05-16 15:36:16 +02:00
Juergen Hoeller ea9ad4ee9b Properly evaluate @Conditional in case of multiple imports for same config class
Issue: SPR-11788
(cherry picked from commit 52f44b3)
2014-05-16 15:35:56 +02:00
Rossen Stoyanchev 482eff81e1 Await TcpClient shutdown in STOMP relay 2014-05-15 21:46:44 -04:00
Juergen Hoeller c706cbbed4 Latest possible dependency updates for spring-orm
(cherry picked from commit 0d22719)
2014-05-15 17:35:32 +02:00
Juergen Hoeller 7bc38acbf6 Polishing 2014-05-15 15:23:11 +02:00
Juergen Hoeller 297e4eec36 Keep unused MemorySafeUndeclaredThrowableStrategy around in deprecated form for the 4.0.x line
Issue: SPR-11782
2014-05-15 15:05:00 +02:00
Juergen Hoeller 235b65d103 Polishing
(cherry picked from commit b0f0d2f)
2014-05-15 14:43:02 +02:00
Juergen Hoeller 8a28645dd6 ResultSetWrappingSqlRowSet preserves first matching column per name (as defined in ResultSet's javadoc)
Issue: SPR-11786
(cherry picked from commit 0728e32)
2014-05-15 14:40:43 +02:00
Juergen Hoeller f94ded830d Consistent use of ClassUtils.forName instead of class.getClassLoader().loadClass
Issue: SPR-11780
(cherry picked from commit 551950c)
2014-05-15 14:40:15 +02:00
Juergen Hoeller ad8f17b6af Test compatibility with JasperReports 5.5.2 2014-05-12 23:35:17 +02:00
Juergen Hoeller 261520cea0 Undertow-related polishing
(cherry picked from commit 2750ab6)
2014-05-12 23:32:12 +02:00
Juergen Hoeller 00aa40b8da Consistent EhCache version between 4.1 and 4.0.5 2014-05-12 23:27:16 +02:00
Juergen Hoeller ac9b64e528 Consistent declaration of JSP, JSTL and JavaMail API dependencies; updated several dependencies to latest maintenance releases (Tiles 3.0.4, Jetty 9.1.5) 2014-05-12 21:50:13 +02:00
Juergen Hoeller 1e7fade89e JasperReports-related polishing
(cherry picked from commit 782d10c)
2014-05-12 20:50:24 +02:00
Stephane Nicoll 3c58be05a5 Fix typo
Issue: SPR-11571
(cherry picked from commit 6551aa6)
2014-05-08 16:38:08 +02:00
Juergen Hoeller ef290ff95c Additional tests for configuration class importing via ASM
Issue: SPR-11647
(cherry picked from commit 8c9116f)
2014-05-08 16:31:07 +02:00
Juergen Hoeller ae45794451 IdToEntityConverter defensively handles access to getDeclaredMethods
Issue: SPR-11758
(cherry picked from commit 381ccde)
2014-05-08 16:30:45 +02:00
Juergen Hoeller fccec210b4 GenericTypeResolver returns null for entirely unresolvable type arguments only
Issue: SPR-11763
(cherry picked from commit bea34ea)
2014-05-08 16:28:53 +02:00
Sebastien Deleuze 96da77ef75 Avoid ConcurrentModificationException
Removal of cached destination is now moved outside the for loop
that removes subscriptions to avoid ConcurrentModificationException.

Also since updateCache is a LinkedHashMap with accessOrder=true,
a simple access with updateCache.get() modify the map.
By iterating over updateCache.entrySet(), we avoid this update.

Issue: SPR-11755
2014-05-06 20:22:05 -04:00
Juergen Hoeller c9417d0610 Fixed invalid code tag in javadoc
(cherry picked from commit a139670)
2014-05-01 10:55:55 +02:00
Spring Buildmaster 085e52fc31 Next development version 2014-04-30 15:41:11 -07:00
Juergen Hoeller 8f175046c8 spring-orm-hibernate4 requires aopalliance dependency now (after propdeps upgrade) 2014-04-30 23:19:07 +02:00
Juergen Hoeller c1dbd9f150 Upgraded to propdeps plugin 0.0.6
(cherry picked from commit a842b93)
2014-04-30 22:58:56 +02:00
Juergen Hoeller 42a35ef3be AnnotationMetadataReadingVisitor passes metaAnnotationMap into getMergedAnnotationAttributes algorithm, for finding out about applicable overrides
Issue: SPR-11649
(cherry picked from commit 842a8a8)
2014-04-30 22:57:09 +02:00
Rossen Stoyanchev 21fd68150a Log ignored CONNECT messages at error level
Issue: SPR-11673
2014-04-30 11:12:32 -04:00
Rossen Stoyanchev d20259be1d Log STOMP ERROR frames at error level
Issue: SPR-11673
2014-04-30 11:01:18 -04:00
Rossen Stoyanchev 6ca921021c Update log level
Issue: SPR-11673
2014-04-30 10:28:27 -04:00
Rossen Stoyanchev eab9d24c31 Fix Javadoc typo 2014-04-30 10:07:51 -04:00
Juergen Hoeller 15749c2a9d Upgraded to Gradle 1.12 and updated several dependencies to latest maintenance releases
(cherry picked from commit e84f61b)
2014-04-30 14:32:12 +02:00
Juergen Hoeller 93b0f0b126 JRubyScriptUtils defensively handles null Nodes in findClassNode (fails against JRuby 1.7.12 otherwise)
Issue: SPR-11747
(cherry picked from commit adb616b)
2014-04-30 14:32:07 +02:00
Juergen Hoeller 27b2ed1614 Spring Framework build uses Reactor 1.1 GA now, getting rid of last remaining pre-GA dependency 2014-04-30 11:41:57 +02:00
Rossen Stoyanchev 790d62bcb1 Simplify and improve STOMP broker relay int tests 2014-04-29 23:01:40 -04:00
Rossen Stoyanchev 563476f57c Split destination cache into access vs update
Issue: SPR-11657
2014-04-29 22:16:49 -04:00
Rossen Stoyanchev 79de45b805 Add cache limit to DefaultSessionRegistry and polish
Issue: SPR-11657
2014-04-29 18:17:40 -04:00
Sebastien Deleuze 63a868dafb Fix DefaultSubscriptionRegistry when using pattern destinations
DestinationCache is now used for both plain and pattern
destinations. It stores internally the subscriptions map for each
cached destination. Subscriptions are initially created when there
is no cache for the requested destination, and are updated when
subscriptions change.

Issue: SPR-11657
2014-04-29 18:17:30 -04:00
Juergen Hoeller 1afdd9bd75 Polishing
(cherry picked from commit 02aca9c)
2014-04-30 00:10:58 +02:00
Juergen Hoeller d0c839f0eb Polishing 2014-04-29 16:21:06 +02:00
Juergen Hoeller 744727b8aa AbstractAdvisingBeanPostProcessor uses target class check for existing proxy but checks against actual exposed object otherwise (catching introductions)
Issue: SPR-11725
(cherry picked from commit a0658c5)
2014-04-29 16:01:44 +02:00
Rossen Stoyanchev 9fbb7394e2 Polish STOMP documentation 2014-04-28 22:35:51 -04:00
Sebastien Deleuze 80cb0c4e5b Include more guidance about DispatcherServlet context
Also update <mvc:annotation-driven /> comment in XSD.

Issue: SPR-11703
2014-04-28 22:10:52 -04:00
Rossen Stoyanchev 5c4804f4a4 Document STOMP-related ApplicationContext events
Issue: SPR-11672
2014-04-28 21:59:09 -04:00
Juergen Hoeller a679f3e7a3 Polishing
(cherry picked from commit be5f2a8)
2014-04-28 23:52:23 +02:00
Juergen Hoeller bd5b3749c5 Revised @PropertySource parsing for consistent PropertySource naming, avoiding accidental overriding by name
Issue: SPR-11637
(cherry picked from commit ab24dda)
2014-04-28 23:47:33 +02:00
Juergen Hoeller 89398b0811 AspectJExpressionPointcut defensively handles fallback expression parsing
Issue: SPR-9335
(cherry picked from commit ce4912b)
2014-04-28 23:47:25 +02:00
Juergen Hoeller a87c9b8c5c Test for base package specified as config location
Issue: SPR-11647
(cherry picked from commit 8e6e6c2)
2014-04-28 23:47:14 +02:00
Juergen Hoeller d0f9853769 Test for overriding singleton @Bean method with scoped proxy in configuration subclass
Issue: SPR-10744
(cherry picked from commit 299776f)
2014-04-28 23:46:51 +02:00
Juergen Hoeller bed739ce92 GenericBeanDefinition's toString() takes parent definition into account
Issue: SPR-9671
(cherry picked from commit 0ef29b2)
2014-04-28 23:46:40 +02:00
Rossen Stoyanchev cb712afa97 Improve handling of disconnects in STOMP broker relay
This is a backport of:
https://github.com/spring-projects/spring-framework/commit/990f5bb720ac172fa659a59339df06065d31c0bf

Issue: SPR-11655
2014-04-28 10:08:00 -04:00
Juergen Hoeller c97c246940 Polishing 2014-04-28 00:29:04 +02:00
Juergen Hoeller 4196e6c96f AbstractMarshaller avoids SAXSource workaround when processExternalEntities=true
Issue: SPR-11737
(cherry picked from commit 93d13cf)
2014-04-28 00:27:04 +02:00
Juergen Hoeller 59cef3ce81 General defensiveness about the bootstrap ClassLoader (i.e. null ClassLoader)
Issue: SPR-11721
2014-04-28 00:26:18 +02:00
Juergen Hoeller c8ea80d7ed Configuration class processing explicitly skips java.* classes since we'll never find @Bean annotations there anyway
Issue: SPR-11718
(cherry picked from commit 470e9c8)
2014-04-28 00:17:19 +02:00
Juergen Hoeller 656fc52ff9 @Bean processing explicitly ignores bridge methods (for method overrides with return type narrowing on JDK 8)
Issue: SPR-11718
(cherry picked from commit dc93406)
2014-04-28 00:16:38 +02:00
Rossen Stoyanchev a4d6f8473e Upgrade to reactor 1.1 RC1 2014-04-25 12:32:36 -04:00
Rossen Stoyanchev 443fb8e4ee Fix issue with subscribe destination
The original fix for SPR-11423:
https://github.com/spring-projects/spring-framework/commit/32e5f57e647022d9ea82c03670936bf31f8467de

was insufficient when using an external broker since the original
destination header has to be in the "native headers" map (i.e. with
STOMP headers) in order to be included in messages broadcast by
the broker.
2014-04-25 12:17:08 -04:00
Juergen Hoeller 95b1cb7173 AspectJ 1.8 final used in build, plus TestNG preparations for optional -target 1.8 usage
Issue: SPR-11212
Issue: SPR-11699
2014-04-24 11:09:39 +02:00
Juergen Hoeller 51fb485181 Polishing
(cherry picked from commit 9353332)
2014-04-24 10:32:38 +02:00
Juergen Hoeller f16e6c4105 General defensiveness about the bootstrap ClassLoader (i.e. null ClassLoader)
Issue: SPR-11721
(cherry picked from commit c05ab3e)
2014-04-24 10:31:48 +02:00
Juergen Hoeller 4dbc0c296c Polishing
(cherry picked from commit ec7d80b)
2014-04-24 10:31:39 +02:00
Juergen Hoeller d71d38bfaf ServletServerHttpResponse specifically checks for Servlet 3.0's HttpServletResponse.getHeader(String) method
Issue: SPR-11712
(cherry picked from commit 21f9ca0)
2014-04-24 10:31:29 +02:00
Juergen Hoeller eb28259371 SpringProperties falls back to ClassLoader.getSystemResource when loaded in bootstrap ClassLoader
Issue: SPR-11721
(cherry picked from commit 9cb5f48)
2014-04-24 10:31:20 +02:00
Juergen Hoeller 7ae6a60f43 checkNotModified leniently handles IE-10-style If-Modified-Since values and silently proceeds if header value cannot be parsed at all
Issue: SPR-11727
(cherry picked from commit 794e859)
2014-04-24 10:30:49 +02:00
Juergen Hoeller d3c9a31e9a DispatcherServlet skips multipart resolution if error page exception attribute indicates MultipartException as root cause
Issue: SPR-11716
(cherry picked from commit 5b47816)
2014-04-24 10:30:12 +02:00
Juergen Hoeller 5aa126600f Final patches from ASM 5.0.2 release
Issue: SPR-11212
(cherry picked from commit fb66567)
2014-04-24 10:29:50 +02:00
Juergen Hoeller 2f15f72fcc ShallowEtagHeaderFilter writes body early on sendError/sendRedirect and interprets setContentLength/setBufferSize as a hint for capacity increase
Issue: SPR-11705
Issue: SPR-11717
(cherry picked from commit 3f392e3)
2014-04-24 10:28:42 +02:00
Juergen Hoeller d5aacdefd9 Polishing
(cherry picked from commit 700c3b2)
2014-04-24 10:27:43 +02:00
Juergen Hoeller e379e77b96 considerInterfaces should work without considerInherited as well
Issue: SPR-11719
(cherry picked from commit 5ab7076)
2014-04-24 10:27:15 +02:00
Juergen Hoeller 9c45755890 AnnotationTypeFilter prevents ASM-based loading of java.* interfaces as well
Issue: SPR-11719
(cherry picked from commit 945335d)
2014-04-24 10:26:42 +02:00
Juergen Hoeller 5962fc2590 EQ/NE do not fail in case of a Comparable mismatch and apply a specific CharSequence equality check
Issue: SPR-11708
(cherry picked from commit 66bae99)
2014-04-24 10:26:08 +02:00
Rossen Stoyanchev 1b59b4eb26 Add Reactor 11 support
This change adds support for Reactor 1.1 in spring-messaging in
addition to Reactor 1.0.1 -- whichever is present on the classpath is
used.

Note also the module name change:
reactor-tcp:1.0.1 -> reactor-net:1.1.0

Issue: SPR-11636
2014-04-23 23:35:49 -04:00
HejiaHo f6b89c2ca9 Fix ConcurrentReferenceHashMap max constraints
Update calculateShift to respect the maximum upper bound as well as the
minimum value.

Issue: SPR-11720

(cherry picked from commit 16410cad)
2014-04-22 15:03:23 +01:00
Sam Brannen 82c32db5a1 Don't mutate annotation metadata when merging attrs
Prior to this commit, invoking the getMergedAnnotationAttributes()
method in AnnotationReadingVisitorUtils resulted in mutation of the
internal state of the ASM-based annotation metadata supplied to the
method.

This commit fixes this issue by making a copy of the original
AnnotationAttributes for the target annotation before merging attribute
values from the meta-annotation hierarchy.

This commit also introduces a slight performance improvement by
avoiding duplicate processing of the attributes of the target
annotation.

Issue: SPR-11710
(cherry picked from commit e1720d89fc)
2014-04-21 12:50:27 -04:00
Juergen Hoeller 52f580149f Polishing 2014-04-17 22:42:33 +02:00
Juergen Hoeller 271fe4f554 Polishing
(cherry picked from commit 48c977a)
2014-04-17 22:14:31 +02:00
Juergen Hoeller 02e8198283 MessageConversionException offers constructor without cause argument now, plus related polishing
Issue: SPR-11653
(cherry picked from commit 2888775)
2014-04-17 22:14:01 +02:00
Juergen Hoeller 090ab4bb6d XStreamMarshaller supports custom NameCoder strategy
Issue: SPR-11702
(cherry picked from commit f5cce14)
2014-04-17 21:39:34 +02:00
Juergen Hoeller 18ef1d4f76 WebSocket intro correctly points to annotations section
Issue: SPR-11667
(cherry picked from commit 53162e7)
2014-04-17 21:39:02 +02:00
Juergen Hoeller d9cb44527c Backported tests for package-visible methods with CGLIB proxies
Issue: SPR-11618
(cherry picked from commit 90309ab)
2014-04-17 21:38:01 +02:00
Juergen Hoeller 8e44521ec4 Latest ASM patches (fix for bug 317151 from ASM HEAD; ASM's 1.8 bytecode processing needs to be lenient with CGLIB 3.1)
Issue: SPR-11212
(cherry picked from commit 637ad20)
2014-04-17 21:34:57 +02:00
Juergen Hoeller d28c6d8bdb Consistent documentation for both 'close' and 'shutdown' as inferred destroy methods
Issue: SPR-11680
(cherry picked from commit 14f9dbf)
2014-04-17 21:32:09 +02:00
Juergen Hoeller c9432ce499 JDBC 3.0 related javadoc overhaul
Issue: SPR-11600
(cherry picked from commit 3fef358)
2014-04-17 21:31:45 +02:00
Stephane Nicoll 2d8e0c8f87 Fix expression cache
Prior to this commit, only the java.lang.reflect.Method was used to
identify an annotated method. As a result, if different annotations
were placed on different methods (method overriding, interface
implementation) only the first one (cached) was used.

LazyParamAwareEvaluationContext was affected by the exact
same problem and has been also fixed.

Issue: SPR-11692
(cherry picked from commit df34bab)
2014-04-15 09:29:56 +02:00
Sam Brannen 03ae8eeb95 Make EOF_STATEMENT_SEPARATOR XML friendly
Changed the value of ScriptUtils.EOF_STATEMENT_SEPARATOR from
"<<< END OF SCRIPT >>>" to "^^^ END OF SCRIPT ^^^" so that the angle
brackets do not have to be escaped in XML configuration files.

Issue: SPR-11687
(cherry picked from commit 1753f5d1ca)
2014-04-11 18:27:59 +02:00
Sam Brannen 9230b38aea Support EOF as statement separator in SQL scripts
Prior to Spring Framework 4.0.3, it was possible to supply a bogus
statement separator (i.e., a separator string that does not exist in
the configured SQL scripts) to ResourceDatabasePopulator with the side
effect that the entire contents of a script file would be interpreted
as a single SQL statement.

This undocumented feature was never intentional; however, some
developers came to rely on it. Unfortunately, changes made in
conjunction with SPR-9531 and SPR-11560 caused such scenarios to no
longer work.

This commit introduces first-class support for executing scripts which
contain a single statement that spans multiple lines but is not
followed by an explicit statement separator.

Specifically, ScriptUtils.EOF_STATEMENT_SEPARATOR may now be specified
as a 'virtual' statement separator to denote that a script contains a
single statement and no actual separator.

Issue: SPR-11687
(cherry picked from commit cc0ae3a881)
2014-04-11 18:25:06 +02:00
Sam Brannen d5ce30f360 Deprecate custom/default CtxLdr class name in TCF
Once the new bootstrap strategy for the TestContext framework (TCF) is
introduced in Spring Framework 4.1, a TestContextBootstrapper will
assume full responsibility for determining what ContextLoader to use as
the default. Consequently, the previous support for supplying the class
name for a custom, default ContextLoader will no longer be applicable.

This commit therefore officially deprecates support for custom, default
ContextLoader class names via the following mechanisms:

 - The TestContextManager(Class, String) constructor

 - The getDefaultContextLoaderClassName(Class) method in
   SpringJUnit4ClassRunner

Issue: SPR-11682
2014-04-10 17:54:14 +02:00
Sam Brannen 428aee5b72 Deprecate getDefTELClasses in TestContextMgr
Since a dedicated bootstrap strategy will be introduced for the
TestContext framework in Spring Framework 4.1, this commit officially
deprecates TestContextManager.getDefaultTestExecutionListenerClasses()
as a forewarning to developers or frameworks that may be using this
obscure feature.

Issue: SPR-11679
2014-04-09 22:20:43 +02:00
Juergen Hoeller f7a17added AbstractMarshaller uses general exception message in extracted buildDocument() method
Issue: SPR-11635
2014-04-09 20:54:41 +02:00
Juergen Hoeller 196f629a20 JBoss "vfszip" resources need to be treated as jar URLs
Issue: SPR-11676
(cherry picked from commit be6b54f)
2014-04-09 20:51:23 +02:00
Juergen Hoeller 7135e729e2 Dropped JCache RC repo (now unused); minor dependency upgrades
Issue: SPR-11640
(cherry picked from commit 9e1631d)
2014-04-09 19:00:44 +02:00
Juergen Hoeller 21874627d2 Polishing
Issue: SPR-11637
(cherry picked from commit 0041e24)
2014-04-09 19:00:23 +02:00
Juergen Hoeller 3ab88b857b AbstractMarshaller pre-implements getDefaultEncoding() method
Issue: SPR-11635
(cherry picked from commit d4b0ae9)
2014-04-09 19:00:08 +02:00
Juergen Hoeller 294545d07a XStreamMarshaller lazily creates fallback XppDriver
Issue: SPR-11635
(cherry picked from commit 8f28a93)
2014-04-09 18:59:47 +02:00
Juergen Hoeller 38cd79047a SelectTag correctly detects multiple="true" again
Issue: SPR-11678
(cherry picked from commit 8d8766d)
2014-04-09 18:59:37 +02:00
Stephane Nicoll 8a779c32d5 Update to JCache 1.0.0 final
Issue: SPR-11640
(cherry picked from commit 0bdece7)
2014-04-08 15:20:57 +02:00
Sam Brannen 7ba31dee45 Use unconstrained quotes in reference manual
Prior to this commit, there were numerous places in the reference
manual, where we see output similar to the following:

    BeanDefinition`s with the `ApplicationContext

This commit addresses this issue by using unconstrained quotes
(e.g., ++XYZ++s) instead of backticks (e.g., `XYZ`s) when the formatted
text is immediately followed by an "s".

This commit also corrects a few typos and corrects natural English
pluralization of Java code elements in the reference manual where
appropriate -- for example, "@Controllers" becomes "@Controller classes,
etc.

Issue: SPR-11650
(cherry picked from commit 0eba1f818f)
2014-04-04 22:05:43 +02:00
Brian Clozel 1c45d7573c Fix @SubscribeMapping MESSAGE response destination
Prior to this commit, @SubscribeMapping mapped methods (backed with
@SendTo* annotations, or not) would send MESSAGEs with the wrong
destination. Instead of using the original SUBSCRIBE destination, it
would use the lookup path computed from the configured prefixes in the
application.

This commit fixes this issue - now @SubscribeMapping MESSAGEs use the
original SUBSCRIBE destination.

Issue: SPR-11648
2014-04-04 12:45:19 +02:00
Juergen Hoeller f014bbb5cf Revised ByteArrayOutputStream handling in MarshallingView and co
Issue: SPR-11646
(cherry picked from commit 8006696)
2014-04-02 21:29:37 +02:00
Juergen Hoeller d1030b798d ResourceHttpRequestHandler explicitly closes a Resource's InputStream
Issue: SPR-11644
(cherry picked from commit 3a96f16)
2014-04-02 21:29:05 +02:00
Juergen Hoeller d628025f13 Polishing
Issue: SPR-11262
2014-04-02 21:28:42 +02:00
Rossen Stoyanchev 30ea1a3475 Fix issue with default executor for message channels
This change ensures correct default settings for message channel's
created through the websocket message-broker XML namespace even
when the channels are customized for other reasons -- e.g. to add
a channel interceptor.

Issue: SPR-11623
2014-04-01 14:16:10 -04:00
Rossen Stoyanchev 7b014eaa55 Improve access to WebSocketSession fields
Ensure the Standard- and the JettyWebSocketSession can return the
Principal and accepted WebSocket sub-protocol even after the
session is closed.

Issue: SPR-11621
2014-04-01 14:16:10 -04:00
Rossen Stoyanchev e21c47d4ce Optimize performance in StompEncoder/Decoder escaping
Issue: SPR-11643
2014-04-01 14:16:10 -04:00
Rossen Stoyanchev 632ae6a4df Improve shutdown responsiveness of SubProtocolWSH
Proactively notify all active WebSocket sessions when a shutdown is
progress. Sessions then can ignore further attempts to send messages
and also stop stop trying to flush messages right away.
2014-04-01 14:16:10 -04:00
Sam Brannen 989f6194b6 Support classes AND locations in @ContextConfiguration
Prior to this commit, the Spring TestContext Framework did not support
the declaration of both 'locations' and 'classes' within
@ContextConfiguration at the same time.

This commit addresses this in the following manner:

 - ContextConfigurationAttributes no longer throws an
   IllegalArgumentException if both 'locations' and 'classes' are
   supplied to its constructor.

 - Concrete SmartContextLoader implementations now validate the
   supplied MergedContextConfiguration before attempting to load the
   ApplicationContext. See validateMergedContextConfiguration().

 - Introduced tests for hybrid context loaders like the one used in
   Spring Boot. See HybridContextLoaderTests.

 - Updated the Testing chapter of the reference manual so that it no
   longer states that locations and classes cannot be used
   simultaneously, mentioning Spring Boot as well.

 - The Javadoc for @ContextConfiguration has been updated accordingly.

 - Added hasLocations(), hasClasses(), and hasResources() convenience
   methods to MergedContextConfiguration.

Issue: SPR-11634
(cherry picked from commit 1f017c4acb)
2014-04-01 19:54:04 +02:00
Sam Brannen 17bf5b991f Update Javadoc for supported JBoss VFS version
(cherry picked from commit 34eb4dba3a)
2014-03-30 16:02:27 +02:00
Sam Brannen cd9d7cfe4f Reinject Servlet mocks between TestNG test methods
Prior to this commit, if multiple test methods were executed in a
subclass of AbstractTestNGSpringContextTests annotated with
@WebAppConfiguration, then injected Servlet API mocks would only
reference the mocks created for the first test method. Subsequent test
methods could therefore never reference the current mocks, and there
was a discrepancy between the state of the injected mocks and the mock
set in the RequestContextHolder.

This commit addresses this issue by ensuring that dependencies
(including updated mocks) are injected into the test instance before
the next test method if the ServletTestExecutionListener resets the
request attributes in RequestContextHolder.

Issue: SPR-11626
(cherry picked from commit c38600762d)
2014-03-29 21:46:58 +01:00
8817 changed files with 302078 additions and 545132 deletions
-10
View File
@@ -1,10 +0,0 @@
root = true
[*.{adoc,bat,groovy,html,java,js,jsp,kt,kts,md,properties,py,rb,sh,sql,svg,txt,xml,xsd}]
charset = utf-8
[*.{groovy,java,kt,kts,xml,xsd}]
indent_style = tab
indent_size = 4
continuation_indent_size = 8
end_of_line = lf
-1
View File
@@ -17,7 +17,6 @@ argfile*
pom.xml
activemq-data/
classes/
/build
buildSrc/build
/spring-*/build
-23
View File
@@ -1,23 +0,0 @@
Juergen Hoeller <jhoeller@pivotal.io> jhoeller <jhoeller@vmware.com>
<jhoeller@pivotal.io> <jhoeller@vmware.com>
<jhoeller@pivotal.io> <jhoeller@gopivotal.com>
<rstoyanchev@pivotal.io> <rstoyanchev@vmware.com>
<rstoyanchev@pivotal.io> <rstoyanchev@gopivotal.com>
<pwebb@pivotal.io> <pwebb@vmware.com>
<pwebb@pivotal.io> <pwebb@gopivotal.com>
<cbeams@pivotal.io> <cbeams@vmware.com>
<cbeams@pivotal.io> <cbeams@gopivotal.com>
<cbeams@pivotal.io> <cbeams@gmail.com>
<apoutsma@pivotal.io> <apoutsma@vmware.com>
<apoutsma@pivotal.io> <apoutsma@gopivotal.com>
<apoutsma@pivotal.io> <poutsma@mac.com>
<ogierke@pivotal.io> <ogierke@vmware.com>
<ogierke@pivotal.io> <ogierke@gopivotal.com>
<dsyer@pivotal.io> <dsyer@vmware.com>
<dsyer@pivotal.io> <dsyer@gopivotal.com>
<dsyer@pivotal.io> <david_syer@hotmail.com>
<aclement@pivotal.io> <aclement@vmware.com>
<aclement@pivotal.io> <aclement@gopivotal.com>
<aclement@pivotal.io> <andrew.clement@gmail.com>
<dmitry.katsubo@gmail.com> <dmitry.katsubo@gmai.com>
Nick Williams <nicholas@nicholaswilliams.net> Nicholas Williams <nicholas@nicholaswilliams.net>
-44
View File
@@ -1,44 +0,0 @@
= Contributor Code of Conduct
As contributors and maintainers of this project, and in the interest of fostering an open
and welcoming community, we pledge to respect all people who contribute through reporting
issues, posting feature requests, updating documentation, submitting pull requests or
patches, and other activities.
We are committed to making participation in this project a harassment-free experience for
everyone, regardless of level of experience, gender, gender identity and expression,
sexual orientation, disability, personal appearance, body size, race, ethnicity, age,
religion, or nationality.
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information, such as physical or electronic addresses,
without explicit permission
* Other unethical or unprofessional conduct
Project maintainers have the right and responsibility to remove, edit, or reject comments,
commits, code, wiki edits, issues, and other contributions that are not aligned to this
Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors
that they deem inappropriate, threatening, offensive, or harmful.
By adopting this Code of Conduct, project maintainers commit themselves to fairly and
consistently applying these principles to every aspect of managing this project. Project
maintainers who do not follow or enforce the Code of Conduct may be permanently removed
from the project team.
This Code of Conduct applies both within project spaces and in public spaces when an
individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
contacting a project maintainer at spring-code-of-conduct@pivotal.io . All complaints will
be reviewed and investigated and will result in a response that is deemed necessary and
appropriate to the circumstances. Maintainers are obligated to maintain confidentiality
with regard to the reporter of an incident.
This Code of Conduct is adapted from the
https://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at
https://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/]
+51
View File
@@ -0,0 +1,51 @@
= How to contribute to the reference
The Spring Framework reference now uses http://asciidoctor.org/[asciidoctor]. This
document describes how to contribute documentation updates.
== Building with Gradle
You can build the documentation using gradle using the `reference` task. For example, from
the project root execute the following command:
./gradlew reference
the output will be available at `spring-framework/build/reference/htmlsingle/index.html`
== Live editing
One of the nice features about using asciidoctor is the support for live editing.
You will find a Guardfile already present at `spring-framework/src/asciidoc/Guardfile`.
Make sure first to follow the setup instructions within the
http://asciidoctor.org/docs/editing-asciidoc-with-live-preview/[Editing AsciiDoc with Live Preview]
document. Once you have done that, there are additional gems to install to make it work
(assuming that you are using http://livereload.com/[LiveReload]):
gem install guard-rspec guard-livereload
When running `guard start` within the `src/asciidoc/` folder, any changes to the
`src/asciidoc/index.adoc` file will automatically be written at
`src/asciidoc/build/index.html`.
== Troubleshooting
* If you are using LiveReload, make sure to select _Allow access to file URLs_ in the
LiveEdit plugin options of your browser.
* The icon used to enable _LiveReload_ can be a bit confusing. The dot is empty when it is
disabled and full when the plugin is active. Make sure to enable it on the tab
displaying the `index.html` file.
* Ensure you are _not_ running guard start at all as two instances could not run at the
same time. To exit a current session in a clean way, just type e in the shell.
== Documentation notes
Some notes on documentation
* Documentation is wrapped at 90 chars, ensure that you manually wrap your edits
* Tabs are used for indentation, do not use spaces
* Follow the existing style when inserting `source` blocks
* http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/[Asciidoctor Quick Reference]
* http://asciidoctor.org/docs/user-manual/[Asciidoctor Manual]
* http://asciidoctor.org/docs/asciidoc-writers-guide/[Asciidoctor Writers Guide]
+271 -92
View File
@@ -1,128 +1,307 @@
# Contributing to the Spring Framework
_Have something you'd like to contribute to the framework? We welcome pull
requests but ask that you carefully read this document first to understand how
best to submit them; what kind of changes are likely to be accepted; and what
to expect from the Spring team when evaluating your submission._
First off, thank you for taking the time to contribute! :+1: :tada:
_Please refer back to this document as a checklist before issuing any pull
request; this will save time for everyone!_
### Table of Contents
## Take Your First Steps
* [Code of Conduct](#code-of-conduct)
* [How to Contribute](#how-to-contribute)
* [Discuss](#discuss)
* [Create a Ticket](#create-a-ticket)
* [Ticket Lifecycle](#ticket-lifecycle)
* [Submit a Pull Request](#submit-a-pull-request)
* [Build from Source](#build-from-source)
* [Source Code Style](#source-code-style)
* [Reference Docs](#reference-docs)
### Understand the basics
### Code of Conduct
Not sure what a pull request is, or how to submit one? Take a look at GitHub's
excellent [help documentation][] first.
This project is governed by the [Spring Code of Conduct](CODE_OF_CONDUCT.adoc).
By participating you are expected to uphold this code.
Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
### How to Contribute
### Search JIRA first; create an issue if necessary
#### Discuss
Is there already an issue that addresses your concern? Do a bit of searching
in our [JIRA issue tracker][] to see if you can find something similar. If you
do not find something similar, please create a new JIRA issue before submitting
a pull request unless the change is truly trivial -- for example: typo fixes,
removing compiler warnings, etc.
If you have a question, check StackOverflow using
[this list of tags](https://spring.io/questions), organized by Spring project.
Find an existing discussion or start a new one if necessary.
### Sign the Contributor License Agreement
If you suspect an issue, perform a search in the
[JIRA issue tracker](https://jira.spring.io/browse/SPR), using a few different keywords.
When you find related issues and discussions, prior or current, it helps you to learn and
it helps us to make a decision.
If you have not previously done so, please fill out and submit the
[SpringSource CLA form][]. You'll receive a token when this process is complete.
Keep track of this; you may be asked for it later!
#### Create a Ticket
Note that emailing/postal mailing a signed copy is _not_ necessary. Submission
of the web form is all that is required.
Reporting an issue or making a feature request is a great way to contribute. Your feedback
and the conversations that result from it provide a continuous flow of ideas.
Once you've completed the web form, simply add the following in a comment on
your pull request:
Before you create a ticket, please take the time to [research first](#discuss).
I have signed and agree to the terms of the SpringSource Individual
Contributor License Agreement.
If creating a ticket after a discussion on StackOverflow, please provide a self-sufficient description in the ticket, independent of the details on StackOverview. We understand this is extra work but the issue tracker is an important place of record for design discussions and decisions that can often be referenced long after the fix version, for example to revisit decisions, to understand the origin of a feature, and so on.
You do not need to include your token/id. Please add the above statement to all
future pull requests as well, simply so that the Spring Framework team knows
immediately that this process is complete.
When ready create a ticket in the [JIRA issue tracker](https://jira.spring.io/browse/SPR).
## Create a Branch
#### Ticket Lifecycle
### Branch from `master`
When an issue is first created, it may not be assigned and will not have a fix version.
Within a day or two, the issue is assigned to a specific committer and the target
version is set to "Waiting for Triage". The committer will then review the issue, ask for
further information if needed, and based on the findings, the issue is either assigned a fix
version or rejected.
Master currently represents work toward Spring Framework 4.0. Please submit
all pull requests there, even bug fixes and minor improvements. Backports to
`3.2.x` will be considered on a case-by-case basis.
When a fix is ready, the issue is marked "Resolved" and may still be re-opened. Once a fix
is released, the issue is permanently "Closed". If necessary, you will need to create a new,
related ticket with a fresh description.
#### Submit a Pull Request
### Use short branch names
You can contribute a source code change by submitting a pull request.
Branches used when submitting pull requests should preferably be named
according to JIRA issues, e.g. 'SPR-1234'. Otherwise, use succinct, lower-case,
dash (-) delimited names, such as 'fix-warnings', 'fix-typo', etc. In
[fork-and-edit][] cases, the GitHub default 'patch-1' is fine as well. This is
important, because branch names show up in the merge commits that result from
accepting pull requests and should be as expressive and concise as possible.
1. If you have not previously done so, please sign the
[Contributor License Agreement](https://cla.pivotal.io/sign/spring). You will also be reminded
automatically when you submit a pull request.
## Use Spring Framework Code Style
1. For all but the most trivial of contributions, please [create a ticket](#create-a-ticket).
The purpose of the ticket is to understand and discuss the underlying issue or feature.
We use the JIRA issue tracker as the preferred place of record for conversations and
conclusions. In that sense discussions directly under a PR are more implementation detail
oriented and transient in nature.
The complete [Spring Framework Code Style][] reference is available on the wiki, but
here's a quick summary:
1. Always check out the `master` branch and submit pull requests against it
(for target version see [settings.gradle](settings.gradle)).
Backports to prior versions will be considered on a case-by-case basis and reflected as
the fix version in the issue tracker.
### Mind the whitespace
1. Use short branch names, preferably based on the JIRA issue (e.g. `SPR-1234`), or
otherwise using succinct, lower-case, dash (-) delimited names, such as `fix-warnings'.
Please carefully follow the whitespace and formatting conventions already
present in the framework.
1. Choose the granularity of your commits consciously and squash commits that represent
multiple edits or corrections of the same logical change. See
[Rewriting History section of Pro Git](https://git-scm.com/book/en/Git-Tools-Rewriting-History)
for an overview of streamlining commit history.
1. Tabs, not spaces
1. Unix (LF), not DOS (CRLF) line endings
1. Eliminate all trailing whitespace
1. Wrap Javadoc at 90 characters
1. Aim to wrap code at 90 characters, but favor readability over wrapping
1. Preserve existing formatting; i.e. do not reformat code for its own sake
1. Search the codebase using `git grep` and other tools to discover common
naming conventions, etc.
1. Latin-1 (ISO-8859-1) encoding for Java sources; use `native2ascii` to convert
if necessary
1. Format commit messages using 55 characters for the subject line, 72 lines for the
description, followed by related issues, e.g. `Issues: SPR-1234, SPR-1235`.
See the
[Commit Guidelines section of Pro Git](https://git-scm.com/book/en/Distributed-Git-Contributing-to-a-Project#Commit-Guidelines)
for best practices around commit messages and use `git log` to see some examples.
1. List the JIRA issue number in the PR description.
### Add Apache license header to all new classes
If accepted, your contribution may be heavily modified as needed prior to merging.
You will likely retain author attribution for your Git commits granted that the bulk of
your changes remain intact. You may also be asked to rework the submission.
```java
/*
* Copyright 2002-2014 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.
*/
If asked to make corrections, simply push the changes against the same branch, and your
pull request will be updated. In other words, you do not need to create a new pull request
when asked to make changes.
package ...;
```
### Build from Source
### Update Apache license header in modified files as necessary
See the [Build from Source](https://github.com/spring-projects/spring-framework/wiki/Build-from-Source)
wiki page for instructions on how to check out, build, and import the Spring Framework
source code into your IDE.
Always check the date range in the license header. For example, if you've
modified a file in 2014 whose header still reads:
### Source Code Style
```java
* Copyright 2002-2011 the original author or authors.
```
The wiki pages
[Code Style](https://github.com/spring-projects/spring-framework/wiki/Code-Style) and
[IntelliJ IDEA Editor Settings](https://github.com/spring-projects/spring-framework/wiki/IntelliJ-IDEA-Editor-Settings)
defines the source file coding standards we use along with some IDEA editor settings we customize.
Then be sure to update it to 2014 accordingly:
### Reference Docs
```java
* Copyright 2002-2014 the original author or authors.
```
The reference documentation is in the [src/docs/asciidoc](src/docs/asciidoc) directory and, in
[Asciidoctor](https://asciidoctor.org/) format. For trivial changes, you may be able to browse,
edit source files, and submit directly from Github.
### Use @since tags for newly-added public API types and methods
When making changes locally, use `./gradlew asciidoctor` and then browse the result under
`build/asciidoc/html5/index.html`.
For example:
Asciidoctor also supports live editing. For more details read
[Editing AsciiDoc with Live Preview](https://asciidoctor.org/docs/editing-asciidoc-with-live-preview/).
Note that if you choose the
[System Monitor](https://asciidoctor.org/docs/editing-asciidoc-with-live-preview/#using-a-system-monitor)
option, you can find a Guardfile under `src/docs/asciidoc`.
```java
/**
* ...
*
* @author First Last
* @since 4.0
* @see ...
*/
```
## Prepare Your Commit
### Submit JUnit test cases for all behavior changes
Search the codebase to find related tests and add additional `@Test` methods
as appropriate. It is also acceptable to submit test cases on a per JIRA issue
basis, for example:
```java
package org.springframework.beans.factory.support;
/**
* Unit tests for SPR-8954, in which a custom {@link InstantiationAwareBeanPostProcessor}
* forces the predicted type of a FactoryBean, effectively preventing retrieval of the
* bean from calls to #getBeansOfType(FactoryBean.class). The implementation of
* {@link AbstractBeanFactory#isFactoryBean(String, RootBeanDefinition)} now ensures
* that not only the predicted bean type is considered, but also the original bean
* definition's beanClass.
*
* @author Chris Beams
*/
public class Spr8954Tests {
@Test
public void cornerSpr8954() {
// ...
}
}
```
### Squash commits
Use `git rebase --interactive --autosquash`, `git add --patch`, and other tools
to "squash" multiple commits into a single atomic commit. In addition to the man
pages for git, there are many resources online to help you understand how these
tools work. The [Rewriting History section of Pro Git][] provides a good overview.
### Use real name in git commits
Please configure git to use your real first and last name for any commits you
intend to submit as pull requests. For example, this is not acceptable:
Author: Nickname <user@mail.com>
Rather, please include your first and last name, properly capitalized, as
submitted against the SpringSource contributor license agreement:
Author: First Last <user@mail.com>
This helps ensure traceability against the CLA and also goes a long way to
ensuring useful output from tools like `git shortlog` and others.
You can configure this via the account admin area in GitHub (useful for
fork-and-edit cases); _globally_ on your machine with
git config --global user.name "First Last"
git config --global user.email user@mail.com
or _locally_ for the `spring-framework` repository only by omitting the
'--global' flag:
cd spring-framework
git config user.name "First Last"
git config user.email user@mail.com
### Format commit messages
Please read and follow the [Commit Guidelines section of Pro Git][].
Most importantly, please format your commit messages in the following way
(adapted from the commit template in the link above):
Short (50 chars or less) summary of changes
More detailed explanatory text, if necessary. Wrap it to about 72
characters or so. In some contexts, the first line is treated as the
subject of an email and the rest of the text as the body. The blank
line separating the summary from the body is critical (unless you omit
the body entirely); tools like rebase can get confused if you run the
two together.
Further paragraphs come after blank lines.
- Bullet points are okay, too
- Typically a hyphen or asterisk is used for the bullet, preceded by a
single space, with blank lines in between, but conventions vary here
Issue: SPR-1234, SPR-1235
1. Use imperative statements in the subject line, e.g. "Fix broken Javadoc link"
1. Begin the subject line with a capitalized verb, e.g. "Add, Prune, Fix,
Introduce, Avoid, etc."
1. Do not end the subject line with a period
1. Restrict the subject line to 50 characters or less if possible
1. Wrap lines in the body at 72 characters or less
1. Mention associated JIRA issue(s) at the end of the commit comment, prefixed
with "Issue: " as above
1. In the body of the commit message, explain how things worked before this
commit, what has changed, and how things work now
For examples of this style, issue a `git log --author=cbeams` in the
`spring-framework` git repository. For convenience, here are several such commits:
- https://github.com/spring-projects/spring-framework/commit/08e2669b84ec0faa2f7904441fe39ac70b65b078
- https://github.com/spring-projects/spring-framework/commit/1d9d3e6ff79ce9f0eca03b02cd1df705925575da
- https://github.com/spring-projects/spring-framework/commit/8e0b1c3a5f957af3049cfa0438317177e16d6de6
- https://github.com/spring-projects/spring-framework/commit/b787a68f2050df179f7036b209aa741230a02477
## Run the Final Checklist
### Run all tests prior to submission
See the [building from source][] section of the `README` for instructions. Make
sure that all tests pass prior to submitting your pull request.
### Submit your pull request
Subject line:
Follow the same conventions for pull request subject lines as mentioned above
for commit message subject lines.
In the body:
1. Explain your use case. What led you to submit this change? Why were existing
mechanisms in the framework insufficient? Make a case that this is a
general-purpose problem and that yours is a general-purpose solution, etc.
1. Add any additional information and ask questions; start a conversation or
continue one from JIRA
1. Mention the JIRA issue ID
1. Also mention that you have submitted the CLA as described above
Note that for pull requests containing a single commit, GitHub will default the
subject line and body of the pull request to match the subject line and body of
the commit message. This is fine, but please also include the items above in the
body of the request.
### Mention your pull request on the associated JIRA issue
Add a comment to the associated JIRA issue(s) linking to your new pull request.
### Expect discussion and rework
The Spring team takes a very conservative approach to accepting contributions to
the framework. This is to keep code quality and stability as high as possible,
and to keep complexity at a minimum. Your changes, if accepted, may be heavily
modified prior to merging. You will retain "Author:" attribution for your Git
commits granted that the bulk of your changes remain intact. You may be asked to
rework the submission for style (as explained above) and/or substance. Again, we
strongly recommend discussing any serious submissions with the Spring Framework
team _prior_ to engaging in serious development work.
Note that you can always force push (`git push -f`) reworked / rebased commits
against the branch used to submit your pull request. In other words, you do not
need to issue a new pull request when asked to make changes.
[help documentation]: http://help.github.com/send-pull-requests
[JIRA issue tracker]: https://jira.spring.io/browse/SPR
[spring-framework-contrib]: https://groups.google.com/forum/#!forum/spring-framework-contrib
[SpringSource CLA form]: https://support.springsource.com/spring_committer_signup
[fork-and-edit]: https://github.com/blog/844-forking-with-the-edit-button
[Spring Framework Code Style]: https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Code-Style
[Rewriting History section of Pro Git]: http://git-scm.com/book/en/Git-Tools-Rewriting-History
[Commit Guidelines section of Pro Git]: http://git-scm.com/book/en/Distributed-Git-Contributing-to-a-Project#Commit-Guidelines
[building from source]: https://github.com/spring-projects/spring-framework#building-from-source
+89 -36
View File
@@ -1,48 +1,101 @@
# <img src="src/docs/asciidoc/images/spring-framework.png" width="80" height="80"> Spring Framework
## Spring Framework
The Spring Framework provides a comprehensive programming and configuration
model for modern Java-based enterprise applications - on any kind of deployment
platform. A key element of Spring is infrastructural support at the application
level: Spring focuses on the "plumbing" of enterprise applications so that teams
can focus on application-level business logic, without unnecessary ties to
specific deployment environments.
This is the home of the Spring Framework, the foundation for all
[Spring projects](https://spring.io/projects). Together the Spring Framework and the family of Spring projects make up what we call "Spring".
The framework also serves as the foundation for [Spring Integration][], [Spring
Batch][] and the rest of the Spring [family of projects][]. Browse the repositories
under the [Spring organization][] on GitHub for a full list.
Spring provides everything you need beyond the Java language to create enterprise
applications in a wide range of scenarios and architectures. Please read the
[Overview](https://docs.spring.io/spring/docs/current/spring-framework-reference/overview.html#spring-introduction)
section in the reference for a more complete introduction.
## Code of Conduct
This project is governed by the [Spring Code of Conduct](CODE_OF_CONDUCT.adoc).
By participating you are expected to uphold this code.
Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
## Access to Binaries
For access to artifacts or a distribution zip, see the
[Spring Framework Artifacts](https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Artifacts)
wiki page.
## Downloading Artifacts
See [downloading Spring artifacts][] for Maven repository information. Unable to
use Maven or other transitive dependency management tools? See [building a
distribution with dependencies][].
## Documentation
See the current [Javadoc][] and [reference docs][].
The Spring Frameworks maintains reference documentation
([published](https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/) and
[source](src/docs/asciidoc)),
Github [wiki pages](https://github.com/spring-projects/spring-framework/wiki), and an
[API reference](https://docs.spring.io/spring-framework/docs/current/javadoc-api/).
There are also [guides and tutorials](https://spring.io/guides) across Spring projects.
## Getting Support
Check out the [Spring forums][] and the [spring][spring tag] and
[spring-mvc][spring-mvc tag] tags on [Stack Overflow][]. [Commercial support][]
is available too.
## Build from Source
## Issue Tracking
Report issues via the [Spring Framework JIRA]. Understand our issue management
process by reading about [the lifecycle of an issue][]. Think you've found a
bug? Please consider submitting a reproduction project via the
[spring-framework-issues][] GitHub repository. The [readme][] there provides
simple step-by-step instructions.
See the [Build from Source](https://github.com/spring-projects/spring-framework/wiki/Build-from-Source)
wiki page and also [CONTRIBUTING.md](CONTRIBUTING.md).
## Building from Source
The Spring Framework uses a [Gradle][]-based build system. In the instructions
below, [`./gradlew`][] is invoked from the root of the source tree and serves as
a cross-platform, self-contained bootstrap mechanism for the build.
## Stay in Touch
### Prerequisites
Follow [@SpringCentral](https://twitter.com/springcentral),
[@SpringFramework](https://twitter.com/springframework), and its
[team members](https://twitter.com/springframework/lists/team/members) on Twitter.
In-depth articles can be found at [The Spring Blog](https://spring.io/blog/),
and releases are announced via our [news feed](https://spring.io/blog/category/news).
[Git][] and [OpenJDK 8 early access build 100 or later][JDK8 build]
Be sure that your `JAVA_HOME` environment variable points to the `jdk1.8.0` folder
extracted from the JDK download.
### Check out sources
`git clone git@github.com:spring-projects/spring-framework.git`
### Import sources into your IDE
Run `./import-into-eclipse.sh` or read `import-into-idea.md` as appropriate.
> **Note:** Per the prerequisites above, ensure that you have JDK 8 configured properly in your IDE.
### Install all spring-\* jars into your local Maven cache
`./gradlew install`
### Compile and test; build all jars, distribution zips, and docs
`./gradlew build`
... and discover more commands with `./gradlew tasks`. See also the [Gradle
build and release FAQ][].
## Contributing
[Pull requests][] are welcome; see the [contributor guidelines][] for details.
## Staying in Touch
Follow [@SpringCentral][] as well as [@SpringFramework][] and its [team members][]
on Twitter. In-depth articles can be found at [The Spring Blog][], and releases
are announced via our [news feed][].
## License
The Spring Framework is released under version 2.0 of the [Apache License][].
The Spring Framework is released under version 2.0 of the
[Apache License](https://www.apache.org/licenses/LICENSE-2.0).
[Spring Integration]: https://github.com/spring-projects/spring-integration
[Spring Batch]: https://github.com/spring-projects/spring-batch
[family of projects]: http://spring.io/projects
[Spring organization]: https://github.com/spring-projects
[downloading Spring artifacts]: https://github.com/spring-projects/spring-framework/wiki/Downloading-Spring-artifacts
[building a distribution with dependencies]: https://github.com/spring-projects/spring-framework/wiki/Building-a-distribution-with-dependencies
[Javadoc]: http://docs.spring.io/spring-framework/docs/current/javadoc-api/
[reference docs]: http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/
[Spring forums]: http://forum.spring.io/
[spring tag]: http://stackoverflow.com/questions/tagged/spring
[spring-mvc tag]: http://stackoverflow.com/questions/tagged/spring-mvc
[Stack Overflow]: http://stackoverflow.com/faq
[Commercial support]: http://spring.io/services
[Spring Framework JIRA]: https://jira.spring.io/browse/SPR
[the lifecycle of an issue]: https://github.com/spring-projects/spring-framework/wiki/The-Lifecycle-of-an-Issue
[spring-framework-issues]: https://github.com/spring-projects/spring-framework-issues#readme
[readme]: https://github.com/spring-projects/spring-framework-issues#readme
[Gradle]: http://gradle.org
[`./gradlew`]: http://vimeo.com/34436402
[Git]: http://help.github.com/set-up-git-redirect
[JDK8 build]: http://jdk8.java.net/download.html
[Gradle build and release FAQ]: https://github.com/spring-projects/spring-framework/wiki/Gradle-build-and-release-FAQ
[Pull requests]: http://help.github.com/send-pull-requests
[contributor guidelines]: https://github.com/spring-projects/spring-framework/blob/master/CONTRIBUTING.md
[@SpringFramework]: https://twitter.com/springframework
[@SpringCentral]: https://twitter.com/springcentral
[team members]: https://twitter.com/springframework/team/members
[The Spring Blog]: http://spring.io/blog/
[news feed]: http://spring.io/blog/category/news
[Apache License]: http://www.apache.org/licenses/LICENSE-2.0
+1074 -170
View File
File diff suppressed because it is too large Load Diff
-10
View File
@@ -1,10 +0,0 @@
description = "Exposes gradle buildSrc for IDE support"
apply plugin: "groovy"
dependencies {
compile gradleApi()
compile localGroovy()
}
configurations.archives.artifacts.clear()
@@ -0,0 +1,158 @@
/*
* Copyright 2002-2013 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.build.gradle
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.TaskAction
/**
* Gradle plugin that detects identically named, non-empty packages split across multiple
* subprojects, e.g. "org.springframework.context.annotation" existing in both spring-core
* and spring-aspects. Adds a 'detectSplitPackages' task to the current project's task
* collection. If the project already contains a 'check' task (i.e. is a typical Gradle
* project with the "java" plugin applied), the 'check' task will be updated to depend on
* the execution of 'detectSplitPackages'.
*
* By default, all subprojects will be scanned. Use the 'projectsToScan' task property to
* modify this value. Example usage:
*
* apply plugin: 'detect-split-packages // typically applied to root project
*
* detectSplitPackages {
* packagesToScan -= project(":spring-xyz") // scan every project but spring-xyz
* }
*
* @author Rob Winch
* @author Glyn Normington
* @author Chris Beams
*/
public class DetectSplitPackagesPlugin implements Plugin<Project> {
public void apply(Project project) {
def tasks = project.tasks
Task detectSplitPackages = tasks.create("detectSplitPackages", DetectSplitPackagesTask.class)
if (tasks.asMap.containsKey("check")) {
tasks.getByName("check").dependsOn detectSplitPackages
}
}
}
public class DetectSplitPackagesTask extends DefaultTask {
private static final String JAVA_FILE_SUFFIX = ".java"
private static final String PACKAGE_SEPARATOR = "."
private static final String HIDDEN_DIRECTORY_PREFIX = "."
@Input
Set<Project> projectsToScan = project.subprojects
public DetectSplitPackagesTask() {
this.group = "Verification"
this.description = "Detects packages split across two or more subprojects."
}
@TaskAction
public void detectSplitPackages() {
def splitPackages = doDetectSplitPackages()
if (!splitPackages.isEmpty()) {
def message = "The following split package(s) have been detected:\n"
splitPackages.each { pkg, mod ->
message += " - ${pkg} (split across ${mod[0].name} and ${mod[1].name})\n"
}
throw new GradleException(message)
}
}
private Map<String, List<Project>> doDetectSplitPackages() {
def splitPackages = [:]
def mergedProjects = findMergedProjects()
def packagesByProject = mapPackagesByProject()
def projects = packagesByProject.keySet().toArray()
def nProjects = projects.length
for (int i = 0; i < nProjects - 1; i++) {
for (int j = i + 1; j < nProjects - 1; j++) {
def prj_i = projects[i]
def prj_j = projects[j]
def pkgs_i = new HashSet(packagesByProject.get(prj_i))
def pkgs_j = packagesByProject.get(prj_j)
pkgs_i.retainAll(pkgs_j)
if (!pkgs_i.isEmpty()
&& mergedProjects.get(prj_i) != prj_j
&& mergedProjects.get(prj_j) != prj_i) {
pkgs_i.each { pkg ->
def readablePkg = pkg.substring(1).replaceAll(File.separator, PACKAGE_SEPARATOR)
splitPackages[readablePkg] = [prj_i, prj_j]
}
}
}
}
return splitPackages;
}
private Map<Project, Set<String>> mapPackagesByProject() {
def packagesByProject = [:]
this.projectsToScan.each { Project p ->
def packages = new HashSet<String>()
p.sourceSets.main.java.srcDirs.each { File dir ->
findPackages(packages, dir, "")
}
if (!packages.isEmpty()) {
packagesByProject.put(p, packages)
}
}
return packagesByProject;
}
private Map<Project, Project> findMergedProjects() {
def mergedProjects = [:]
this.projectsToScan.findAll { p ->
p.plugins.findPlugin(MergePlugin)
}.findAll { p ->
p.merge.into
}.each { p ->
mergedProjects.put(p, p.merge.into)
}
return mergedProjects
}
private static void findPackages(Set<String> packages, File dir, String packagePath) {
def scanDir = new File(dir, packagePath)
def File[] javaFiles = scanDir.listFiles({ file ->
!file.isDirectory() && file.name.endsWith(JAVA_FILE_SUFFIX)
} as FileFilter)
if (javaFiles != null && javaFiles.length != 0) {
packages.add(packagePath)
}
scanDir.listFiles({ File file ->
file.isDirectory() && !file.name.startsWith(HIDDEN_DIRECTORY_PREFIX)
} as FileFilter).each { File subDir ->
findPackages(packages, dir, packagePath + File.separator + subDir.name)
}
}
}
@@ -0,0 +1,157 @@
/*
* Copyright 2002-2013 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.build.gradle
import org.gradle.api.*
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ProjectDependency;
import org.gradle.api.artifacts.maven.Conf2ScopeMapping
import org.gradle.api.plugins.MavenPlugin
import org.gradle.plugins.ide.eclipse.EclipsePlugin
import org.gradle.plugins.ide.idea.IdeaPlugin
import org.gradle.api.invocation.*
/**
* Gradle plugin that allows projects to merged together. Primarily developed to
* allow Spring to support multiple incompatible versions of third-party
* dependencies (for example Hibernate v3 and v4).
* <p>
* The 'merge' extension should be used to define how projects are merged, for example:
* <pre class="code">
* configure(subprojects) {
* apply plugin: MergePlugin
* }
*
* project("myproject") {
* }
*
* project("myproject-extra") {
* merge.into = project("myproject")
* }
* </pre>
* <p>
* This plugin adds two new configurations:
* <ul>
* <li>merging - Contains the projects being merged into this project<li>
* <li>runtimeMerge - Contains all dependencies that are merge projects. These are used
* to allow an IDE to reference merge projects.</li>
* <ul>
*
* @author Rob Winch
* @author Phillip Webb
*/
class MergePlugin implements Plugin<Project> {
private static boolean attachedProjectsEvaluated;
public void apply(Project project) {
project.plugins.apply(MavenPlugin)
project.plugins.apply(EclipsePlugin)
project.plugins.apply(IdeaPlugin)
MergeModel model = project.extensions.create("merge", MergeModel)
project.configurations.create("merging")
Configuration runtimeMerge = project.configurations.create("runtimeMerge")
// Ensure the IDE can reference merged projects
project.eclipse.classpath.plusConfigurations += [runtimeMerge]
project.idea.module.scopes.PROVIDED.plus += runtimeMerge
// Hook to perform the actual merge logic
project.afterEvaluate{
if (it.merge.into != null) {
setup(it)
}
}
// Hook to build runtimeMerge dependencies
if (!attachedProjectsEvaluated) {
project.gradle.projectsEvaluated{
postProcessProjects(it)
}
attachedProjectsEvaluated = true;
}
}
private void setup(Project project) {
project.merge.into.dependencies.add("merging", project)
project.dependencies.add("provided", project.merge.into.sourceSets.main.output)
project.dependencies.add("runtimeMerge", project.merge.into)
setupTaskDependencies(project)
setupMaven(project)
}
private void setupTaskDependencies(Project project) {
// invoking a task will invoke the task with the same name on 'into' project
["sourcesJar", "jar", "javadocJar", "javadoc", "install", "artifactoryPublish"].each {
def task = project.tasks.findByPath(it)
if (task) {
task.enabled = false
task.dependsOn(project.merge.into.tasks.findByPath(it))
}
}
// update 'into' project artifacts to contain the source artifact contents
project.merge.into.sourcesJar.from(project.sourcesJar.source)
project.merge.into.jar.from(project.sourceSets.main.output)
project.merge.into.javadoc {
source += project.javadoc.source
classpath += project.javadoc.classpath
}
}
private void setupMaven(Project project) {
project.configurations.each { configuration ->
Conf2ScopeMapping mapping = project.conf2ScopeMappings.getMapping([configuration])
if (mapping.scope) {
Configuration intoConfiguration = project.merge.into.configurations.create(
project.name + "-" + configuration.name)
configuration.excludeRules.each {
configuration.exclude([
(ExcludeRule.GROUP_KEY) : it.group,
(ExcludeRule.MODULE_KEY) : it.module])
}
configuration.dependencies.each {
def intoCompile = project.merge.into.configurations.getByName("compile")
// Protect against changing a compile scope dependency (SPR-10218)
if (!intoCompile.dependencies.contains(it)) {
intoConfiguration.dependencies.add(it)
}
}
project.merge.into.install.repositories.mavenInstaller.pom.scopeMappings.addMapping(
mapping.priority + 100, intoConfiguration, mapping.scope)
}
}
}
private postProcessProjects(Gradle gradle) {
gradle.allprojects(new Action<Project>() {
public void execute(Project project) {
project.configurations.getByName("runtime").allDependencies.withType(ProjectDependency).each{
Configuration dependsOnMergedFrom = it.dependencyProject.configurations.getByName("merging");
dependsOnMergedFrom.dependencies.each{ dep ->
project.dependencies.add("runtimeMerge", dep.dependencyProject)
}
}
}
});
}
}
class MergeModel {
Project into;
}
@@ -0,0 +1 @@
implementation-class=org.springframework.build.gradle.DetectSplitPackagesPlugin
@@ -0,0 +1 @@
implementation-class=org.springframework.build.gradle.MergePlugin
+1 -1
View File
@@ -1 +1 @@
version=5.0.21.BUILD-SNAPSHOT
version=4.0.10.BUILD-SNAPSHOT
-239
View File
@@ -1,239 +0,0 @@
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.
*/
task api(type: Javadoc) {
group = "Documentation"
description = "Generates aggregated Javadoc API documentation."
title = "${rootProject.description} ${version} API"
dependsOn {
subprojects.collect {
it.tasks.getByName("jar")
}
}
options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PROTECTED
options.author = true
options.header = rootProject.description
options.use = true
options.overview = "src/docs/api/overview.html"
options.stylesheetFile = file("src/docs/api/stylesheet.css")
options.splitIndex = true
options.links(project.ext.javadocLinks)
options.addStringOption('Xdoclint:none', '-quiet')
source subprojects.collect { project ->
project.sourceSets.main.allJava
}
maxMemory = "1024m"
destinationDir = new File(buildDir, "api")
doFirst {
classpath = files(
// ensure the javadoc process can resolve types compiled from .aj sources
project(":spring-aspects").sourceSets.main.output
)
classpath += files(subprojects.collect { it.sourceSets.main.compileClasspath })
}
}
dokka {
dependsOn {
tasks.getByName("api")
}
doFirst {
classpath = subprojects.collect { project -> project.jar.outputs.files.getFiles() }.flatten()
classpath += files(subprojects.collect { it.sourceSets.main.compileClasspath })
}
moduleName = "spring-framework"
outputFormat = "html"
outputDirectory = "$buildDir/docs/kdoc"
sourceDirs = files(subprojects.collect { project ->
def kotlinDirs = project.sourceSets.main.kotlin.srcDirs.collect()
kotlinDirs -= project.sourceSets.main.java.srcDirs
})
externalDocumentationLink {
url = new URL("https://docs.spring.io/spring-framework/docs/$version/javadoc-api/")
packageListUrl = new File(buildDir, "api/package-list").toURI().toURL()
}
externalDocumentationLink {
url = new URL("https://projectreactor.io/docs/core/release/api/")
}
externalDocumentationLink {
url = new URL("https://www.reactive-streams.org/reactive-streams-1.0.1-javadoc/")
}
}
asciidoctor {
sources {
include '*.adoc'
}
resources {
from(sourceDir) {
include 'images/*', 'stylesheets/*', 'tocbot-3.0.2/*'
}
}
logDocuments = true
backends = ["html5"]
// only ouput PDF documentation for non-SNAPSHOT builds
if(!project.getVersion().toString().contains("BUILD-SNAPSHOT")) {
backends += "pdf"
}
options doctype: 'book', eruby: 'erubis'
attributes 'icons': 'font',
'idprefix': '',
'idseparator': '-',
docinfo: '',
revnumber: project.version,
sectanchors: '',
sectnums: '',
'source-highlighter': 'coderay@', // TODO switch to 'rouge' once supported by the html5 backend
stylesdir: 'stylesheets/',
stylesheet: 'main.css',
'spring-version': project.version
}
task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor', 'dokka']) {
group = "Distribution"
baseName = "spring-framework"
classifier = "docs"
description = "Builds -${classifier} archive containing api and reference " +
"for deployment at https://docs.spring.io/spring-framework/docs."
from("src/dist") {
include "changelog.txt"
}
from (api) {
into "javadoc-api"
}
from ("$asciidoctor.outputDir/html5") {
into "spring-framework-reference"
}
from ("$asciidoctor.outputDir/pdf") {
into "spring-framework-reference/pdf"
}
from (dokka) {
into "kdoc-api"
}
}
task schemaZip(type: Zip) {
group = "Distribution"
baseName = "spring-framework"
classifier = "schema"
description = "Builds -${classifier} archive containing all " +
"XSDs for deployment at https://springframework.org/schema."
duplicatesStrategy 'exclude'
moduleProjects.each { subproject ->
def Properties schemas = new Properties();
subproject.sourceSets.main.resources.find {
(it.path.endsWith("META-INF/spring.schemas") || it.path.endsWith("META-INF\\spring.schemas"))
}?.withInputStream { schemas.load(it) }
for (def key : schemas.keySet()) {
def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
assert shortName != key
File xsdFile = subproject.sourceSets.main.resources.find {
(it.path.endsWith(schemas.get(key)) || it.path.endsWith(schemas.get(key).replaceAll('\\/','\\\\')))
}
assert xsdFile != null
into (shortName) {
from xsdFile.path
}
}
}
}
task distZip(type: Zip, dependsOn: [docsZip, schemaZip]) {
group = "Distribution"
baseName = "spring-framework"
classifier = "dist"
description = "Builds -${classifier} archive, containing all jars and docs, " +
"suitable for community download page."
ext.baseDir = "${baseName}-${project.version}";
from("src/docs/dist") {
include "readme.txt"
include "license.txt"
include "notice.txt"
into "${baseDir}"
expand(copyright: new Date().format("yyyy"), version: project.version)
}
from(zipTree(docsZip.archivePath)) {
into "${baseDir}/docs"
}
from(zipTree(schemaZip.archivePath)) {
into "${baseDir}/schema"
}
moduleProjects.each { subproject ->
into ("${baseDir}/libs") {
from subproject.jar
if (subproject.tasks.findByPath("sourcesJar")) {
from subproject.sourcesJar
}
if (subproject.tasks.findByPath("javadocJar")) {
from subproject.javadocJar
}
}
}
}
distZip.mustRunAfter subprojects.test
// Create a distribution that contains all dependencies (required and optional).
// Not published by default; only for use when building from source.
task depsZip(type: Zip, dependsOn: distZip) { zipTask ->
group = "Distribution"
baseName = "spring-framework"
classifier = "dist-with-deps"
description = "Builds -${classifier} archive, containing everything " +
"in the -${distZip.classifier} archive plus all runtime dependencies."
from zipTree(distZip.archivePath)
gradle.taskGraph.whenReady { taskGraph ->
if (taskGraph.hasTask(":${zipTask.name}")) {
def projectNames = rootProject.subprojects*.name
def artifacts = new HashSet()
subprojects.each { subproject ->
(subproject.configurations.runtime.resolvedConfiguration.resolvedArtifacts +
subproject.configurations.optional.resolvedConfiguration.resolvedArtifacts).each { artifact ->
def dependency = artifact.moduleVersion.id
if (!projectNames.contains(dependency.name)) {
artifacts << artifact.file
}
}
}
zipTask.from(artifacts) {
into "${distZip.baseDir}/deps"
}
}
}
}
+10 -8
View File
@@ -5,23 +5,23 @@ import org.gradle.plugins.ide.eclipse.model.SourceFolder
apply plugin: "propdeps-eclipse"
apply plugin: "propdeps-idea"
// Until eclipse fully supports Java 8 use 1.7 source level
eclipse.jdt {
sourceCompatibility = 1.8
targetCompatibility = 1.8
sourceCompatibility = 1.7
targetCompatibility = 1.7
}
// Replace classpath entries with project dependencies (GRADLE-1116)
// https://issues.gradle.org/browse/GRADLE-1116
eclipse.classpath.file.whenMerged { classpath ->
def regexp = /.*?\/([^\/]+)\/build\/([^\/]+\/)+(?:main|test)/ // only match those that end in main or test (avoids removing necessary entries like build/classes/jaxb)
def regexp = /.*?\/([^\/]+)\/build\/[^\/]+\/(?:main|test)/ // only match those that end in main or test (avoids removing necessary entries like build/classes/jaxb)
def projectOutputDependencies = classpath.entries.findAll { entry -> entry.path =~ regexp }
projectOutputDependencies.each { entry ->
def matcher = (entry.path =~ regexp)
if (matcher) {
if(matcher) {
def projectName = matcher[0][1]
def path = "/${projectName}"
if(!classpath.entries.find { e -> e instanceof ProjectDependency && e.path == path }) {
def dependency = new ProjectDependency(path)
def dependency = new ProjectDependency(path, project(":${projectName}").path)
dependency.exported = true
classpath.entries.add(dependency)
}
@@ -58,9 +58,10 @@ eclipse.classpath.file.whenMerged { classpath ->
}
}
// Allow projects to be used as WTP modules
// Allow projects to be used as WPT modules
eclipse.project.natures "org.eclipse.wst.common.project.facet.core.nature"
// Include project specific settings
task eclipseSettings(type: Copy) {
from rootProject.files(
@@ -85,8 +86,8 @@ task eclipseJdtPrepare(type: Copy) {
}
task cleanEclipseJdtUi(type: Delete) {
delete project.file(".settings/org.eclipse.jdt.core.prefs")
delete project.file(".settings/org.eclipse.jdt.ui.prefs")
delete project.file("org.eclipse.jdt.core.prefs")
delete project.file(".settings/org.eclipse.wst.common.component")
delete project.file(".settings/org.eclipse.wst.common.project.facet.core.xml")
}
@@ -97,6 +98,7 @@ tasks["eclipse"].dependsOn(eclipseSettings, eclipseWstComponent)
// Filter 'build' folder
eclipse.project.file.withXml {
def node = it.asNode()
-1
View File
@@ -43,7 +43,6 @@ task jdiff {
ant.mkdir(dir: outputDir)
ant.jdiff(
destdir: outputDir,
source: "1.8",
verbose: "off",
stats: "on",
docchanges: "off") {
+3 -3
View File
@@ -11,7 +11,7 @@ difference between two public Java APIs.
The file jdiff.html contains the reference page for JDiff. The latest
version of JDiff can be downloaded at:
https://sourceforge.net/projects/javadiff
http://sourceforge.net/projects/javadiff
To use the Ant task on your own project, see example.xml. More examples
of using JDiff to compare the public APIs of J2SE1.3 and J2SE1.4 can
@@ -40,7 +40,7 @@ Acknowledgements
JDiff uses Stuart D. Gathman's Java translation of Gene Myers' O(ND)
difference algorithm.
JDiff uses Xerces 1.4.2 from https://www.apache.org.
JDiff uses Xerces 1.4.2 from http://www.apache.org.
JDiff also includes a script to use the classdoc application from
http://classdoc.sourceforge.net or http://www.jensgulden.de, by Jens
@@ -56,4 +56,4 @@ much of this work.
Footnote:
If you are looking for a generalized diff tool for XML, try diffmk from
https://wwws.sun.com/software/xml/developers/diffmk/
http://wwws.sun.com/software/xml/developers/diffmk/
+11 -11
View File
@@ -7,10 +7,10 @@
<BODY BGCOLOR="#ffffff">
<table width="100%">
<tr>
<td align="left"><A href="https://sourceforge.net/projects/javadiff/">
<td align="left"><A href="http://sourceforge.net/projects/javadiff/">
<IMG src="http://javadiff.cvs.sourceforge.net/*checkout*/javadiff/jdiff/lib/jdiff_logo.gif"
width="88" height="31" border="0" alt="JDiff Logo"></A></td>
<td align="right"><A href="https://sourceforge.net"> <IMG src="https://sourceforge.net/sflogo.php?group_id=37160" width="88" height="31" border="0" alt="SourceForge Logo"></A></td>
<td align="right"><A href="http://sourceforge.net"> <IMG src="http://sourceforge.net/sflogo.php?group_id=37160" width="88" height="31" border="0" alt="SourceForge Logo"></A></td>
</tr>
</table>
@@ -21,7 +21,7 @@ width="88" height="31" border="0" alt="JDiff Logo"></A></td>
<BLOCKQUOTE>
<b>JDiff</b> is a Javadoc <a
href="https://java.sun.com/j2se/javadoc">doclet</a> which generates an
href="http://java.sun.com/j2se/javadoc">doclet</a> which generates an
HTML report of all the packages, classes, constructors, methods, and
fields which have been removed, added or changed in any way, including
their documentation, when two APIs are compared. This is very useful
@@ -312,7 +312,7 @@ the HTML output to the given directory.
<code>-javadocnew</code> &lt;<i>javadoc files location for the new API</i>></DT>
<DD STYLE="margin-right: 2cm; margin-bottom: 0.5cm">
The location of existing Javadoc files
for the new API, e.g. "https://java.sun.com/j2se/<b>1.5.0</b>/docs/api/" for the
for the new API, e.g. "http://java.sun.com/j2se/<b>1.5.0</b>/docs/api/" for the
public documentation for J2SE1.5.0. The default value is "../", which implies
that the documentation directory generated by Javadoc is at the same level as
the "changes.html" file generated by JDiff. Slashes are always
@@ -325,7 +325,7 @@ the HTML output to the given directory.
<DT STYLE="margin-right: 2cm; margin-bottom: 0.5cm">
<code>-javadocold</code> &lt;<i>javadoc files location for the old API</i>></DT>
<DD STYLE="margin-right: 2cm; margin-bottom: 0.5cm"> The location of existing
Javadoc files for the old API, e.g. "https://java.sun.com/j2se/<b>1.5.0</b>/docs/API/"
Javadoc files for the old API, e.g. "http://java.sun.com/j2se/<b>1.5.0</b>/docs/API/"
for the public documentation for J2SE1.5.0. The default value is null, which
results in no links to Javadoc-generated documentation for the previous
release. Slashes are always forward in the argument, since this is an HTML
@@ -426,7 +426,7 @@ the HTML output to the given directory.
<code>-showallchanges</code></DT>
<DD STYLE="margin-right: 2cm; margin-bottom: 0.5cm">
If this argument is used, JDiff will show changes in
native and synchronized modifiers. See <a href="https://java.sun.com/j2se/1.4.1/docs/tooldocs/solaris/javadoc.html#generatedapideclarations">here</a> for why these are not shown by default.
native and synchronized modifiers. See <a href="http://java.sun.com/j2se/1.4.1/docs/tooldocs/solaris/javadoc.html#generatedapideclarations">here</a> for why these are not shown by default.
</DD>
<DT STYLE="margin-right: 2cm; margin-bottom: 0.5cm">
@@ -547,7 +547,7 @@ moved to the end of the file and placed inside XML comments.
<BLOCKQUOTE> The text which is added can be HTML text if necessary, but if the
HTML is incorrect, JDiff may fail to read the comments file and exit. Note that
the required HTML is in fact <a href="https://www.w3.org/TR/xhtml1/diffs.html">XHTML</a>. Since this HTML is stored in an XML document, single tags without their closing ("slash") element are not permitted.
the required HTML is in fact <a href="http://www.w3.org/TR/xhtml1/diffs.html">XHTML</a>. Since this HTML is stored in an XML document, single tags without their closing ("slash") element are not permitted.
For example, most browsers permit HTML which looks like "&lt;p>Here is some
text.", with no closing tag. XML requires that either a closing tag exists ("&lt;/p>"),
or that the single tag is closed, e.g. "&lt;p/>Here is some text.".
@@ -988,7 +988,7 @@ it can tell you how the content has changed.
Nor does it
compare what the methods in an API do; if JDiff could tell you what had changed about the way two
versions of an API execute, the <a
href="https://en.wikipedia.org/wiki/Halting_Problem">Halting
href="http://en.wikipedia.org/wiki/Halting_Problem">Halting
Problem</a> would be solved, and our lives would be very different.</li>
<li>On a P3 450MHz machine, to scan all of the J2SE <code>Java</code>
and <code>javax</code> packages and generate XML takes about 2 minutes
@@ -1002,14 +1002,14 @@ per version. To generate a report from the XML files takes about 30s</li>
<BLOCKQUOTE>
<UL>
<LI><A HREF="https://www.sys-con.com/java">Java Developer's Journal
<LI><A HREF="http://www.sys-con.com/java">Java Developer's Journal
</A>, April 2002 contained an article about JDiff. The article
can also be <a
href="http://javadiff.cvs.sourceforge.net/*checkout*/javadiff/jdiff/doc/JDiffArticle.pdf">found
here</a>.</LI>
<LI><A HREF="https://java.sun.com/j2se/javadoc/">Javadoc</A> and Doclet
<LI><A HREF="http://java.sun.com/j2se/javadoc/">Javadoc</A> and Doclet
documentation from Sun.</LI>
<LI><A HREF="https://java.sun.com/j2se/javadoc/faq.html#doclets">Third-party
<LI><A HREF="http://java.sun.com/j2se/javadoc/faq.html#doclets">Third-party
doclets</a> as listed by Sun.</LI>
<LI><A HREF="http://www.doclet.com">Third-party doclets</a> as listed by others.</LI>
</UL>
+3 -8
View File
@@ -18,11 +18,6 @@ def customizePom(pom, gradleProject) {
"$dep.scope:$dep.groupId:$dep.artifactId"
}
def managedVersions = dependencyManagement.managedVersions
generatedPom.dependencies.findAll{dep -> !dep.version }.each { dep ->
dep.version = managedVersions["${dep.groupId}:${dep.artifactId}"]
}
// add all items necessary for maven central publication
generatedPom.project {
name = gradleProject.description
@@ -34,8 +29,8 @@ def customizePom(pom, gradleProject) {
}
licenses {
license {
name "Apache License, Version 2.0"
url "https://www.apache.org/licenses/LICENSE-2.0"
name "The Apache Software License, Version 2.0"
url "https://www.apache.org/licenses/LICENSE-2.0.txt"
distribution "repo"
}
}
@@ -48,7 +43,7 @@ def customizePom(pom, gradleProject) {
developer {
id = "jhoeller"
name = "Juergen Hoeller"
email = "jhoeller@pivotal.io"
email = "jhoeller@gopivotal.com"
}
}
issueManagement {
Binary file not shown.
+2 -1
View File
@@ -1,5 +1,6 @@
#Wed Apr 30 13:06:57 CEST 2014
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-1.12-bin.zip
Vendored
+52 -60
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env sh
#!/usr/bin/env bash
##############################################################################
##
@@ -6,6 +6,48 @@
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
GRADLE_OPTS="-XX:MaxMetaspaceSize=1024m -Xmx1024m $GRADLE_OPTS"
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
@@ -20,50 +62,9 @@ while [ -h "$PRG" ] ; do
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
GRADLE_OPTS="-XX:MaxMetaspaceSize=1024m -Xmx1024m $GRADLE_OPTS"
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# 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
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -90,7 +91,7 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
@@ -114,7 +115,6 @@ fi
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
@@ -155,19 +155,11 @@ if $cygwin ; then
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
APP_ARGS=$(save "$@")
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
Vendored
+11 -5
View File
@@ -8,15 +8,15 @@
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set GRADLE_OPTS=-XX:MaxMetaspaceSize=1024m -Xmx1024m -XX:MaxHeapSize=256m %GRADLE_OPTS%
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set GRADLE_OPTS=-XX:MaxMetaspaceSize=1024m -Xmx1024m -XX:MaxHeapSize=256m %GRADLE_OPTS%
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
@@ -47,9 +47,10 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
@@ -60,6 +61,11 @@ set _SKIP=2
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
+12 -17
View File
@@ -1,4 +1,5 @@
@echo off
set STS_TEST_VERSION='2.9.2.RELEASE'
set CURRENT_DIR=%~dp0
cd %CURRENT_DIR%
@@ -7,22 +8,16 @@ cls
echo.
echo -----------------------------------------------------------------------
echo Spring Framework - Eclipse/STS project import guide
echo Spring Framework Eclipse/STS project import guide
echo.
echo This script will guide you through the process of importing the Spring
echo Framework projects into Eclipse or the Spring Tool Suite (STS). It is
echo recommended that you have a recent version of Eclipse or STS. As a bare
echo minimum you will need Eclipse with full Java 8 support, the AspectJ
echo Development Tools (AJDT), and the Groovy Compiler.
echo This script will guide you through the process of importing the
echo Spring Framework sources into Eclipse/STS. It is recommended that you
echo have a recent version of the SpringSource Tool Suite (this script has
echo been tested against STS %STS_TEST_VERSION%), but at the minimum you will
echo need Eclipse + AJDT.
echo.
echo If you need to download and install Eclipse or STS, please do that now
echo by visiting one of the following sites:
echo.
echo - Eclipse downloads: https://download.eclipse.org/eclipse/downloads
echo - STS downloads: https://spring.io/tools/sts/all
echo - STS nightly builds: https://dist.springsource.com/snapshot/STS/nightly-distributions.html
echo - ADJT: https://www.eclipse.org/ajdt/downloads/
echo - Groovy Eclipse: https://github.com/groovy/groovy-eclipse/wiki
echo If you need to download and install STS, please do that now by
echo visiting https://spring.io/tools/sts/all
echo.
echo Otherwise, press enter and we'll begin.
@@ -34,8 +29,8 @@ REM - generates OXM test classes to avoid errors on import into Eclipse
REM - generates metadata for all subprojects
REM - skips metadata gen for the root project (-x :eclipse) to work
REM around Eclipse's inability to import hierarchical project structures
REM SET COMMAND="./gradlew --no-daemon cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
SET COMMAND=gradlew --no-daemon cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse
REM SET COMMAND="./gradlew cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
SET COMMAND=gradlew cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse
echo.
echo -----------------------------------------------------------------------
@@ -74,7 +69,7 @@ echo When the above is complete, return here and press the enter key.
pause
set COMMAND=gradlew --no-daemon :eclipse
set COMMAND=gradlew :eclipse
echo.
echo -----------------------------------------------------------------------
+38 -47
View File
@@ -1,31 +1,22 @@
STS_TEST_VERSION='2.9.2.RELEASE'
cd `dirname $0`
clear
cat <<EOM
------------------------------------------------------------------------
Spring Framework - Eclipse/STS Project Import Guide
-----------------------------------------------------------------------
Spring Framework Eclipse/STS project import guide
This script will guide you through the process of importing the Spring
Framework projects into Eclipse or the Spring Tool Suite (STS). It is
recommended that you have a recent version of Eclipse or STS. As a bare
minimum you will need Eclipse with full Java 8 support, the AspectJ
Development Tools (AJDT), and the Groovy Compiler.
This script will guide you through the process of importing the
Spring Framework sources into Eclipse/STS. It is recommended that you
have a recent version of the SpringSource Tool Suite (this script has
been tested against STS $STS_TEST_VERSION), but at the minimum you will
need Eclipse + AJDT.
This script has been tested against:
If you need to download and install STS, please do that now by
visiting https://spring.io/tools/sts/all
- STS: 3.8.3.RELEASE (Eclipse Neon.2 4.6.2)
- AJDT: 2.2.4.201612122115 (Eclipse Neon 4.6)
If you need to download and install Eclipse or STS, please do that now
by visiting one of the following sites:
- Eclipse downloads: https://download.eclipse.org/eclipse/downloads
- STS downloads: https://spring.io/tools/sts/all
- STS nightly builds: https://dist.springsource.com/snapshot/STS/nightly-distributions.html
- ADJT: https://www.eclipse.org/ajdt/downloads/
- Groovy Eclipse: https://github.com/groovy/groovy-eclipse/wiki
Once Eclipse/STS is installed, press enter, and we'll begin.
Otherwise, press enter and we'll begin.
EOM
read
@@ -36,18 +27,18 @@ read
# - generates metadata for all subprojects
# - skips metadata gen for the root project (-x :eclipse) to work
# around Eclipse's inability to import hierarchical project structures
COMMAND="./gradlew --no-daemon cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
COMMAND="./gradlew cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
cat <<EOM
------------------------------------------------------------------------
-----------------------------------------------------------------------
STEP 1: Generate subproject Eclipse metadata
The first step will be to generate Eclipse project metadata for each of
the spring-* subprojects. This happens via the built-in "Gradle wrapper"
script (./gradlew in this directory). If this is your first time using
the Gradle wrapper, this step may take a few minutes while a Gradle
distribution is downloaded for you.
The first step will be to generate Eclipse project metadata for each
of the spring-* subprojects. This happens via the built-in
"Gradle wrapper" script (./gradlew in this directory). If this is your
first time using the Gradle wrapper, this step may take a few minutes
while a Gradle distribution is downloaded for you.
The command run will be:
@@ -62,33 +53,33 @@ $COMMAND || exit
cat <<EOM
------------------------------------------------------------------------
-----------------------------------------------------------------------
STEP 2: Import subprojects into Eclipse/STS
Within Eclipse/STS, do the following:
- File > Import... > Existing Projects into Workspace
- When prompted for the 'root directory', provide $PWD.
- Press enter. You will see the modules show up under "Projects".
- All projects should be selected/checked. Click Finish.
- When the project import is complete, you should have no errors.
File > Import... > Existing Projects into Workspace
> When prompted for the 'root directory', provide $PWD
> Press enter. You will see the modules show up under "Projects"
> All projects should be selected/checked. Click Finish.
> When the project import is complete, you should have no errors.
When the above is complete, return here and press the enter key.
EOM
read
COMMAND="./gradlew --no-daemon :eclipse"
COMMAND="./gradlew :eclipse"
cat <<EOM
------------------------------------------------------------------------
STEP 3: Generate root project Eclipse metadata
-----------------------------------------------------------------------
STEP 3: generate root project Eclipse metadata
Unfortunately, Eclipse does not support importing project hierarchies,
so we had to skip root project metadata generation during step 1. In
this step we simply generate root project metadata so that you can
import it in the next step.
Unfortunately, Eclipse does not allow for importing project
hierarchies, so we had to skip root project metadata generation in the
during step 1. In this step we simply generate root project metadata
so you can import it in the next step.
The command run will be:
@@ -102,11 +93,11 @@ read
$COMMAND || exit
cat <<EOM
------------------------------------------------------------------------
-----------------------------------------------------------------------
STEP 4: Import root project into Eclipse/STS
Follow the project import steps listed in step 2 above to import the
root "spring" project.
root project.
Press enter when complete, and move on to the final step.
EOM
@@ -114,14 +105,14 @@ EOM
read
cat <<EOM
------------------------------------------------------------------------
-----------------------------------------------------------------------
STEP 5: Enable Git support for all projects
- In the Eclipse/STS Package Explorer, select all spring* projects.
- Right-click to open the context menu and select Team > Share Project...
- In the Share Project dialog that appears, select Git and press Next.
- Check "Use or create repository in parent folder of project".
- Click Finish.
- In the Share Project dialog that appears, select Git and press Next
- Check "Use or create repository in parent folder of project"
- Click Finish
When complete, you'll have Git support enabled for all projects.
+15 -18
View File
@@ -1,28 +1,25 @@
The following has been tested against IntelliJ IDEA 2016.2.2
The following has been tested against Intellij IDEA 12.0
## Steps
_Within your locally cloned spring-framework working directory:_
1. Precompile `spring-oxm` with `./gradlew :spring-oxm:compileTestJava`
2. Import into IntelliJ (File -> New -> Project from Existing Sources -> Navigate to directory -> Select build.gradle)
3. When prompted exclude the `spring-aspects` module (or after the import via File-> Project Structure -> Modules)
4. Code away
1. Generate IDEA metadata with `./gradlew :spring-oxm:compileTestJava cleanIdea idea`
2. Import into IDEA as usual
3. Set the Project JDK as appropriate
4. Add git support
5. Code away
## Known issues
1. `spring-core` and `spring-oxm` should be pre-compiled due to repackaged dependencies.
See `*RepackJar` tasks in the build and https://youtrack.jetbrains.com/issue/IDEA-160605).
2. `spring-aspects` does not compile due to references to aspect types unknown to
IntelliJ IDEA. See https://youtrack.jetbrains.com/issue/IDEA-64446 for details. In the meantime, the
'spring-aspects' can be excluded from the project to avoid compilation errors.
3. While JUnit tests pass from the command line with Gradle, some may fail when run from
IntelliJ IDEA. Resolving this is a work in progress. If attempting to run all JUnit tests from within
IntelliJ IDEA, you will likely need to set the following VM options to avoid out of memory errors:
1. Those steps don't work currently for Intellij IDEA 13+
2. `spring-aspects` does not compile out of the box due to references to aspect types unknown to IDEA.
See http://youtrack.jetbrains.com/issue/IDEA-64446 for details. In the meantime, the 'spring-aspects'
module has been excluded from the overall project to avoid compilation errors.
3. While all JUnit tests pass from the command line with Gradle, many will fail when run from IDEA.
Resolving this is a work in progress. If attempting to run all JUnit tests from within IDEA, you will
likely need to set the following VM options to avoid out of memory errors:
-XX:MaxPermSize=2048m -Xmx2048m -XX:MaxHeapSize=2048m
4. If you invoke "Rebuild Project" in the IDE, you'll have to generate some test
resources of the `spring-oxm` module again (`./gradlew :spring-oxm:compileTestJava`)
## Tips
@@ -31,6 +28,6 @@ You'll notice these files are already intentionally in .gitignore. The same poli
## FAQ
Q. What about IntelliJ IDEA's own [Gradle support](https://confluence.jetbrains.net/display/IDEADEV/Gradle+integration)?
Q. What about IDEA's own [Gradle support](http://confluence.jetbrains.net/display/IDEADEV/Gradle+integration)?
A. Keep an eye on https://youtrack.jetbrains.com/issue/IDEA-53476
A. Keep an eye on http://youtrack.jetbrains.com/issue/IDEA-53476
+7 -8
View File
@@ -1,31 +1,30 @@
rootProject.name = "spring"
include "spring-aop"
include "spring-aspects"
include "spring-beans"
include "spring-beans-groovy"
include "spring-context"
include "spring-context-support"
include "spring-context-indexer"
include "spring-core"
include "spring-expression"
include "spring-instrument"
include "spring-jcl"
include "spring-instrument-tomcat"
include "spring-jdbc"
include "spring-jms"
include "spring-messaging"
include "spring-orm"
include "spring-orm-hibernate4"
include "spring-oxm"
include "spring-test"
include "spring-tx"
include "spring-web"
include "spring-webmvc"
include "spring-webflux"
include "spring-webmvc-portlet"
include "spring-webmvc-tiles3"
include "spring-websocket"
include "spring-framework-bom"
// Exposes gradle buildSrc for IDE support
include "buildSrc"
rootProject.children.find{ it.name == "buildSrc" }.name = "spring-build-src"
rootProject.name = "spring"
rootProject.children.each {project ->
project.buildFileName = "${project.name}.gradle"
}
-9
View File
@@ -1,9 +0,0 @@
description = "Spring AOP"
dependencies {
compile(project(":spring-beans"))
compile(project(":spring-core"))
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
optional("org.apache.commons:commons-pool2:2.5.0")
optional("com.jamonapi:jamon:2.81")
}
@@ -1,28 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.aopalliance.aop;
/**
* Tag interface for Advice. Implementations can be any type
* of advice, such as Interceptors.
*
* @author Rod Johnson
* @version $Id: Advice.java,v 1.1 2004/03/19 17:02:16 johnsonr Exp $
*/
public interface Advice {
}
@@ -1,48 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.aopalliance.aop;
/**
* Superclass for all AOP infrastructure exceptions.
* Unchecked, as such exceptions are fatal and end user
* code shouldn't be forced to catch them.
*
* @author Rod Johnson
* @author Bob Lee
* @author Juergen Hoeller
*/
@SuppressWarnings("serial")
public class AspectException extends RuntimeException {
/**
* Constructor for AspectException.
* @param message the exception message
*/
public AspectException(String message) {
super(message);
}
/**
* Constructor for AspectException.
* @param message the exception message
* @param cause the root cause, if any
*/
public AspectException(String message, Throwable cause) {
super(message, cause);
}
}
@@ -1,4 +0,0 @@
/**
* The core AOP Alliance advice marker.
*/
package org.aopalliance.aop;
@@ -1,59 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.aopalliance.intercept;
/**
* Intercepts the construction of a new object.
*
* <p>The user should implement the {@link
* #construct(ConstructorInvocation)} method to modify the original
* behavior. E.g. the following class implements a singleton
* interceptor (allows only one unique instance for the intercepted
* class):
*
* <pre class=code>
* class DebuggingInterceptor implements ConstructorInterceptor {
* Object instance=null;
*
* Object construct(ConstructorInvocation i) throws Throwable {
* if(instance==null) {
* return instance=i.proceed();
* } else {
* throw new Exception("singleton does not allow multiple instance");
* }
* }
* }
* </pre>
*
* @author Rod Johnson
*/
public interface ConstructorInterceptor extends Interceptor {
/**
* Implement this method to perform extra treatments before and
* after the construction of a new object. Polite implementations
* would certainly like to invoke {@link Joinpoint#proceed()}.
* @param invocation the construction joinpoint
* @return the newly created object, which is also the result of
* the call to {@link Joinpoint#proceed()}; might be replaced by
* the interceptor
* @throws Throwable if the interceptors or the target object
* throws an exception
*/
Object construct(ConstructorInvocation invocation) throws Throwable;
}
@@ -1,41 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.aopalliance.intercept;
import java.lang.reflect.Constructor;
/**
* Description of an invocation to a constuctor, given to an
* interceptor upon constructor-call.
*
* <p>A constructor invocation is a joinpoint and can be intercepted
* by a constructor interceptor.
*
* @author Rod Johnson
* @see ConstructorInterceptor
*/
public interface ConstructorInvocation extends Invocation {
/**
* Get the constructor being called.
* <p>This method is a friendly implementation of the
* {@link Joinpoint#getStaticPart()} method (same result).
* @return the constructor being called
*/
Constructor<?> getConstructor();
}
@@ -1,59 +0,0 @@
/*
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.aopalliance.intercept;
import org.aopalliance.aop.Advice;
/**
* This interface represents a generic interceptor.
*
* <p>A generic interceptor can intercept runtime events that occur
* within a base program. Those events are materialized by (reified
* in) joinpoints. Runtime joinpoints can be invocations, field
* access, exceptions...
*
* <p>This interface is not used directly. Use the sub-interfaces
* to intercept specific events. For instance, the following class
* implements some specific interceptors in order to implement a
* debugger:
*
* <pre class=code>
* class DebuggingInterceptor implements MethodInterceptor,
* ConstructorInterceptor {
*
* Object invoke(MethodInvocation i) throws Throwable {
* debug(i.getMethod(), i.getThis(), i.getArgs());
* return i.proceed();
* }
*
* Object construct(ConstructorInvocation i) throws Throwable {
* debug(i.getConstructor(), i.getThis(), i.getArgs());
* return i.proceed();
* }
*
* void debug(AccessibleObject ao, Object this, Object value) {
* ...
* }
* }
* </pre>
*
* @author Rod Johnson
* @see Joinpoint
*/
public interface Interceptor extends Advice {
}
@@ -1,37 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.aopalliance.intercept;
/**
* This interface represents an invocation in the program.
*
* <p>An invocation is a joinpoint and can be intercepted by an
* interceptor.
*
* @author Rod Johnson
*/
public interface Invocation extends Joinpoint {
/**
* Get the arguments as an array object.
* It is possible to change element values within this
* array to change the arguments.
* @return the argument of the invocation
*/
Object[] getArguments();
}
@@ -1,65 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.aopalliance.intercept;
import java.lang.reflect.AccessibleObject;
/**
* This interface represents a generic runtime joinpoint (in the AOP
* terminology).
*
* <p>A runtime joinpoint is an <i>event</i> that occurs on a static
* joinpoint (i.e. a location in a the program). For instance, an
* invocation is the runtime joinpoint on a method (static joinpoint).
* The static part of a given joinpoint can be generically retrieved
* using the {@link #getStaticPart()} method.
*
* <p>In the context of an interception framework, a runtime joinpoint
* is then the reification of an access to an accessible object (a
* method, a constructor, a field), i.e. the static part of the
* joinpoint. It is passed to the interceptors that are installed on
* the static joinpoint.
*
* @author Rod Johnson
* @see Interceptor
*/
public interface Joinpoint {
/**
* Proceed to the next interceptor in the chain.
* <p>The implementation and the semantics of this method depends
* on the actual joinpoint type (see the children interfaces).
* @return see the children interfaces' proceed definition
* @throws Throwable if the joinpoint throws an exception
*/
Object proceed() throws Throwable;
/**
* Return the object that holds the current joinpoint's static part.
* <p>For instance, the target object for an invocation.
* @return the object (can be null if the accessible object is static)
*/
Object getThis();
/**
* Return the static part of this joinpoint.
* <p>The static part is an accessible object on which a chain of
* interceptors are installed.
*/
AccessibleObject getStaticPart();
}
@@ -1,57 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.aopalliance.intercept;
/**
* Intercepts calls on an interface on its way to the target. These
* are nested "on top" of the target.
*
* <p>The user should implement the {@link #invoke(MethodInvocation)}
* method to modify the original behavior. E.g. the following class
* implements a tracing interceptor (traces all the calls on the
* intercepted method(s)):
*
* <pre class=code>
* class TracingInterceptor implements MethodInterceptor {
* Object invoke(MethodInvocation i) throws Throwable {
* System.out.println("method "+i.getMethod()+" is called on "+
* i.getThis()+" with args "+i.getArguments());
* Object ret=i.proceed();
* System.out.println("method "+i.getMethod()+" returns "+ret);
* return ret;
* }
* }
* </pre>
*
* @author Rod Johnson
*/
@FunctionalInterface
public interface MethodInterceptor extends Interceptor {
/**
* Implement this method to perform extra treatments before and
* after the invocation. Polite implementations would certainly
* like to invoke {@link Joinpoint#proceed()}.
* @param invocation the method invocation joinpoint
* @return the result of the call to {@link Joinpoint#proceed()};
* might be intercepted by the interceptor
* @throws Throwable if the interceptors or the target object
* throws an exception
*/
Object invoke(MethodInvocation invocation) throws Throwable;
}
@@ -1,41 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.aopalliance.intercept;
import java.lang.reflect.Method;
/**
* Description of an invocation to a method, given to an interceptor
* upon method-call.
*
* <p>A method invocation is a joinpoint and can be intercepted by a
* method interceptor.
*
* @author Rod Johnson
* @see MethodInterceptor
*/
public interface MethodInvocation extends Invocation {
/**
* Get the method being called.
* <p>This method is a frienly implementation of the
* {@link Joinpoint#getStaticPart()} method (same result).
* @return the method being called
*/
Method getMethod();
}
@@ -1,4 +0,0 @@
/**
* The AOP Alliance reflective interception abstraction.
*/
package org.aopalliance.intercept;
@@ -1,4 +0,0 @@
/**
* Spring's variant of the AOP Alliance interfaces.
*/
package org.aopalliance;
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -31,18 +31,9 @@ import org.aopalliance.aop.Advice;
* implemented using interception.
*
* @author Rod Johnson
* @author Juergen Hoeller
*/
public interface Advisor {
/**
* Common placeholder for an empty {@code Advice} to be returned from
* {@link #getAdvice()} if no proper advice has been configured (yet).
* @since 5.0
*/
Advice EMPTY_ADVICE = new Advice() {};
/**
* Return the advice part of this aspect. An advice may be an
* interceptor, a before advice, a throws advice, etc.
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -18,8 +18,6 @@ package org.springframework.aop;
import java.lang.reflect.Method;
import org.springframework.lang.Nullable;
/**
* 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.
@@ -41,6 +39,6 @@ public interface AfterReturningAdvice extends AfterAdvice {
* allowed by the method signature. Otherwise the exception
* will be wrapped as a runtime exception.
*/
void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable;
void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable;
}
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -27,7 +27,6 @@ package org.springframework.aop;
* @see Pointcut
* @see MethodMatcher
*/
@FunctionalInterface
public interface ClassFilter {
/**
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -18,8 +18,6 @@ package org.springframework.aop;
import java.lang.reflect.Method;
import org.springframework.lang.Nullable;
/**
* A specialized type of {@link MethodMatcher} that takes into account introductions
* when matching methods. If there are no introductions on the target class,
@@ -41,6 +39,6 @@ public interface IntroductionAwareMethodMatcher extends MethodMatcher {
* asking is the subject on one or more introductions; {@code false} otherwise
* @return whether or not this method matches statically
*/
boolean matches(Method method, @Nullable Class<?> targetClass, boolean hasIntroductions);
boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions);
}
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -18,8 +18,6 @@ package org.springframework.aop;
import java.lang.reflect.Method;
import org.springframework.lang.Nullable;
/**
* Advice invoked before a method is invoked. Such advices cannot
* prevent the method call proceeding, unless they throw a Throwable.
@@ -41,6 +39,6 @@ public interface MethodBeforeAdvice extends BeforeAdvice {
* allowed by the method signature. Otherwise the exception
* will be wrapped as a runtime exception.
*/
void before(Method method, Object[] args, @Nullable Object target) throws Throwable;
void before(Method method, Object[] args, Object target) throws Throwable;
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -18,8 +18,6 @@ package org.springframework.aop;
import java.lang.reflect.Method;
import org.springframework.lang.Nullable;
/**
* Part of a {@link Pointcut}: Checks whether the target method is eligible for advice.
*
@@ -50,17 +48,16 @@ import org.springframework.lang.Nullable;
public interface MethodMatcher {
/**
* Perform static checking whether the given method matches.
* <p>If this returns {@code false} or if the {@link #isRuntime()}
* method returns {@code false}, no runtime check (i.e. no
* {@link #matches(java.lang.reflect.Method, Class, Object[])} call)
* will be made.
* Perform static checking whether the given method matches. If this
* returns {@code false} or if the {@link #isRuntime()} method
* returns {@code false}, 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}, 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, @Nullable Class<?> targetClass);
boolean matches(Method method, Class<?> targetClass);
/**
* Is this MethodMatcher dynamic, that is, must a final call be made on the
@@ -89,7 +86,7 @@ public interface MethodMatcher {
* @return whether there's a runtime match
* @see MethodMatcher#matches(Method, Class)
*/
boolean matches(Method method, @Nullable Class<?> targetClass, Object... args);
boolean matches(Method method, Class<?> targetClass, Object[] args);
/**
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -18,8 +18,6 @@ package org.springframework.aop;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.lang.Nullable;
/**
* Extension of the AOP Alliance {@link org.aopalliance.intercept.MethodInvocation}
* interface, allowing access to the proxy that the method invocation was made through.
@@ -59,14 +57,14 @@ public interface ProxyMethodInvocation extends MethodInvocation {
* @return an invocable clone of this invocation.
* {@code proceed()} can be called once per clone.
*/
MethodInvocation invocableClone(Object... arguments);
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);
void setArguments(Object[] arguments);
/**
* Add the specified user attribute with the given value to this invocation.
@@ -75,7 +73,7 @@ public interface ProxyMethodInvocation extends MethodInvocation {
* @param key the name of the attribute
* @param value the value of the attribute, or {@code null} to reset it
*/
void setUserAttribute(String key, @Nullable Object value);
void setUserAttribute(String key, Object value);
/**
* Return the value of the specified user attribute.
@@ -83,7 +81,6 @@ public interface ProxyMethodInvocation extends MethodInvocation {
* @return the value of the attribute, or {@code null} if not set
* @see #setUserAttribute
*/
@Nullable
Object getUserAttribute(String key);
}
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,13 +16,11 @@
package org.springframework.aop;
import org.springframework.lang.Nullable;
/**
* 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})
* (via {@link org.springframework.aop.framework.Advised}}
* as well as by {@link TargetSource TargetSources}.
*
* @author Juergen Hoeller
@@ -36,7 +34,6 @@ public interface TargetClassAware {
* (typically a proxy configuration or an actual proxy).
* @return the target Class, or {@code null} if not known
*/
@Nullable
Class<?> getTargetClass();
}
@@ -1,11 +1,11 @@
/*<
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,8 +16,6 @@
package org.springframework.aop;
import org.springframework.lang.Nullable;
/**
* A {@code TargetSource} is used to obtain the current "target" of
* an AOP invocation, which will be invoked via reflection if no around
@@ -31,24 +29,24 @@ import org.springframework.lang.Nullable;
* {@code TargetSources} directly: this is an AOP framework interface.
*
* @author Rod Johnson
* @author Juergen Hoeller
*/
public interface TargetSource extends TargetClassAware {
/**
* Return the type of targets returned by this {@link TargetSource}.
* <p>Can return {@code null}, although certain usages of a {@code TargetSource}
* might just work with a predetermined target class.
* <p>Can return {@code null}, although certain usages of a
* {@code TargetSource} might just work with a predetermined
* target class.
* @return the type of targets returned by this {@link TargetSource}
*/
@Override
@Nullable
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()}.
* <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} if the target is immutable
* @see #getTarget
*/
@@ -57,16 +55,14 @@ public interface TargetSource extends TargetClassAware {
/**
* 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,
* or {@code null} if there is no actual target instance
* @return the target object, which contains the joinpoint
* @throws Exception if the target object can't be resolved
*/
@Nullable
Object getTarget() throws Exception;
/**
* Release the given target object obtained from the
* {@link #getTarget()} method, if any.
* {@link #getTarget()} method.
* @param target object obtained from a call to {@link #getTarget()}
* @throws Exception if the object can't be released
*/
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -19,8 +19,6 @@ package org.springframework.aop;
import java.io.Serializable;
import java.lang.reflect.Method;
import org.springframework.lang.Nullable;
/**
* Canonical MethodMatcher instance that matches all methods.
*
@@ -31,36 +29,28 @@ class TrueMethodMatcher implements MethodMatcher, Serializable {
public static final TrueMethodMatcher INSTANCE = new TrueMethodMatcher();
/**
* Enforce Singleton pattern.
*/
private TrueMethodMatcher() {
}
@Override
public boolean isRuntime() {
return false;
}
@Override
public boolean matches(Method method, @Nullable Class<?> targetClass) {
public boolean matches(Method method, Class<?> targetClass) {
return true;
}
@Override
public boolean matches(Method method, @Nullable Class<?> targetClass, Object... args) {
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
// Should never be invoked as isRuntime returns false.
throw new UnsupportedOperationException();
}
@Override
public String toString() {
return "MethodMatcher.TRUE";
}
/**
* Required to support serialization. Replaces with canonical
* instance on deserialization, protecting Singleton pattern.
@@ -70,4 +60,9 @@ class TrueMethodMatcher implements MethodMatcher, Serializable {
return INSTANCE;
}
@Override
public String toString() {
return "MethodMatcher.TRUE";
}
}
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,9 +16,6 @@
package org.springframework.aop.aspectj;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
@@ -42,7 +39,6 @@ import org.springframework.aop.support.MethodMatchers;
import org.springframework.aop.support.StaticMethodMatcher;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
@@ -59,8 +55,7 @@ import org.springframework.util.StringUtils;
* @author Ramnivas Laddad
* @since 2.0
*/
@SuppressWarnings("serial")
public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation, Serializable {
public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation {
/**
* Key used in ReflectiveMethodInvocation userAtributes map for the current joinpoint.
@@ -91,24 +86,21 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
private final Class<?> declaringClass;
protected final Method aspectJAdviceMethod;
private final String methodName;
private final Class<?>[] parameterTypes;
protected transient 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
* 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 = "";
private String aspectName;
/**
* The order of declaration of this advice within the aspect.
@@ -119,16 +111,13 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
* This will be non-null if the creator of this advice object knows the argument names
* and sets them explicitly
*/
@Nullable
private String[] argumentNames;
private String[] argumentNames = null;
/** Non-null if after throwing advice binds the thrown value */
@Nullable
private String throwingName;
private String throwingName = null;
/** Non-null if after returning advice binds the return value */
@Nullable
private String returningName;
private String returningName = null;
private Class<?> discoveredReturningType = Object.class;
@@ -146,12 +135,10 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
*/
private int joinPointStaticPartArgumentIndex = -1;
@Nullable
private Map<String, Integer> argumentBindings;
private Map<String, Integer> argumentBindings = null;
private boolean argumentsIntrospected = false;
@Nullable
private Type 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.
@@ -167,10 +154,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
Method aspectJAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aspectInstanceFactory) {
Assert.notNull(aspectJAdviceMethod, "Advice method must not be null");
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
this.methodName = aspectJAdviceMethod.getName();
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
this.aspectJAdviceMethod = aspectJAdviceMethod;
this.adviceInvocationArgumentCount = this.aspectJAdviceMethod.getParameterTypes().length;
this.pointcut = pointcut;
this.aspectInstanceFactory = aspectInstanceFactory;
}
@@ -213,7 +198,6 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
/**
* Return the ClassLoader for aspect instances.
*/
@Nullable
public final ClassLoader getAspectClassLoader() {
return this.aspectInstanceFactory.getAspectClassLoader();
}
@@ -224,9 +208,6 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
/**
* Set the name of the aspect (bean) in which the advice was declared.
*/
public void setAspectName(String name) {
this.aspectName = name;
}
@@ -237,7 +218,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
/**
* Set the declaration order of this advice within the aspect.
* Sets the <b>declaration order</b> of this advice within the aspect
*/
public void setDeclarationOrder(int order) {
this.declarationOrder = order;
@@ -269,17 +250,17 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
this.argumentNames[i] + "' that is not a valid Java identifier");
}
}
if (this.argumentNames != null) {
if (this.aspectJAdviceMethod.getParameterCount() == this.argumentNames.length + 1) {
if (argumentNames != null) {
if (aspectJAdviceMethod.getParameterTypes().length == argumentNames.length + 1) {
// May need to add implicit join point arg name...
Class<?> firstArgType = this.aspectJAdviceMethod.getParameterTypes()[0];
Class<?> firstArgType = aspectJAdviceMethod.getParameterTypes()[0];
if (firstArgType == JoinPoint.class ||
firstArgType == ProceedingJoinPoint.class ||
firstArgType == JoinPoint.StaticPart.class) {
String[] oldNames = this.argumentNames;
this.argumentNames = new String[oldNames.length + 1];
this.argumentNames[0] = "THIS_JOIN_POINT";
System.arraycopy(oldNames, 0, this.argumentNames, 1, oldNames.length);
String[] oldNames = argumentNames;
argumentNames = new String[oldNames.length + 1];
argumentNames[0] = "THIS_JOIN_POINT";
System.arraycopy(oldNames, 0, argumentNames, 1, oldNames.length);
}
}
}
@@ -305,8 +286,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
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);
"' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath. " +
"Root cause: " + ex);
}
}
}
@@ -315,7 +296,6 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
return this.discoveredReturningType;
}
@Nullable
protected Type getDiscoveredReturningGenericType() {
return this.discoveredReturningGenericType;
}
@@ -340,8 +320,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
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);
"' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath. " +
"Root cause: " + ex);
}
}
}
@@ -377,16 +357,18 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
* to which argument name. There are multiple strategies for determining
* this binding, which are arranged in a ChainOfResponsibility.
*/
public final synchronized void calculateArgumentBindings() {
public synchronized final void calculateArgumentBindings() {
// The simple case... nothing to bind.
if (this.argumentsIntrospected || this.parameterTypes.length == 0) {
if (this.argumentsIntrospected || this.adviceInvocationArgumentCount == 0) {
return;
}
int numUnboundArgs = this.parameterTypes.length;
int numUnboundArgs = this.adviceInvocationArgumentCount;
Class<?>[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0]) ||
maybeBindJoinPointStaticPart(parameterTypes[0])) {
if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0])) {
numUnboundArgs--;
}
else if (maybeBindJoinPointStaticPart(parameterTypes[0])) {
numUnboundArgs--;
}
@@ -399,7 +381,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
private boolean maybeBindJoinPoint(Class<?> candidateParameterType) {
if (JoinPoint.class == candidateParameterType) {
if (candidateParameterType.equals(JoinPoint.class)) {
this.joinPointArgumentIndex = 0;
return true;
}
@@ -409,7 +391,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
private boolean maybeBindProceedingJoinPoint(Class<?> candidateParameterType) {
if (ProceedingJoinPoint.class == candidateParameterType) {
if (candidateParameterType.equals(ProceedingJoinPoint.class)) {
if (!supportsProceedingJoinPoint()) {
throw new IllegalArgumentException("ProceedingJoinPoint is only supported for around advice");
}
@@ -426,7 +408,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
private boolean maybeBindJoinPointStaticPart(Class<?> candidateParameterType) {
if (JoinPoint.StaticPart.class == candidateParameterType) {
if (candidateParameterType.equals(JoinPoint.StaticPart.class)) {
this.joinPointStaticPartArgumentIndex = 0;
return true;
}
@@ -470,18 +452,17 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
private void bindExplicitArguments(int numArgumentsLeftToBind) {
Assert.state(this.argumentNames != null, "No argument names available");
this.argumentBindings = new HashMap<>();
this.argumentBindings = new HashMap<String, Integer>();
int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterCount();
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 " +
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.parameterTypes.length - numArgumentsLeftToBind;
int argumentIndexOffset = this.adviceInvocationArgumentCount - numArgumentsLeftToBind;
for (int i = argumentIndexOffset; i < this.argumentNames.length; i++) {
this.argumentBindings.put(this.argumentNames[i], i);
}
@@ -490,8 +471,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
// 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");
throw new IllegalStateException("Returning argument name '"
+ this.returningName + "' was not bound in advice arguments");
}
else {
Integer index = this.argumentBindings.get(this.returningName);
@@ -501,8 +482,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
if (this.throwingName != null) {
if (!this.argumentBindings.containsKey(this.throwingName)) {
throw new IllegalStateException("Throwing argument name '" + this.throwingName +
"' was not bound in advice arguments");
throw new IllegalStateException("Throwing argument name '"
+ this.throwingName + "' was not bound in advice arguments");
}
else {
Integer index = this.argumentBindings.get(this.throwingName);
@@ -511,7 +492,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
// configure the pointcut expression accordingly.
configurePointcutParameters(this.argumentNames, argumentIndexOffset);
configurePointcutParameters(argumentIndexOffset);
}
/**
@@ -519,7 +500,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
* pointcut parameters - but returning and throwing vars are handled differently
* and must be removed from the list if present.
*/
private void configurePointcutParameters(String[] argumentNames, int argumentIndexOffset) {
private void configurePointcutParameters(int argumentIndexOffset) {
int numParametersToRemove = argumentIndexOffset;
if (this.returningName != null) {
numParametersToRemove++;
@@ -527,20 +508,20 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
if (this.throwingName != null) {
numParametersToRemove++;
}
String[] pointcutParameterNames = new String[argumentNames.length - 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 < argumentNames.length; i++) {
for (int i = 0; i < this.argumentNames.length; i++) {
if (i < argumentIndexOffset) {
continue;
}
if (argumentNames[i].equals(this.returningName) ||
argumentNames[i].equals(this.throwingName)) {
if (this.argumentNames[i].equals(this.returningName) ||
this.argumentNames[i].equals(this.throwingName)) {
continue;
}
pointcutParameterNames[index] = argumentNames[i];
pointcutParameterNames[index] = this.argumentNames[i];
pointcutParameterTypes[index] = methodParameterTypes[i];
index++;
}
@@ -558,13 +539,11 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
* @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, @Nullable JoinPointMatch jpMatch,
@Nullable Object returnValue, @Nullable Throwable ex) {
protected Object[] argBinding(JoinPoint jp, JoinPointMatch jpMatch, Object returnValue, Throwable ex) {
calculateArgumentBindings();
// AMC start
Object[] adviceInvocationArgs = new Object[this.parameterTypes.length];
Object[] adviceInvocationArgs = new Object[this.adviceInvocationArgumentCount];
int numBound = 0;
if (this.joinPointArgumentIndex != -1) {
@@ -601,10 +580,11 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
}
if (numBound != this.parameterTypes.length) {
throw new IllegalStateException("Required to bind " + this.parameterTypes.length +
" arguments, but only bound " + numBound + " (JoinPointMatch " +
(jpMatch == null ? "was NOT" : "WAS") + " bound in invocation)");
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;
@@ -619,23 +599,20 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
* @return the invocation result
* @throws Throwable in case of invocation failure
*/
protected Object invokeAdviceMethod(
@Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex)
throws Throwable {
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, @Nullable JoinPointMatch jpMatch,
@Nullable Object returnValue, @Nullable Throwable t) throws Throwable {
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.getParameterCount() == 0) {
if (this.aspectJAdviceMethod.getParameterTypes().length == 0) {
actualArgs = null;
}
try {
@@ -663,7 +640,6 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
/**
* Get the current join point match at the join point we are being dispatched on.
*/
@Nullable
protected JoinPointMatch getJoinPointMatch() {
MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
if (!(mi instanceof ProxyMethodInvocation)) {
@@ -678,10 +654,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
// '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.
@Nullable
protected JoinPointMatch getJoinPointMatch(ProxyMethodInvocation pmi) {
String expression = this.pointcut.getExpression();
return (expression != null ? (JoinPointMatch) pmi.getUserAttribute(expression) : null);
return (JoinPointMatch) pmi.getUserAttribute(this.pointcut.getExpression());
}
@@ -691,16 +665,6 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
"aspect name '" + this.aspectName + "'";
}
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
inputStream.defaultReadObject();
try {
this.aspectJAdviceMethod = this.declaringClass.getMethod(this.methodName, this.parameterTypes);
}
catch (NoSuchMethodException ex) {
throw new IllegalStateException("Failed to find advice method on deserialization", ex);
}
}
/**
* MethodMatcher that excludes the specified advice method.
@@ -715,7 +679,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
@Override
public boolean matches(Method method, @Nullable Class<?> targetClass) {
public boolean matches(Method method, Class<?> targetClass) {
return !this.adviceMethod.equals(method);
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -17,7 +17,6 @@
package org.springframework.aop.aspectj;
import org.springframework.core.Ordered;
import org.springframework.lang.Nullable;
/**
* Interface implemented to provide an instance of an AspectJ aspect.
@@ -41,10 +40,8 @@ public interface AspectInstanceFactory extends Ordered {
/**
* Expose the aspect class loader that this factory uses.
* @return the aspect class loader (or {@code null} for the bootstrap loader)
* @see org.springframework.util.ClassUtils#getDefaultClassLoader()
* @return the aspect class loader (never {@code null})
*/
@Nullable
ClassLoader getAspectClassLoader();
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -28,9 +28,7 @@ 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.lang.Nullable;
import org.springframework.util.StringUtils;
/**
@@ -114,7 +112,6 @@ import org.springframework.util.StringUtils;
* returning {@code null} in the case that the parameter names cannot be discovered.
*
* @author Adrian Colyer
* @author Juergen Hoeller
* @since 2.0
*/
public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscoverer {
@@ -132,8 +129,8 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
private static final int STEP_REFERENCE_PCUT_BINDING = 7;
private static final int STEP_FINISHED = 8;
private static final Set<String> singleValuedAnnotationPcds = new HashSet<>();
private static final Set<String> nonReferencePointcutTokens = new HashSet<>();
private static final Set<String> singleValuedAnnotationPcds = new HashSet<String>();
private static final Set<String> nonReferencePointcutTokens = new HashSet<String>();
static {
@@ -156,23 +153,26 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
}
/** The pointcut expression associated with the advice, as a simple String */
@Nullable
private String pointcutExpression;
private boolean raiseExceptions;
/** If the advice is afterReturning, and binds the return value, this is the parameter name used */
@Nullable
/**
* 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 */
@Nullable
/**
* If the advice is afterThrowing, and binds the thrown value, this is the parameter name used.
*/
private String throwingName;
private Class<?>[] argumentTypes = new Class<?>[0];
/**
* The pointcut expression associated with the advice, as a simple String.
*/
private String pointcutExpression;
private String[] parameterNameBindings = new String[0];
private Class<?>[] argumentTypes;
private String[] parameterNameBindings;
private int numberOfRemainingUnboundArguments;
@@ -181,11 +181,10 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
* Create a new discoverer that attempts to discover parameter names
* from the given pointcut expression.
*/
public AspectJAdviceParameterNameDiscoverer(@Nullable String pointcutExpression) {
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.
@@ -200,7 +199,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
* returning variable name must be specified.
* @param returningName the name of the returning variable
*/
public void setReturningName(@Nullable String returningName) {
public void setReturningName(String returningName) {
this.returningName = returningName;
}
@@ -209,11 +208,10 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
* throwing variable name must be specified.
* @param throwingName the name of the throwing variable
*/
public void setThrowingName(@Nullable String throwingName) {
public void setThrowingName(String throwingName) {
this.throwingName = throwingName;
}
/**
* Deduce the parameter names for an advice method.
* <p>See the {@link AspectJAdviceParameterNameDiscoverer class level javadoc}
@@ -222,7 +220,6 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
* @return the parameter names
*/
@Override
@Nullable
public String[] getParameterNames(Method method) {
this.argumentTypes = method.getParameterTypes();
this.numberOfRemainingUnboundArguments = this.argumentTypes.length;
@@ -311,7 +308,6 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
* {@link #setRaiseExceptions(boolean) raiseExceptions} has been set to {@code true}
*/
@Override
@Nullable
public String[] getParameterNames(Constructor<?> ctor) {
if (this.raiseExceptions) {
throw new UnsupportedOperationException("An advice method can never be a constructor");
@@ -417,11 +413,11 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
* <p>Some more support from AspectJ in doing this exercise would be nice... :)
*/
private void maybeBindAnnotationsFromPointcutExpression() {
List<String> varNames = new ArrayList<>();
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('(');
int firstParenIndex = toMatch.indexOf("(");
if (firstParenIndex != -1) {
toMatch = toMatch.substring(0, firstParenIndex);
}
@@ -476,9 +472,8 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
/*
* If the token starts meets Java identifier conventions, it's in.
*/
@Nullable
private String maybeExtractVariableName(@Nullable String candidateToken) {
if (!StringUtils.hasLength(candidateToken)) {
private String maybeExtractVariableName(String candidateToken) {
if (candidateToken == null || candidateToken.equals("")) {
return null;
}
if (Character.isJavaIdentifierStart(candidateToken.charAt(0)) &&
@@ -500,7 +495,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
* Given an args pointcut body (could be {@code args} or {@code at_args}),
* add any candidate variable names to the given list.
*/
private void maybeExtractVariableNamesFromArgs(@Nullable String argsSpec, List<String> varNames) {
private void maybeExtractVariableNamesFromArgs(String argsSpec, List<String> varNames) {
if (argsSpec == null) {
return;
}
@@ -524,7 +519,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
+ " unbound args at this(),target(),args() binding stage, with no way to determine between them");
}
List<String> varNames = new ArrayList<>();
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") ||
@@ -541,7 +536,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
else if (tokens[i].equals("args") || tokens[i].startsWith("args(")) {
PointcutBody body = getPointcutBody(tokens, i);
i += body.numTokensConsumed;
List<String> candidateVarNames = new ArrayList<>();
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...
@@ -575,14 +570,14 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
+ " unbound args at reference pointcut binding stage, with no way to determine between them");
}
List<String> varNames = new ArrayList<>();
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('(');
int firstParenIndex = toMatch.indexOf("(");
if (firstParenIndex != -1) {
toMatch = toMatch.substring(0, firstParenIndex);
}
@@ -656,7 +651,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
}
if (tokens[currentIndex].endsWith(")")) {
sb.append(tokens[currentIndex], 0, tokens[currentIndex].length() - 1);
sb.append(tokens[currentIndex].substring(0, tokens[currentIndex].length() - 1));
return new PointcutBody(numTokensConsumed, sb.toString().trim());
}
@@ -687,7 +682,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
}
if (numUnboundPrimitives == 1) {
// Look for arg variable and bind it if we find exactly one...
List<String> varNames = new ArrayList<>();
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(")) {
@@ -781,10 +776,9 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
private int numTokensConsumed;
@Nullable
private String text;
public PointcutBody(int tokens, @Nullable String text) {
public PointcutBody(int tokens, String text) {
this.numTokensConsumed = tokens;
this.text = text;
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,7 +16,6 @@
package org.springframework.aop.aspectj;
import java.io.Serializable;
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInterceptor;
@@ -30,9 +29,7 @@ import org.springframework.aop.AfterAdvice;
* @author Rod Johnson
* @since 2.0
*/
@SuppressWarnings("serial")
public class AspectJAfterAdvice extends AbstractAspectJAdvice
implements MethodInterceptor, AfterAdvice, Serializable {
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice {
public AspectJAfterAdvice(
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
@@ -40,7 +37,6 @@ public class AspectJAfterAdvice extends AbstractAspectJAdvice
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,13 +16,11 @@
package org.springframework.aop.aspectj;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import org.springframework.aop.AfterAdvice;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.TypeUtils;
@@ -34,9 +32,7 @@ import org.springframework.util.TypeUtils;
* @author Ramnivas Laddad
* @since 2.0
*/
@SuppressWarnings("serial")
public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
implements AfterReturningAdvice, AfterAdvice, Serializable {
public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice implements AfterReturningAdvice, AfterAdvice {
public AspectJAfterReturningAdvice(
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
@@ -44,7 +40,6 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public boolean isBeforeAdvice() {
return false;
@@ -61,13 +56,12 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
}
@Override
public void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable {
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
@@ -76,7 +70,7 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
* @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, @Nullable Object returnValue) {
private boolean shouldInvokeOnReturnValueOf(Method method, Object returnValue) {
Class<?> type = getDiscoveredReturningType();
Type genericType = getDiscoveredReturningGenericType();
// If we aren't dealing with a raw type, check if generic parameters are assignable.
@@ -95,14 +89,14 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
* @param returnValue the return value of the target method
* @return whether to invoke the advice method for the given return value and type
*/
private boolean matchesReturnValue(Class<?> type, Method method, @Nullable Object returnValue) {
private boolean matchesReturnValue(Class<?> type, Method method, Object returnValue) {
if (returnValue != null) {
return ClassUtils.isAssignableValue(type, returnValue);
}
else if (Object.class == type && void.class == method.getReturnType()) {
else if (type.equals(Object.class) && method.getReturnType().equals(void.class)) {
return true;
}
else {
else{
return ClassUtils.isAssignable(type, method.getReturnType());
}
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,7 +16,6 @@
package org.springframework.aop.aspectj;
import java.io.Serializable;
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInterceptor;
@@ -30,9 +29,7 @@ import org.springframework.aop.AfterAdvice;
* @author Rod Johnson
* @since 2.0
*/
@SuppressWarnings("serial")
public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
implements MethodInterceptor, AfterAdvice, Serializable {
public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice {
public AspectJAfterThrowingAdvice(
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
@@ -40,7 +37,6 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public boolean isBeforeAdvice() {
return false;
@@ -61,11 +57,11 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
try {
return mi.proceed();
}
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
catch (Throwable t) {
if (shouldInvokeOnThrowing(t)) {
invokeAdviceMethod(getJoinPointMatch(), null, t);
}
throw ex;
throw t;
}
}
@@ -73,8 +69,8 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
* 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 ex) {
return getDiscoveredThrowingType().isAssignableFrom(ex.getClass());
private boolean shouldInvokeOnThrowing(Throwable t) {
return getDiscoveredThrowingType().isAssignableFrom(t.getClass());
}
}
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -21,7 +21,6 @@ import org.aopalliance.aop.Advice;
import org.springframework.aop.Advisor;
import org.springframework.aop.AfterAdvice;
import org.springframework.aop.BeforeAdvice;
import org.springframework.lang.Nullable;
/**
* Utility methods for dealing with AspectJ advisors.
@@ -59,7 +58,6 @@ public abstract class AspectJAopUtils {
* If neither the advisor nor the advice have precedence information, this method
* will return {@code null}.
*/
@Nullable
public static AspectJPrecedenceInformation getAspectJPrecedenceInformationFor(Advisor anAdvisor) {
if (anAdvisor instanceof AspectJPrecedenceInformation) {
return (AspectJPrecedenceInformation) anAdvisor;
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,7 +16,6 @@
package org.springframework.aop.aspectj;
import java.io.Serializable;
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInterceptor;
@@ -34,8 +33,7 @@ import org.springframework.aop.ProxyMethodInvocation;
* @author Juergen Hoeller
* @since 2.0
*/
@SuppressWarnings("serial")
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor {
public AspectJAroundAdvice(
Method aspectJAroundAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
@@ -43,7 +41,6 @@ public class AspectJAroundAdvice extends AbstractAspectJAdvice implements Method
super(aspectJAroundAdviceMethod, pointcut, aif);
}
@Override
public boolean isBeforeAdvice() {
return false;
@@ -59,6 +56,7 @@ public class AspectJAroundAdvice extends AbstractAspectJAdvice implements Method
return true;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -19,8 +19,6 @@ package org.springframework.aop.aspectj;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@@ -29,6 +27,7 @@ import java.util.concurrent.ConcurrentHashMap;
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.ReflectionWorldException;
import org.aspectj.weaver.reflect.ShadowMatchImpl;
@@ -55,10 +54,7 @@ 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.beans.factory.annotation.BeanFactoryAnnotationUtils;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -85,7 +81,7 @@ import org.springframework.util.StringUtils;
public class AspectJExpressionPointcut extends AbstractExpressionPointcut
implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware {
private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<>();
private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<PointcutPrimitive>();
static {
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
@@ -103,23 +99,19 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
private static final Log logger = LogFactory.getLog(AspectJExpressionPointcut.class);
@Nullable
private Class<?> pointcutDeclarationScope;
private String[] pointcutParameterNames = new String[0];
private Class<?>[] pointcutParameterTypes = new Class<?>[0];
@Nullable
private BeanFactory beanFactory;
@Nullable
private transient ClassLoader pointcutClassLoader;
@Nullable
private transient PointcutExpression pointcutExpression;
private transient Map<Method, ShadowMatch> shadowMatchCache = new ConcurrentHashMap<>(32);
private transient Map<Method, ShadowMatch> shadowMatchCache = new ConcurrentHashMap<Method, ShadowMatch>(32);
/**
@@ -174,13 +166,13 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
@Override
public ClassFilter getClassFilter() {
obtainPointcutExpression();
checkReadyToMatch();
return this;
}
@Override
public MethodMatcher getMethodMatcher() {
obtainPointcutExpression();
checkReadyToMatch();
return this;
}
@@ -189,59 +181,41 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
* Check whether this pointcut is ready to match,
* lazily building the underlying AspectJ pointcut expression.
*/
private PointcutExpression obtainPointcutExpression() {
private void checkReadyToMatch() {
if (getExpression() == null) {
throw new IllegalStateException("Must set property 'expression' before attempting to match");
}
if (this.pointcutExpression == null) {
this.pointcutClassLoader = determinePointcutClassLoader();
this.pointcutClassLoader = (this.beanFactory instanceof ConfigurableBeanFactory ?
((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() :
ClassUtils.getDefaultClassLoader());
this.pointcutExpression = buildPointcutExpression(this.pointcutClassLoader);
}
return this.pointcutExpression;
}
/**
* Determine the ClassLoader to use for pointcut evaluation.
*/
@Nullable
private ClassLoader determinePointcutClassLoader() {
if (this.beanFactory instanceof ConfigurableBeanFactory) {
return ((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader();
}
if (this.pointcutDeclarationScope != null) {
return this.pointcutDeclarationScope.getClassLoader();
}
return ClassUtils.getDefaultClassLoader();
}
/**
* Build the underlying AspectJ pointcut expression.
*/
private PointcutExpression buildPointcutExpression(@Nullable ClassLoader classLoader) {
private PointcutExpression buildPointcutExpression(ClassLoader classLoader) {
PointcutParser parser = initializePointcutParser(classLoader);
PointcutParameter[] pointcutParameters = new PointcutParameter[this.pointcutParameterNames.length];
for (int i = 0; i < pointcutParameters.length; i++) {
pointcutParameters[i] = parser.createPointcutParameter(
this.pointcutParameterNames[i], this.pointcutParameterTypes[i]);
}
return parser.parsePointcutExpression(replaceBooleanOperators(resolveExpression()),
return parser.parsePointcutExpression(
replaceBooleanOperators(getExpression()),
this.pointcutDeclarationScope, pointcutParameters);
}
private String resolveExpression() {
String expression = getExpression();
Assert.state(expression != null, "No expression set");
return expression;
}
/**
* Initialize the underlying AspectJ pointcut parser.
*/
private PointcutParser initializePointcutParser(@Nullable ClassLoader classLoader) {
private PointcutParser initializePointcutParser(ClassLoader cl) {
PointcutParser parser = PointcutParser
.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(
SUPPORTED_PRIMITIVES, classLoader);
parser.registerPointcutDesignatorHandler(new BeanPointcutDesignatorHandler());
SUPPORTED_PRIMITIVES, cl);
parser.registerPointcutDesignatorHandler(new BeanNamePointcutDesignatorHandler());
return parser;
}
@@ -264,15 +238,16 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
* Return the underlying AspectJ pointcut expression.
*/
public PointcutExpression getPointcutExpression() {
return obtainPointcutExpression();
checkReadyToMatch();
return this.pointcutExpression;
}
@Override
public boolean matches(Class<?> targetClass) {
PointcutExpression pointcutExpression = obtainPointcutExpression();
checkReadyToMatch();
try {
try {
return pointcutExpression.couldMatchJoinPointsInType(targetClass);
return this.pointcutExpression.couldMatchJoinPointsInType(targetClass);
}
catch (ReflectionWorldException ex) {
logger.debug("PointcutExpression matching rejected target class - trying fallback expression", ex);
@@ -283,16 +258,17 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
}
}
}
catch (Throwable ex) {
catch (BCException ex) {
logger.debug("PointcutExpression matching rejected target class", ex);
}
return false;
}
@Override
public boolean matches(Method method, @Nullable Class<?> targetClass, boolean hasIntroductions) {
obtainPointcutExpression();
ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
public boolean matches(Method method, Class<?> targetClass, boolean beanHasIntroductions) {
checkReadyToMatch();
Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
ShadowMatch shadowMatch = getShadowMatch(targetMethod, method);
// Special handling for this, target, @this, @target, @annotation
// in Spring - we can optimize since we know we have exactly this class,
@@ -305,7 +281,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
}
else {
// the maybe case
if (hasIntroductions) {
if (beanHasIntroductions) {
return true;
}
// A match test returned maybe - if there are any subtype sensitive variables
@@ -313,25 +289,26 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
// we say this is not a match as in Spring there will never be a different
// runtime subtype.
RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch);
return (!walker.testsSubtypeSensitiveVars() ||
(targetClass != null && walker.testTargetInstanceOfResidue(targetClass)));
return (!walker.testsSubtypeSensitiveVars() || walker.testTargetInstanceOfResidue(targetClass));
}
}
@Override
public boolean matches(Method method, @Nullable Class<?> targetClass) {
public boolean matches(Method method, Class<?> targetClass) {
return matches(method, targetClass, false);
}
@Override
public boolean isRuntime() {
return obtainPointcutExpression().mayNeedDynamicTest();
checkReadyToMatch();
return this.pointcutExpression.mayNeedDynamicTest();
}
@Override
public boolean matches(Method method, @Nullable Class<?> targetClass, Object... args) {
obtainPointcutExpression();
ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
checkReadyToMatch();
ShadowMatch shadowMatch = getShadowMatch(AopUtils.getMostSpecificMethod(method, targetClass), method);
ShadowMatch originalShadowMatch = getShadowMatch(method, method);
// Bind Spring AOP proxy to AspectJ "this" and Spring AOP target to AspectJ target,
// consistent with return of MethodInvocationProceedingJoinPoint
@@ -349,44 +326,32 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
}
catch (IllegalStateException ex) {
// No current invocation...
if (logger.isDebugEnabled()) {
logger.debug("Could not access current invocation - matching with limited context: " + ex);
}
// TODO: Should we really proceed here?
logger.debug("Couldn't access current invocation - matching with limited context: " + ex);
}
try {
JoinPointMatch joinPointMatch = shadowMatch.matchesJoinPoint(thisObject, targetObject, args);
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 && thisObject != null) { // there is a current invocation
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(getShadowMatch(method, method));
if (!originalMethodResidueTest.testThisInstanceOfResidue(thisObject.getClass())) {
return false;
}
if (joinPointMatch.matches()) {
bindParameters(pmi, joinPointMatch);
}
/*
* 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 = getRuntimeTestWalker(originalShadowMatch);
if (!originalMethodResidueTest.testThisInstanceOfResidue(thisObject.getClass())) {
return false;
}
return joinPointMatch.matches();
}
catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to evaluate join point for arguments " + Arrays.asList(args) +
" - falling back to non-match", ex);
if (joinPointMatch.matches()) {
bindParameters(pmi, joinPointMatch);
}
return false;
}
return joinPointMatch.matches();
}
@Nullable
protected String getCurrentProxiedBeanName() {
return ProxyCreationContext.getCurrentProxiedBeanName();
}
@@ -395,7 +360,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
/**
* Get a new pointcut expression based on a target class's loader rather than the default.
*/
@Nullable
private PointcutExpression getFallbackPointcutExpression(Class<?> targetClass) {
try {
ClassLoader classLoader = targetClass.getClassLoader();
@@ -423,29 +387,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
// '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(resolveExpression(), jpm);
}
private ShadowMatch getTargetShadowMatch(Method method, @Nullable Class<?> targetClass) {
Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
if (targetClass != null && targetMethod.getDeclaringClass().isInterface()) {
// Try to build the most specific interface possible for inherited methods to be
// considered for sub-interface matches as well, in particular for proxy classes.
// Note: AspectJ is only going to take Method.getDeclaringClass() into account.
Set<Class<?>> ifcs = ClassUtils.getAllInterfacesForClassAsSet(targetClass);
if (ifcs.size() > 1) {
try {
Class<?> compositeInterface = ClassUtils.createCompositeInterface(
ClassUtils.toClassArray(ifcs), targetClass.getClassLoader());
targetMethod = ClassUtils.getMostSpecificMethod(targetMethod, compositeInterface);
}
catch (IllegalArgumentException ex) {
// Implemented interfaces probably expose conflicting method signatures...
// Proceed with original target method.
}
}
}
return getShadowMatch(targetMethod, method);
invocation.setUserAttribute(getExpression(), jpm);
}
private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
@@ -455,54 +397,43 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
synchronized (this.shadowMatchCache) {
// Not found - now check again with full lock...
PointcutExpression fallbackExpression = null;
Method methodToMatch = targetMethod;
shadowMatch = this.shadowMatchCache.get(targetMethod);
if (shadowMatch == null) {
Method methodToMatch = targetMethod;
try {
shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
}
catch (ReflectionWorldException ex) {
// Failed to introspect target method, probably because it has been loaded
// in a special ClassLoader. Let's try the declaring ClassLoader instead...
try {
shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);
fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
if (fallbackExpression != null) {
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
}
}
catch (ReflectionWorldException ex) {
// Failed to introspect target method, probably because it has been loaded
// in a special ClassLoader. Let's try the declaring ClassLoader instead...
catch (ReflectionWorldException ex2) {
fallbackExpression = null;
}
}
if (shadowMatch == null && targetMethod != originalMethod) {
methodToMatch = originalMethod;
try {
shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
}
catch (ReflectionWorldException ex3) {
// Could neither introspect the target class nor the proxy class ->
// let's try the original method's declaring class before we give up...
try {
fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
if (fallbackExpression != null) {
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
}
}
catch (ReflectionWorldException ex2) {
catch (ReflectionWorldException ex4) {
fallbackExpression = null;
}
}
if (targetMethod != originalMethod && (shadowMatch == null ||
(shadowMatch.neverMatches() && Proxy.isProxyClass(targetMethod.getDeclaringClass())))) {
// Fall back to the plain original method in case of no resolvable match or a
// negative match on a proxy class (which doesn't carry any annotations on its
// redeclared methods).
methodToMatch = originalMethod;
try {
shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);
}
catch (ReflectionWorldException ex) {
// Could neither introspect the target class nor the proxy class ->
// let's try the original method's declaring class before we give up...
try {
fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
if (fallbackExpression != null) {
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
}
}
catch (ReflectionWorldException ex2) {
fallbackExpression = null;
}
}
}
}
catch (Throwable ex) {
// Possibly AspectJ 1.8.10 encountering an invalid signature
logger.debug("PointcutExpression matching rejected target method", ex);
fallbackExpression = null;
}
if (shadowMatch == null) {
shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null);
@@ -547,16 +478,18 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("AspectJExpressionPointcut: ");
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(", ");
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(")");
sb.append(" ");
if (getExpression() != null) {
sb.append(getExpression());
@@ -567,19 +500,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
return sb.toString();
}
//---------------------------------------------------------------------
// Serialization support
//---------------------------------------------------------------------
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Rely on default serialization, just initialize state after deserialization.
ois.defaultReadObject();
// Initialize transient fields.
// pointcutExpression will be initialized lazily by checkReadyToMatch()
this.shadowMatchCache = new ConcurrentHashMap<>(32);
}
/**
* Handler for the Spring-specific {@code bean()} pointcut designator
@@ -589,7 +509,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
* automatically by examining a thread local variable and therefore a matching
* context need not be set on the pointcut.
*/
private class BeanPointcutDesignatorHandler implements PointcutDesignatorHandler {
private class BeanNamePointcutDesignatorHandler implements PointcutDesignatorHandler {
private static final String BEAN_DESIGNATOR_NAME = "bean";
@@ -600,7 +520,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
@Override
public ContextBasedMatcher parse(String expression) {
return new BeanContextMatcher(expression);
return new BeanNameContextMatcher(expression);
}
}
@@ -612,11 +532,11 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
* For static match tests, this matcher abstains to allow the overall
* pointcut to match even when negation is used with the bean() pointcut.
*/
private class BeanContextMatcher implements ContextBasedMatcher {
private class BeanNameContextMatcher implements ContextBasedMatcher {
private final NamePattern expressionPattern;
public BeanContextMatcher(String expression) {
public BeanNameContextMatcher(String expression) {
this.expressionPattern = new NamePattern(expression);
}
@@ -649,7 +569,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
return false;
}
private FuzzyBoolean contextMatch(@Nullable Class<?> targetType) {
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
@@ -661,21 +581,45 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
if (targetType != null) {
boolean isFactory = FactoryBean.class.isAssignableFrom(targetType);
return FuzzyBoolean.fromBoolean(
matchesBean(isFactory ? BeanFactory.FACTORY_BEAN_PREFIX + advisedBeanName : advisedBeanName));
matchesBeanName(isFactory ? BeanFactory.FACTORY_BEAN_PREFIX + advisedBeanName : advisedBeanName));
}
else {
return FuzzyBoolean.fromBoolean(matchesBean(advisedBeanName) ||
matchesBean(BeanFactory.FACTORY_BEAN_PREFIX + advisedBeanName));
return FuzzyBoolean.fromBoolean(matchesBeanName(advisedBeanName) ||
matchesBeanName(BeanFactory.FACTORY_BEAN_PREFIX + advisedBeanName));
}
}
private boolean matchesBean(String advisedBeanName) {
return BeanFactoryAnnotationUtils.isQualifierMatch(
this.expressionPattern::matches, advisedBeanName, beanFactory);
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;
}
}
//---------------------------------------------------------------------
// Serialization support
//---------------------------------------------------------------------
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Rely on default serialization, just initialize state after deserialization.
ois.defaultReadObject();
// Initialize transient fields.
// pointcutExpression will be initialized lazily by checkReadyToMatch()
this.shadowMatchCache = new ConcurrentHashMap<Method, ShadowMatch>(32);
}
private static class DefensiveShadowMatch implements ShadowMatch {
private final ShadowMatch primary;
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -18,9 +18,6 @@ package org.springframework.aop.aspectj;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.AbstractGenericPointcutAdvisor;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.lang.Nullable;
/**
* Spring AOP Advisor that can be used for any AspectJ pointcut expression.
@@ -29,45 +26,38 @@ import org.springframework.lang.Nullable;
* @since 2.0
*/
@SuppressWarnings("serial")
public class AspectJExpressionPointcutAdvisor extends AbstractGenericPointcutAdvisor implements BeanFactoryAware {
public class AspectJExpressionPointcutAdvisor extends AbstractGenericPointcutAdvisor {
private final AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
public void setExpression(@Nullable String expression) {
this.pointcut.setExpression(expression);
}
@Nullable
public String getExpression() {
return this.pointcut.getExpression();
}
public void setLocation(@Nullable String location) {
this.pointcut.setLocation(location);
}
@Nullable
public String getLocation() {
return this.pointcut.getLocation();
}
public void setParameterNames(String... names) {
this.pointcut.setParameterNames(names);
}
public void setParameterTypes(Class<?>... types) {
this.pointcut.setParameterTypes(types);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.pointcut.setBeanFactory(beanFactory);
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
public void setExpression(String expression) {
this.pointcut.setExpression(expression);
}
public String getExpression() {
return this.pointcut.getExpression();
}
public void setLocation(String location) {
this.pointcut.setLocation(location);
}
public String getLocation() {
return this.pointcut.getLocation();
}
public void setParameterTypes(Class<?>[] types) {
this.pointcut.setParameterTypes(types);
}
public void setParameterNames(String... names) {
this.pointcut.setParameterNames(names);
}
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,11 +16,9 @@
package org.springframework.aop.aspectj;
import java.io.Serializable;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.lang.Nullable;
/**
* Spring AOP advice that wraps an AspectJ before method.
@@ -29,8 +27,7 @@ import org.springframework.lang.Nullable;
* @author Adrian Colyer
* @since 2.0
*/
@SuppressWarnings("serial")
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable {
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice {
public AspectJMethodBeforeAdvice(
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
@@ -38,9 +35,8 @@ public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
public void before(Method method, Object[] args, Object target) throws Throwable {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -21,8 +21,8 @@ import org.aopalliance.aop.Advice;
import org.springframework.aop.Pointcut;
import org.springframework.aop.PointcutAdvisor;
import org.springframework.core.Ordered;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* AspectJPointcutAdvisor that adapts an {@link AbstractAspectJAdvice}
@@ -38,7 +38,6 @@ public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
private final Pointcut pointcut;
@Nullable
private Integer order;
@@ -52,20 +51,10 @@ public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
this.pointcut = advice.buildSafePointcut();
}
public void setOrder(int order) {
this.order = order;
}
@Override
public int getOrder() {
if (this.order != null) {
return this.order;
}
else {
return this.advice.getOrder();
}
}
@Override
public boolean isPerInstance() {
@@ -82,13 +71,14 @@ public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
return this.pointcut;
}
/**
* Return the name of the aspect (bean) in which the advice was declared.
* @since 4.3.15
* @see AbstractAspectJAdvice#getAspectName()
*/
public String getAspectName() {
return this.advice.getAspectName();
@Override
public int getOrder() {
if (this.order != null) {
return this.order;
}
else {
return this.advice.getOrder();
}
}
@@ -101,12 +91,12 @@ public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
return false;
}
AspectJPointcutAdvisor otherAdvisor = (AspectJPointcutAdvisor) other;
return this.advice.equals(otherAdvisor.advice);
return (ObjectUtils.nullSafeEquals(this.advice, otherAdvisor.advice));
}
@Override
public int hashCode() {
return AspectJPointcutAdvisor.class.hashCode() * 29 + this.advice.hashCode();
return AspectJPointcutAdvisor.class.hashCode();
}
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -36,12 +36,12 @@ public interface AspectJPrecedenceInformation extends Ordered {
// its advice for aspects with non-singleton instantiation models.
/**
* Return the name of the aspect (bean) in which the advice was declared.
* The name of the aspect (bean) in which the advice was declared.
*/
String getAspectName();
/**
* Return the declaration order of the advice member within the aspect.
* The declaration order of the advice member within the aspect.
*/
int getDeclarationOrder();
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -20,7 +20,6 @@ import org.aopalliance.aop.Advice;
import org.springframework.aop.ClassFilter;
import org.springframework.aop.IntroductionAdvisor;
import org.springframework.aop.IntroductionInterceptor;
import org.springframework.aop.support.ClassFilters;
import org.springframework.aop.support.DelegatePerTargetObjectIntroductionInterceptor;
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
@@ -35,12 +34,12 @@ import org.springframework.aop.support.DelegatingIntroductionInterceptor;
*/
public class DeclareParentsAdvisor implements IntroductionAdvisor {
private final Advice advice;
private final Class<?> introducedInterface;
private final ClassFilter typePatternClassFilter;
private final Advice advice;
/**
* Create a new advisor for this DeclareParents field.
@@ -49,8 +48,8 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor {
* @param defaultImpl the default implementation class
*/
public DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Class<?> defaultImpl) {
this(interfaceType, typePattern,
new DelegatePerTargetObjectIntroductionInterceptor(defaultImpl, interfaceType));
this(interfaceType, typePattern, defaultImpl,
new DelegatePerTargetObjectIntroductionInterceptor(defaultImpl, interfaceType));
}
/**
@@ -60,24 +59,32 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor {
* @param delegateRef the delegate implementation object
*/
public DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Object delegateRef) {
this(interfaceType, typePattern, new DelegatingIntroductionInterceptor(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 use of final fields)
* (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 interceptor the delegation advice as {@link IntroductionInterceptor}
* @param implementationClass implementation class
* @param advice delegation advice
*/
private DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, IntroductionInterceptor interceptor) {
this.advice = interceptor;
private DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Class<?> implementationClass, Advice advice) {
this.introducedInterface = interfaceType;
ClassFilter typePatternFilter = new TypePatternClassFilter(typePattern);
// Excludes methods implemented.
ClassFilter typePatternFilter = new TypePatternClassFilter(typePattern);
ClassFilter exclusion = (clazz -> !introducedInterface.isAssignableFrom(clazz));
ClassFilter exclusion = new ClassFilter() {
@Override
public boolean matches(Class<?> clazz) {
return !(introducedInterface.isAssignableFrom(clazz));
}
};
this.typePatternClassFilter = ClassFilters.intersection(typePatternFilter, exclusion);
this.advice = advice;
}
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -29,19 +29,20 @@ import org.aspectj.runtime.internal.AroundClosure;
import org.springframework.aop.ProxyMethodInvocation;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* An implementation of the AspectJ {@link ProceedingJoinPoint} interface
* wrapping an AOP Alliance {@link org.aopalliance.intercept.MethodInvocation}.
* Implementation of AspectJ ProceedingJoinPoint interface
* wrapping an AOP Alliance MethodInvocation.
*
* <p><b>Note</b>: The {@code getThis()} method returns the current Spring AOP proxy.
* <p><b>Note</b>: the {@code getThis()} method returns the current Spring AOP proxy.
* The {@code getTarget()} method returns the current Spring AOP target (which may be
* {@code null} if there is no target instance) as a plain POJO without any advice.
* <b>If you want to call the object and have the advice take effect, use {@code getThis()}.</b>
* A common example is casting the object to an introduced interface in the implementation of
* an introduction. There is no such distinction between target and proxy in AspectJ itself.
* {@code null} 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()}.</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
@@ -55,15 +56,12 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
private final ProxyMethodInvocation methodInvocation;
@Nullable
private Object[] args;
private Object[] defensiveCopyOfArgs;
/** Lazily initialized signature object */
@Nullable
private Signature signature;
/** Lazily initialized source location object */
@Nullable
private SourceLocation sourceLocation;
@@ -77,7 +75,6 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
this.methodInvocation = methodInvocation;
}
@Override
public void set$AroundClosure(AroundClosure aroundClosure) {
throw new UnsupportedOperationException();
@@ -112,17 +109,18 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
* Returns the Spring AOP target. May be {@code null} if there is no target.
*/
@Override
@Nullable
public Object getTarget() {
return this.methodInvocation.getThis();
}
@Override
public Object[] getArgs() {
if (this.args == null) {
this.args = this.methodInvocation.getArguments().clone();
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.args;
return this.defensiveCopyOfArgs;
}
@Override
@@ -130,7 +128,7 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
if (this.signature == null) {
this.signature = new MethodSignatureImpl();
}
return this.signature;
return signature;
}
@Override
@@ -178,7 +176,6 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
*/
private class MethodSignatureImpl implements MethodSignature {
@Nullable
private volatile String[] parameterNames;
@Override
@@ -217,14 +214,11 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
}
@Override
@Nullable
public String[] getParameterNames() {
String[] parameterNames = this.parameterNames;
if (parameterNames == null) {
parameterNames = parameterNameDiscoverer.getParameterNames(getMethod());
this.parameterNames = parameterNames;
if (this.parameterNames == null) {
this.parameterNames = parameterNameDiscoverer.getParameterNames(getMethod());
}
return parameterNames;
return this.parameterNames;
}
@Override
@@ -249,7 +243,6 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
private String toString(boolean includeModifier, boolean includeReturnTypeAndArgs,
boolean useLongReturnAndArgumentTypeName, boolean useLongTypeName) {
StringBuilder sb = new StringBuilder();
if (includeModifier) {
sb.append(Modifier.toString(getModifiers()));
@@ -269,9 +262,8 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
return sb.toString();
}
private void appendTypes(StringBuilder sb, Class<?>[] types, boolean includeArgs,
boolean useLongReturnAndArgumentTypeName) {
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);
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -37,7 +37,6 @@ import org.aspectj.weaver.reflect.ReflectionVar;
import org.aspectj.weaver.reflect.ShadowMatchImpl;
import org.aspectj.weaver.tools.ShadowMatch;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
@@ -51,7 +50,7 @@ import org.springframework.util.ReflectionUtils;
* migrate to {@code ShadowMatch.getVariablesInvolvedInRuntimeTest()}
* or some similar operation.
*
* <p>See <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=151593"/>Bug 151593</a>
* <p>See <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=151593"/>.
*
* @author Adrian Colyer
* @author Ramnivas Laddad
@@ -79,7 +78,6 @@ class RuntimeTestWalker {
}
@Nullable
private final Test runtimeTest;
@@ -175,7 +173,7 @@ class RuntimeTestWalker {
}
private abstract static class InstanceOfResidueTestVisitor extends TestVisitorAdapter {
private static abstract class InstanceOfResidueTestVisitor extends TestVisitorAdapter {
private final Class<?> matchClass;
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,13 +16,9 @@
package org.springframework.aop.aspectj;
import java.lang.reflect.InvocationTargetException;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.core.Ordered;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
/**
* Implementation of {@link AspectInstanceFactory} that creates a new instance
@@ -45,7 +41,6 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
this.aspectClass = aspectClass;
}
/**
* Return the specified aspect class (never {@code null}).
*/
@@ -53,31 +48,21 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
return this.aspectClass;
}
@Override
public final Object getAspectInstance() {
try {
return ReflectionUtils.accessibleConstructor(this.aspectClass).newInstance();
}
catch (NoSuchMethodException ex) {
throw new AopConfigException(
"No default constructor on aspect class: " + this.aspectClass.getName(), ex);
return this.aspectClass.newInstance();
}
catch (InstantiationException ex) {
throw new AopConfigException(
"Unable to instantiate aspect class: " + this.aspectClass.getName(), ex);
throw new AopConfigException("Unable to instantiate aspect class [" + this.aspectClass.getName() + "]", ex);
}
catch (IllegalAccessException ex) {
throw new AopConfigException(
"Could not access aspect constructor: " + this.aspectClass.getName(), ex);
}
catch (InvocationTargetException ex) {
throw new AopConfigException(
"Failed to invoke aspect constructor: " + this.aspectClass.getName(), ex.getTargetException());
throw new AopConfigException("Cannot access element class [" + this.aspectClass.getName() + "]", ex);
}
}
@Override
@Nullable
public ClassLoader getAspectClassLoader() {
return this.aspectClass.getClassLoader();
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,10 +16,7 @@
package org.springframework.aop.aspectj;
import java.io.Serializable;
import org.springframework.core.Ordered;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -32,8 +29,7 @@ import org.springframework.util.Assert;
* @since 2.0
* @see SimpleAspectInstanceFactory
*/
@SuppressWarnings("serial")
public class SingletonAspectInstanceFactory implements AspectInstanceFactory, Serializable {
public class SingletonAspectInstanceFactory implements AspectInstanceFactory {
private final Object aspectInstance;
@@ -54,7 +50,6 @@ public class SingletonAspectInstanceFactory implements AspectInstanceFactory, Se
}
@Override
@Nullable
public ClassLoader getAspectClassLoader() {
return this.aspectInstance.getClass().getClassLoader();
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -20,7 +20,6 @@ import org.aspectj.weaver.tools.PointcutParser;
import org.aspectj.weaver.tools.TypePatternMatcher;
import org.springframework.aop.ClassFilter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -28,14 +27,12 @@ import org.springframework.util.StringUtils;
* Spring AOP {@link ClassFilter} implementation using AspectJ type matching.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since 2.0
*/
public class TypePatternClassFilter implements ClassFilter {
private String typePattern = "";
private String typePattern;
@Nullable
private TypePatternMatcher aspectJTypePatternMatcher;
@@ -53,6 +50,8 @@ public class TypePatternClassFilter implements ClassFilter {
* 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} is {@code null}
* or is recognized as invalid
*/
public TypePatternClassFilter(String typePattern) {
setTypePattern(typePattern);
@@ -73,23 +72,21 @@ public class TypePatternClassFilter implements ClassFilter {
* 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} is {@code null}
* or is recognized as invalid
*/
public void setTypePattern(String typePattern) {
Assert.notNull(typePattern, "Type pattern must not be null");
Assert.notNull(typePattern);
this.typePattern = typePattern;
this.aspectJTypePatternMatcher =
PointcutParser.getPointcutParserSupportingAllPrimitivesAndUsingContextClassloaderForResolution().
parseTypePattern(replaceBooleanOperators(typePattern));
}
/**
* Return the AspectJ type pattern to match.
*/
public String getTypePattern() {
return this.typePattern;
return typePattern;
}
/**
* Should the pointcut apply to the given interface or target class?
* @param clazz candidate target class
@@ -98,7 +95,9 @@ public class TypePatternClassFilter implements ClassFilter {
*/
@Override
public boolean matches(Class<?> clazz) {
Assert.state(this.aspectJTypePatternMatcher != null, "No type pattern has been set");
if (this.aspectJTypePatternMatcher == null) {
throw new IllegalStateException("No 'typePattern' has been set via ctor/setter.");
}
return this.aspectJTypePatternMatcher.matches(clazz);
}
@@ -109,8 +108,9 @@ public class TypePatternClassFilter implements ClassFilter {
* <p>This method converts back to {@code &&} for the AspectJ pointcut parser.
*/
private String replaceBooleanOperators(String pcExpr) {
String result = StringUtils.replace(pcExpr," and "," && ");
result = StringUtils.replace(result, " or ", " || ");
return StringUtils.replace(result, " not ", " ! ");
pcExpr = StringUtils.replace(pcExpr," and "," && ");
pcExpr = StringUtils.replace(pcExpr, " or ", " || ");
pcExpr = StringUtils.replace(pcExpr, " not ", " ! ");
return pcExpr;
}
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -37,11 +37,11 @@ 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.annotation.AnnotationUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
/**
* Abstract base class for factories that can create Spring AOP Advisors
@@ -59,8 +59,33 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
private static final String AJC_MAGIC = "ajc$";
private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
/**
* Find and return the first AspectJ annotation on the given method
* (there <i>should</i> only be one anyway...)
*/
@SuppressWarnings("unchecked")
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
Class<?>[] classesToLookFor = new Class<?>[] {
Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
for (Class<?> c : classesToLookFor) {
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) 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 */
@@ -124,40 +149,54 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
}
/**
* Find and return the first AspectJ annotation on the given method
* (there <i>should</i> only be one anyway...).
* 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.
*/
@SuppressWarnings("unchecked")
@Nullable
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
protected AspectJExpressionPointcut createPointcutExpression(
Method annotatedMethod, Class<?> declarationScope, String[] pointcutParameterNames) {
@Nullable
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
A result = AnnotationUtils.findAnnotation(method, toLookFor);
if (result != null) {
return new AspectJAnnotation<>(result);
Class<?> [] pointcutParameterTypes = new Class<?>[0];
if (pointcutParameterNames != null) {
pointcutParameterTypes = extractPointcutParameterTypes(pointcutParameterNames,annotatedMethod);
}
else {
return null;
}
}
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(declarationScope,pointcutParameterNames,pointcutParameterTypes);
ajexp.setLocation(annotatedMethod.toString());
return ajexp;
}
/**
* Enum for AspectJ annotation types.
* @see AspectJAnnotation#getAnnotationType()
* 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)
*/
protected enum AspectJAnnotationType {
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;
}
AtPointcut, AtAround, AtBefore, AtAfter, AtAfterReturning, AtAfterThrowing
protected enum AspectJAnnotationType {
AtPointcut,
AtBefore,
AtAfter,
AtAfterReturning,
AtAfterThrowing,
AtAround
}
@@ -167,17 +206,18 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
*/
protected static class AspectJAnnotation<A extends Annotation> {
private static final String[] EXPRESSION_ATTRIBUTES = new String[] {"pointcut", "value"};
private static final String[] EXPRESSION_PROPERTIES = new String[] {"value", "pointcut"};
private static Map<Class<?>, AspectJAnnotationType> annotationTypeMap = new HashMap<>(8);
private static Map<Class<?>, AspectJAnnotationType> annotationTypes =
new HashMap<Class<?>, AspectJAnnotationType>();
static {
annotationTypeMap.put(Pointcut.class, AspectJAnnotationType.AtPointcut);
annotationTypeMap.put(Around.class, AspectJAnnotationType.AtAround);
annotationTypeMap.put(Before.class, AspectJAnnotationType.AtBefore);
annotationTypeMap.put(After.class, AspectJAnnotationType.AtAfter);
annotationTypeMap.put(AfterReturning.class, AspectJAnnotationType.AtAfterReturning);
annotationTypeMap.put(AfterThrowing.class, AspectJAnnotationType.AtAfterThrowing);
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;
@@ -191,35 +231,44 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
public AspectJAnnotation(A annotation) {
this.annotation = annotation;
this.annotationType = determineAnnotationType(annotation);
// 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.pointcutExpression = resolveExpression(annotation);
Object argNames = AnnotationUtils.getValue(annotation, "argNames");
this.argumentNames = (argNames instanceof String ? (String) argNames : "");
this.argumentNames = (String) annotation.getClass().getMethod("argNames").invoke(annotation);
}
catch (Exception ex) {
throw new IllegalArgumentException(annotation + " is not a valid AspectJ annotation", ex);
throw new IllegalArgumentException(annotation + " cannot be an AspectJ annotation", ex);
}
}
private AspectJAnnotationType determineAnnotationType(A annotation) {
AspectJAnnotationType type = annotationTypeMap.get(annotation.annotationType());
if (type != null) {
return type;
for (Class<?> type : annotationTypes.keySet()) {
if (type.isInstance(annotation)) {
return annotationTypes.get(type);
}
}
throw new IllegalStateException("Unknown annotation type: " + annotation);
throw new IllegalStateException("Unknown annotation type: " + annotation.toString());
}
private String resolveExpression(A annotation) {
for (String attributeName : EXPRESSION_ATTRIBUTES) {
Object val = AnnotationUtils.getValue(annotation, attributeName);
if (val instanceof String) {
String str = (String) val;
if (!str.isEmpty()) {
return str;
private String resolveExpression(A annotation) throws Exception {
String expression = null;
for (String methodName : EXPRESSION_PROPERTIES) {
Method method;
try {
method = annotation.getClass().getDeclaredMethod(methodName);
}
catch (NoSuchMethodException ex) {
method = null;
}
if (method != null) {
String candidate = (String) method.invoke(annotation);
if (StringUtils.hasText(candidate)) {
expression = candidate;
}
}
}
throw new IllegalStateException("Failed to resolve expression: " + annotation);
return expression;
}
public AspectJAnnotationType getAnnotationType() {
@@ -252,20 +301,19 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
private static class AspectJAnnotationParameterNameDiscoverer implements ParameterNameDiscoverer {
@Override
@Nullable
public String[] getParameterNames(Method method) {
if (method.getParameterCount() == 0) {
if (method.getParameterTypes().length == 0) {
return new String[0];
}
AspectJAnnotation<?> annotation = findAspectJAnnotationOnMethod(method);
if (annotation == null) {
return null;
}
StringTokenizer nameTokens = new StringTokenizer(annotation.getArgumentNames(), ",");
if (nameTokens.countTokens() > 0) {
String[] names = new String[nameTokens.countTokens()];
StringTokenizer strTok = new StringTokenizer(annotation.getArgumentNames(), ",");
if (strTok.countTokens() > 0) {
String[] names = new String[strTok.countTokens()];
for (int i = 0; i < names.length; i++) {
names[i] = nameTokens.nextToken();
names[i] = strTok.nextToken();
}
return names;
}
@@ -275,7 +323,6 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
}
@Override
@Nullable
public String[] getParameterNames(Constructor<?> ctor) {
throw new UnsupportedOperationException("Spring AOP cannot handle constructor advice");
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -24,7 +24,6 @@ import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -49,13 +48,10 @@ import org.springframework.util.Assert;
@SuppressWarnings("serial")
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
@Nullable
private List<Pattern> includePatterns;
@Nullable
private AspectJAdvisorFactory aspectJAdvisorFactory;
private AspectJAdvisorFactory aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory();
@Nullable
private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;
@@ -64,7 +60,7 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
* <p>Default is to consider all @AspectJ beans as eligible.
*/
public void setIncludePatterns(List<String> patterns) {
this.includePatterns = new ArrayList<>(patterns.size());
this.includePatterns = new ArrayList<Pattern>(patterns.size());
for (String patternText : patterns) {
this.includePatterns.add(Pattern.compile(patternText));
}
@@ -78,9 +74,6 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
@Override
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
super.initBeanFactory(beanFactory);
if (this.aspectJAdvisorFactory == null) {
this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
}
this.aspectJAdvisorsBuilder =
new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}
@@ -91,9 +84,7 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
// Add all the Spring advisors found according to superclass rules.
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
@@ -107,8 +98,7 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
// 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 != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
return (super.isInfrastructureClass(beanClass) || this.aspectJAdvisorFactory.isAspect(beanClass));
}
/**
@@ -140,7 +130,6 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
public BeanFactoryAspectJAdvisorsBuilderAdapter(
ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {
super(beanFactory, advisorFactory);
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -24,7 +24,6 @@ import org.aopalliance.aop.Advice;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.lang.Nullable;
/**
* Interface for factories that can create Spring AOP Advisors from classes
@@ -64,32 +63,31 @@ public interface AspectJAdvisorFactory {
/**
* Build Spring AOP Advisors for all annotated At-AspectJ methods
* on the specified aspect instance.
* @param aspectInstanceFactory the aspect instance factory
* (not the aspect instance itself in order to avoid eager instantiation)
* @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 aspectInstanceFactory);
List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aif);
/**
* Build a Spring AOP Advisor for the given AspectJ advice method.
* @param candidateAdviceMethod the candidate advice method
* @param aspectInstanceFactory the aspect instance factory
* @param declarationOrder the declaration order within the aspect
* @param aif the aspect instance factory
* @param declarationOrderInAspect the declaration order within the aspect
* @param aspectName the name of the aspect
* @return {@code null} 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
*/
@Nullable
Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrder, String aspectName);
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 expressionPointcut the AspectJ expression pointcut
* @param aspectInstanceFactory the aspect instance factory
* @param declarationOrder the declaration order within the aspect
* @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} 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
@@ -100,8 +98,7 @@ public interface AspectJAdvisorFactory {
* @see org.springframework.aop.aspectj.AspectJAfterReturningAdvice
* @see org.springframework.aop.aspectj.AspectJAfterThrowingAdvice
*/
@Nullable
Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName);
Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut pointcut,
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName);
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,18 +16,18 @@
package org.springframework.aop.aspectj.annotation;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.aspectj.lang.reflect.PerClauseKind;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJProxyUtils;
import org.springframework.aop.aspectj.SimpleAspectInstanceFactory;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.aop.framework.ProxyCreatorSupport;
import org.springframework.aop.support.AopUtils;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.OrderComparator;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -50,7 +50,7 @@ import org.springframework.util.ClassUtils;
public class AspectJProxyFactory extends ProxyCreatorSupport {
/** Cache for singleton aspect instances */
private static final Map<Class<?>, Object> aspectCache = new ConcurrentHashMap<>();
private static final Map<Class<?>, Object> aspectCache = new HashMap<Class<?>, Object>();
private final AspectJAdvisorFactory aspectFactory = new ReflectiveAspectJAdvisorFactory();
@@ -76,7 +76,7 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
* Create a new {@code AspectJProxyFactory}.
* No target, only interfaces. Must add interceptors.
*/
public AspectJProxyFactory(Class<?>... interfaces) {
public AspectJProxyFactory(Class<?>[] interfaces) {
setInterfaces(interfaces);
}
@@ -119,11 +119,9 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
*/
private void addAdvisorsFromAspectInstanceFactory(MetadataAwareAspectInstanceFactory instanceFactory) {
List<Advisor> advisors = this.aspectFactory.getAdvisors(instanceFactory);
Class<?> targetClass = getTargetClass();
Assert.state(targetClass != null, "Unresolvable target class");
advisors = AopUtils.findAdvisorsThatCanApply(advisors, targetClass);
advisors = AopUtils.findAdvisorsThatCanApply(advisors, getTargetClass());
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(advisors);
AnnotationAwareOrderComparator.sort(advisors);
OrderComparator.sort(advisors);
addAdvisors(advisors);
}
@@ -146,7 +144,7 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
private MetadataAwareAspectInstanceFactory createAspectInstanceFactory(
AspectMetadata am, Class<?> aspectClass, String aspectName) {
MetadataAwareAspectInstanceFactory instanceFactory;
MetadataAwareAspectInstanceFactory instanceFactory = null;
if (am.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
// Create a shared aspect instance.
Object instance = getSingletonAspectInstance(aspectClass);
@@ -164,19 +162,23 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
* is created if one cannot be found in the instance cache.
*/
private Object getSingletonAspectInstance(Class<?> aspectClass) {
// Quick check without a lock...
Object instance = aspectCache.get(aspectClass);
if (instance == null) {
synchronized (aspectCache) {
// To be safe, check within full lock now...
instance = aspectCache.get(aspectClass);
if (instance == null) {
instance = new SimpleAspectInstanceFactory(aspectClass).getAspectInstance();
aspectCache.put(aspectClass, instance);
}
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);
}
}
return instance;
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,10 +16,6 @@
package org.springframework.aop.aspectj.annotation;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.AjType;
import org.aspectj.lang.reflect.AjTypeSystem;
@@ -35,35 +31,21 @@ 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, enabling us to work with different
* AspectJ instantiation models such as "singleton", "pertarget" and "perthis".
* <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
*/
@SuppressWarnings("serial")
public class AspectMetadata implements Serializable {
/**
* 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 final String aspectName;
/**
* The aspect class, stored separately for re-resolution of the
* corresponding AjType on deserialization.
*/
private final Class<?> aspectClass;
public class AspectMetadata {
/**
* AspectJ reflection information (AspectJ 5 / Java 5 specific).
* Re-resolved on deserialization since it isn't serializable itself.
*/
private transient AjType<?> ajType;
private final AjType<?> ajType;
/**
* Spring AOP pointcut corresponding to the per clause of the
@@ -72,6 +54,13 @@ public class AspectMetadata implements Serializable {
*/
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.
@@ -83,7 +72,7 @@ public class AspectMetadata implements Serializable {
Class<?> currClass = aspectClass;
AjType<?> ajType = null;
while (currClass != Object.class) {
while (!currClass.equals(Object.class)) {
AjType<?> ajTypeToCheck = AjTypeSystem.getAjType(currClass);
if (ajTypeToCheck.isAspect()) {
ajType = ajTypeToCheck;
@@ -94,29 +83,26 @@ public class AspectMetadata implements Serializable {
if (ajType == null) {
throw new IllegalArgumentException("Class '" + aspectClass.getName() + "' is not an @AspectJ aspect");
}
if (ajType.getDeclarePrecedence().length > 0) {
this.ajType = ajType;
if (this.ajType.getDeclarePrecedence().length > 0) {
throw new IllegalArgumentException("DeclarePrecendence not presently supported in Spring AOP");
}
this.aspectClass = ajType.getJavaClass();
this.ajType = ajType;
switch (this.ajType.getPerClause().getKind()) {
case SINGLETON:
case SINGLETON :
this.perClausePointcut = Pointcut.TRUE;
return;
case PERTARGET:
case PERTHIS:
case PERTARGET : case PERTHIS :
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
ajexp.setLocation(aspectClass.getName());
ajexp.setLocation("@Aspect annotation on " + aspectClass.getName());
ajexp.setExpression(findPerClause(aspectClass));
ajexp.setPointcutDeclarationScope(aspectClass);
this.perClausePointcut = ajexp;
return;
case PERTYPEWITHIN:
case PERTYPEWITHIN :
// Works with a type pattern
this.perClausePointcut = new ComposablePointcut(new TypePatternClassFilter(findPerClause(aspectClass)));
return;
default:
default :
throw new AopConfigException(
"PerClause " + ajType.getPerClause().getKind() + " not supported by Spring AOP for " + aspectClass);
}
@@ -126,8 +112,10 @@ public class AspectMetadata implements Serializable {
* Extract contents from String of form {@code pertarget(contents)}.
*/
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(str.indexOf("(") + 1);
str = str.substring(0, str.length() - 1);
return str;
}
@@ -144,11 +132,11 @@ public class AspectMetadata implements Serializable {
* Return the aspect class.
*/
public Class<?> getAspectClass() {
return this.aspectClass;
return this.ajType.getJavaClass();
}
/**
* Return the aspect name.
* Return the aspect class.
*/
public String getAspectName() {
return this.aspectName;
@@ -185,10 +173,4 @@ public class AspectMetadata implements Serializable {
return (isPerThisOrPerTarget() || isPerTypeWithin());
}
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
inputStream.defaultReadObject();
this.ajType = AjTypeSystem.getAjType(this.aspectClass);
}
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,14 +16,11 @@
package org.springframework.aop.aspectj.annotation;
import java.io.Serializable;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.OrderUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order;
import org.springframework.util.ClassUtils;
/**
@@ -41,8 +38,7 @@ import org.springframework.util.ClassUtils;
* @see org.springframework.beans.factory.BeanFactory
* @see LazySingletonAspectInstanceFactoryDecorator
*/
@SuppressWarnings("serial")
public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInstanceFactory, Serializable {
public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInstanceFactory {
private final BeanFactory beanFactory;
@@ -59,7 +55,7 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
* @param name name of the bean
*/
public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name) {
this(beanFactory, name, null);
this(beanFactory, name, beanFactory.getType(name));
}
/**
@@ -69,19 +65,11 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
* @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
* ({@code null} indicates resolution through {@link BeanFactory#getType} via the bean name)
*/
public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name, @Nullable Class<?> type) {
Assert.notNull(beanFactory, "BeanFactory must not be null");
Assert.notNull(name, "Bean name must not be null");
public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name, Class<?> type) {
this.beanFactory = beanFactory;
this.name = name;
Class<?> resolvedType = type;
if (type == null) {
resolvedType = beanFactory.getType(name);
Assert.notNull(resolvedType, "Unresolvable bean type - explicitly specify the aspect class");
}
this.aspectMetadata = new AspectMetadata(resolvedType, name);
this.aspectMetadata = new AspectMetadata(type, name);
}
@@ -91,11 +79,13 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
}
@Override
@Nullable
public ClassLoader getAspectClassLoader() {
return (this.beanFactory instanceof ConfigurableBeanFactory ?
((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() :
ClassUtils.getDefaultClassLoader());
if (this.beanFactory instanceof ConfigurableBeanFactory) {
return ((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader();
}
else {
return ClassUtils.getDefaultClassLoader();
}
}
@Override
@@ -103,24 +93,6 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
return this.aspectMetadata;
}
@Override
@Nullable
public Object getAspectCreationMutex() {
if (this.beanFactory.isSingleton(this.name)) {
// Rely on singleton semantics provided by the factory -> no local lock.
return null;
}
else if (this.beanFactory instanceof ConfigurableBeanFactory) {
// No singleton guarantees from the factory -> let's lock locally but
// reuse the factory's singleton lock, just in case a lazy dependency
// of our advice bean happens to trigger the singleton lock implicitly...
return ((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex();
}
else {
return this;
}
}
/**
* Determine the order for this factory's target aspect, either
* an instance-specific order expressed through implementing the
@@ -138,7 +110,10 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
if (Ordered.class.isAssignableFrom(type) && this.beanFactory.isSingleton(this.name)) {
return ((Ordered) this.beanFactory.getBean(this.name)).getOrder();
}
return OrderUtils.getOrder(type, Ordered.LOWEST_PRECEDENCE);
Order order = AnnotationUtils.findAnnotation(type, Order.class);
if (order != null) {
return order.value();
}
}
return Ordered.LOWEST_PRECEDENCE;
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,18 +16,17 @@
package org.springframework.aop.aspectj.annotation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
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.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -44,12 +43,12 @@ public class BeanFactoryAspectJAdvisorsBuilder {
private final AspectJAdvisorFactory advisorFactory;
@Nullable
private volatile List<String> aspectBeanNames;
private List<String> aspectBeanNames;
private final Map<String, List<Advisor>> advisorsCache = new ConcurrentHashMap<>();
private final Map<String, List<Advisor>> advisorsCache = new HashMap<String, List<Advisor>>();
private final Map<String, MetadataAwareAspectInstanceFactory> aspectFactoryCache = new ConcurrentHashMap<>();
private final Map<String, MetadataAwareAspectInstanceFactory> aspectFactoryCache =
new HashMap<String, MetadataAwareAspectInstanceFactory>();
/**
@@ -57,7 +56,7 @@ public class BeanFactoryAspectJAdvisorsBuilder {
* @param beanFactory the ListableBeanFactory to scan
*/
public BeanFactoryAspectJAdvisorsBuilder(ListableBeanFactory beanFactory) {
this(beanFactory, new ReflectiveAspectJAdvisorFactory(beanFactory));
this(beanFactory, new ReflectiveAspectJAdvisorFactory());
}
/**
@@ -81,64 +80,63 @@ public class BeanFactoryAspectJAdvisorsBuilder {
* @see #isEligibleBean
*/
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
List<String> aspectNames = null;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
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);
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 {
// 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));
}
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;
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new ArrayList<>();
List<Advisor> advisors = new LinkedList<Advisor>();
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,9 +16,6 @@
package org.springframework.aop.aspectj.annotation;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
import org.aopalliance.aop.Advice;
@@ -31,7 +28,6 @@ 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;
import org.springframework.lang.Nullable;
/**
* Internal implementation of AspectJPointcutAdvisor.
@@ -41,116 +37,71 @@ import org.springframework.lang.Nullable;
* @author Juergen Hoeller
* @since 2.0
*/
@SuppressWarnings("serial")
class InstantiationModelAwarePointcutAdvisorImpl
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation, Serializable {
private static final Advice EMPTY_ADVICE = new Advice() {};
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation {
private final AspectJExpressionPointcut declaredPointcut;
private final Class<?> declaringClass;
private final String methodName;
private final Class<?>[] parameterTypes;
private transient Method aspectJAdviceMethod;
private final AspectJAdvisorFactory aspectJAdvisorFactory;
private Pointcut pointcut;
private final MetadataAwareAspectInstanceFactory aspectInstanceFactory;
private final int declarationOrder;
private final String aspectName;
private final Pointcut pointcut;
private final Method method;
private final boolean lazy;
@Nullable
private final AspectJAdvisorFactory atAspectJAdvisorFactory;
private Advice instantiatedAdvice;
@Nullable
private int declarationOrder;
private String aspectName;
private Boolean isBeforeAdvice;
@Nullable
private Boolean isAfterAdvice;
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
public InstantiationModelAwarePointcutAdvisorImpl(AspectJAdvisorFactory af, AspectJExpressionPointcut ajexp,
MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect, String aspectName) {
this.declaredPointcut = declaredPointcut;
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
this.methodName = aspectJAdviceMethod.getName();
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
this.aspectJAdviceMethod = aspectJAdviceMethod;
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
this.aspectInstanceFactory = aspectInstanceFactory;
this.declarationOrder = declarationOrder;
this.declaredPointcut = ajexp;
this.method = method;
this.atAspectJAdvisorFactory = af;
this.aspectInstanceFactory = aif;
this.declarationOrder = declarationOrderInAspect;
this.aspectName = aspectName;
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
if (aif.getAspectMetadata().isLazilyInstantiated()) {
// Static part of the pointcut is a lazy type.
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
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, aspectInstanceFactory);
this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aif);
this.lazy = true;
}
else {
// A singleton aspect.
this.pointcut = this.declaredPointcut;
this.lazy = false;
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.
* The pointcut for Spring AOP to use. Actual behaviour of the pointcut will change
* depending on the state of the advice.
*/
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
@Override
public boolean isLazy() {
return this.lazy;
}
@Override
public synchronized boolean isAdviceInstantiated() {
return (this.instantiatedAdvice != null);
}
/**
* Lazily instantiate advice if necessary.
*/
@Override
public synchronized Advice getAdvice() {
if (this.instantiatedAdvice == null) {
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
return this.instantiatedAdvice;
}
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
/**
* This is only of interest for Spring AOP: AspectJ instantiation semantics
* are much richer. In AspectJ terminology, all a return of {@code true}
@@ -168,6 +119,33 @@ class InstantiationModelAwarePointcutAdvisorImpl
return this.aspectInstanceFactory.getAspectMetadata();
}
/**
* Lazily instantiate advice if necessary.
*/
@Override
public synchronized Advice getAdvice() {
if (this.instantiatedAdvice == null) {
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
return this.instantiatedAdvice;
}
@Override
public boolean isLazy() {
return this.lazy;
}
@Override
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;
}
@@ -213,55 +191,45 @@ class InstantiationModelAwarePointcutAdvisorImpl
*/
private void determineAdviceType() {
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.aspectJAdviceMethod);
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.method);
if (aspectJAnnotation == null) {
this.isBeforeAdvice = false;
this.isAfterAdvice = false;
}
else {
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
case AtAround:
this.isBeforeAdvice = false;
this.isAfterAdvice = false;
break;
case AtBefore:
this.isBeforeAdvice = true;
this.isAfterAdvice = false;
break;
case AtAfter:
case AtAfterReturning:
case AtAfterThrowing:
this.isBeforeAdvice = false;
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;
}
}
}
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
inputStream.defaultReadObject();
try {
this.aspectJAdviceMethod = this.declaringClass.getMethod(this.methodName, this.parameterTypes);
}
catch (NoSuchMethodException ex) {
throw new IllegalStateException("Failed to find advice method on deserialization", ex);
}
}
@Override
public String toString() {
return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() +
"]; advice method [" + this.aspectJAdviceMethod + "]; perClauseKind=" +
this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind();
"]; 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.
* 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 {
@@ -269,12 +237,10 @@ class InstantiationModelAwarePointcutAdvisorImpl
private final Pointcut preInstantiationPointcut;
@Nullable
private LazySingletonAspectInstanceFactoryDecorator aspectInstanceFactory;
public PerTargetInstantiationModelPointcut(AspectJExpressionPointcut declaredPointcut,
private PerTargetInstantiationModelPointcut(AspectJExpressionPointcut declaredPointcut,
Pointcut preInstantiationPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
this.declaredPointcut = declaredPointcut;
this.preInstantiationPointcut = preInstantiationPointcut;
if (aspectInstanceFactory instanceof LazySingletonAspectInstanceFactoryDecorator) {
@@ -283,15 +249,14 @@ class InstantiationModelAwarePointcutAdvisorImpl
}
@Override
public boolean matches(Method method, @Nullable Class<?> targetClass) {
// We're either instantiated and matching on declared pointcut,
// or uninstantiated matching on either pointcut...
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);
}
@Override
public boolean matches(Method method, @Nullable Class<?> targetClass, Object... args) {
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
// This can match only on declared pointcut.
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass));
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,9 +16,6 @@
package org.springframework.aop.aspectj.annotation;
import java.io.Serializable;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -28,12 +25,10 @@ import org.springframework.util.Assert;
* @author Juergen Hoeller
* @since 2.0
*/
@SuppressWarnings("serial")
public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwareAspectInstanceFactory, Serializable {
public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwareAspectInstanceFactory {
private final MetadataAwareAspectInstanceFactory maaif;
@Nullable
private volatile Object materialized;
@@ -48,25 +43,15 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
@Override
public Object getAspectInstance() {
Object aspectInstance = this.materialized;
if (aspectInstance == null) {
Object mutex = this.maaif.getAspectCreationMutex();
if (mutex == null) {
aspectInstance = this.maaif.getAspectInstance();
this.materialized = aspectInstance;
}
else {
synchronized (mutex) {
aspectInstance = this.materialized;
if (aspectInstance == null) {
aspectInstance = this.maaif.getAspectInstance();
this.materialized = aspectInstance;
}
public synchronized Object getAspectInstance() {
if (this.materialized == null) {
synchronized (this) {
if (this.materialized == null) {
this.materialized = this.maaif.getAspectInstance();
}
}
}
return aspectInstance;
return this.materialized;
}
public boolean isMaterialized() {
@@ -74,7 +59,6 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
}
@Override
@Nullable
public ClassLoader getAspectClassLoader() {
return this.maaif.getAspectClassLoader();
}
@@ -84,12 +68,6 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
return this.maaif.getAspectMetadata();
}
@Override
@Nullable
public Object getAspectCreationMutex() {
return this.maaif.getAspectCreationMutex();
}
@Override
public int getOrder() {
return this.maaif.getOrder();
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -17,7 +17,6 @@
package org.springframework.aop.aspectj.annotation;
import org.springframework.aop.aspectj.AspectInstanceFactory;
import org.springframework.lang.Nullable;
/**
* Subinterface of {@link org.springframework.aop.aspectj.AspectInstanceFactory}
@@ -40,12 +39,4 @@ public interface MetadataAwareAspectInstanceFactory extends AspectInstanceFactor
*/
AspectMetadata getAspectMetadata();
/**
* Return the best possible creation mutex for this factory.
* @return the mutex object (may be {@code null} for no mutex to use)
* @since 4.3
*/
@Nullable
Object getAspectCreationMutex();
}
@@ -5,7 +5,7 @@
* 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
* 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,
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,13 +16,11 @@
package org.springframework.aop.aspectj.annotation;
import java.io.Serializable;
import org.springframework.beans.factory.BeanFactory;
/**
* {@link org.springframework.aop.aspectj.AspectInstanceFactory} backed by a
* {@link BeanFactory}-provided prototype, enforcing prototype semantics.
* 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}
@@ -34,8 +32,7 @@ import org.springframework.beans.factory.BeanFactory;
* @see org.springframework.beans.factory.BeanFactory
* @see LazySingletonAspectInstanceFactoryDecorator
*/
@SuppressWarnings("serial")
public class PrototypeAspectInstanceFactory extends BeanFactoryAspectInstanceFactory implements Serializable {
public class PrototypeAspectInstanceFactory extends BeanFactoryAspectInstanceFactory {
/**
* Create a PrototypeAspectInstanceFactory. AspectJ will be called to
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,12 +16,12 @@
package org.springframework.aop.aspectj.annotation;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import org.aopalliance.aop.Advice;
@@ -45,13 +45,12 @@ 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.beans.factory.BeanFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConvertingComparator;
import org.springframework.lang.Nullable;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.comparator.CompoundComparator;
import org.springframework.util.comparator.InstanceComparator;
/**
@@ -66,61 +65,45 @@ import org.springframework.util.comparator.InstanceComparator;
* @author Phillip Webb
* @since 2.0
*/
@SuppressWarnings("serial")
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory {
private static final Comparator<Method> METHOD_COMPARATOR;
static {
Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
new InstanceComparator<>(
CompoundComparator<Method> comparator = new CompoundComparator<Method>();
comparator.addComparator(new ConvertingComparator<Method, Annotation>(
new InstanceComparator<Annotation>(
Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
(Converter<Method, Annotation>) method -> {
AspectJAnnotation<?> ann = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
return (ann != null ? ann.getAnnotation() : null);
});
Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator);
}
@Nullable
private final BeanFactory beanFactory;
/**
* Create a new {@code ReflectiveAspectJAdvisorFactory}.
*/
public ReflectiveAspectJAdvisorFactory() {
this(null);
}
/**
* Create a new {@code ReflectiveAspectJAdvisorFactory}, propagating the given
* {@link BeanFactory} to the created {@link AspectJExpressionPointcut} instances,
* for bean pointcut handling as well as consistent {@link ClassLoader} resolution.
* @param beanFactory the BeanFactory to propagate (may be {@code null}}
* @since 4.3.6
* @see AspectJExpressionPointcut#setBeanFactory
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#getBeanClassLoader()
*/
public ReflectiveAspectJAdvisorFactory(@Nullable BeanFactory beanFactory) {
this.beanFactory = beanFactory;
new Converter<Method, Annotation>() {
@Override
public Annotation convert(Method method) {
AspectJAnnotation<?> annotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
return annotation == null ? null : annotation.getAnnotation();
}
}));
comparator.addComparator(new ConvertingComparator<Method, String>(
new Converter<Method, String>() {
@Override
public String convert(Method method) {
return method.getName();
}
}));
METHOD_COMPARATOR = comparator;
}
@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
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.
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(maaif);
List<Advisor> advisors = new ArrayList<>();
final List<Advisor> advisors = new LinkedList<Advisor>();
for (Method method : getAdvisorMethods(aspectClass)) {
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
@@ -146,16 +129,17 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
}
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
final List<Method> methods = new ArrayList<>();
ReflectionUtils.doWithMethods(aspectClass, method -> {
// Exclude pointcuts
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
final List<Method> methods = new LinkedList<Method>();
ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
@Override
public void doWith(Method method) throws IllegalArgumentException {
// Exclude pointcuts
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
}
}, ReflectionUtils.USER_DECLARED_METHODS);
if (methods.size() > 1) {
methods.sort(METHOD_COMPARATOR);
}
});
Collections.sort(methods, METHOD_COMPARATOR);
return methods;
}
@@ -164,9 +148,8 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
* for the given introduction field.
* <p>Resulting Advisors will need to be evaluated for targets.
* @param introductionField the field to introspect
* @return the Advisor instance, or {@code null} if not an Advisor
* @return {@code null} if not an Advisor
*/
@Nullable
private Advisor getDeclareParentsAdvisor(Field introductionField) {
DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
if (declareParents == null) {
@@ -174,8 +157,10 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
return null;
}
if (DeclareParents.class == declareParents.defaultImpl()) {
throw new IllegalStateException("'defaultImpl' attribute must be set on DeclareParents");
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(
@@ -184,46 +169,38 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aif,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
validate(aif.getAspectMetadata().getAspectClass());
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
AspectJExpressionPointcut ajexp =
getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass());
if (ajexp == null) {
return null;
}
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
return new InstantiationModelAwarePointcutAdvisorImpl(
this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName);
}
@Nullable
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());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
return ajexp;
}
@Override
@Nullable
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp,
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) {
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
Class<?> candidateAspectClass = aif.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
AspectJAnnotation<?> aspectJAnnotation =
@@ -247,57 +224,50 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
AbstractAspectJAdvice springAdvice;
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
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, expressionPointcut, aspectInstanceFactory);
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);
"Unsupported advice type on method " + candidateAdviceMethod);
}
// Now to configure the advice...
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
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.
@@ -307,8 +277,13 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor {
public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) {
super(aif.getAspectMetadata().getPerClausePointcut(), (MethodBeforeAdvice)
(method, args, target) -> aif.getAspectInstance());
super(aif.getAspectMetadata().getPerClausePointcut(), new MethodBeforeAdvice() {
@Override
public void before(Method method, Object[] args, Object target) {
// Simply instantiate the aspect
aif.getAspectInstance();
}
});
}
}

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