Compare commits

...

157 Commits

Author SHA1 Message Date
Spring Buildmaster 77c0292665 Release version 4.2.6.RELEASE 2016-05-06 07:55:23 +00:00
Juergen Hoeller 5fc0d43852 AsyncResult properly propagates execution exception
Issue: SPR-14249
(cherry picked from commit 1b1aac9)
2016-05-05 20:57:42 +02:00
Juergen Hoeller 2dbc8b0381 Latest applicable dependency updates (EhCache 2.10.2, JRuby 1.7.25, Quartz 2.2.3, Undertow 1.3.22) 2016-05-04 18:44:11 +02:00
Juergen Hoeller 0f2bc3f6bf AbstractRequestLoggingFilter ignores non-available query string
Issue: SPR-14244
(cherry picked from commit 08ddd1b)
2016-05-04 18:44:04 +02:00
Juergen Hoeller 1e491f11d7 Polishing
(cherry picked from commit 8c139ef)
2016-05-04 18:43:59 +02:00
Juergen Hoeller 68cdd5d358 LazySingletonAspectInstanceFactoryDecorator uses shared singleton mutex
Issue: SPR-14241
2016-05-04 09:13:09 +02:00
Juergen Hoeller bf3dee9492 Polishing 2016-05-03 18:47:33 +02:00
Juergen Hoeller a6563a3263 Explicit note on Java deserialization
(cherry picked from commit 76964e1)
2016-05-03 18:46:40 +02:00
Juergen Hoeller 0589c1b4b5 Warn about non-static BeanDefinitionRegistryPostProcessor declarations on @Configuration classes
Issue: SPR-14234
(cherry picked from commit 7737c3c)
2016-05-02 15:20:15 +02:00
Juergen Hoeller 85675fbe2e Consistent SmartLifecycle implementations
Issue: SPR-14233
(cherry picked from commit f83cbff)
2016-05-02 14:07:32 +02:00
Juergen Hoeller 85faeef816 DefaultMessageListenerContainer immediately invokes stop callback when not running
Issue: SPR-14233
(cherry picked from commit e45d33f)
2016-05-02 14:07:25 +02:00
Juergen Hoeller d49ecab89a Polishing 2016-04-29 11:12:20 +02:00
Rossen Stoyanchev f7ace54488 Ensure Environment.shutdown() in Reactor2TcpClient
Issue: SPR-14229
2016-04-28 17:48:38 -04:00
Rossen Stoyanchev d48eeb2c84 Reactor2TcpClient cleans up TcpClient instances
Issue: SPR-14231
2016-04-28 15:48:13 -04:00
Rossen Stoyanchev a3da6b186f Upgrade to Reactor 2.0.8
(cherry picked from commit 6e4e52b)
2016-04-27 21:57:16 +02:00
Juergen Hoeller d66186a90b Polishing
(cherry picked from commit 8ddb432)
2016-04-27 21:42:01 +02:00
Juergen Hoeller 75a8f5b3ca ApplicationListenerDetector explicitly prevents serialization of its ApplicationContext reference
Issue: SPR-14214
(cherry picked from commit e0734ae)
2016-04-27 21:41:55 +02:00
Juergen Hoeller 6a3d4940b5 SpringServletContainerInitializer does not log WebApplicationInitializer class names
Issue: SPR-14213
(cherry picked from commit f73df2e)
2016-04-27 21:41:44 +02:00
Juergen Hoeller 002d6d70a5 SocketUtils considers port range including maxPort
Issue: SPR-14211
(cherry picked from commit bf7b475)
2016-04-27 21:41:36 +02:00
Juergen Hoeller b9fa67e0e6 FastByteArrayInputStream returns correct count from read(byte[])
Issue: SPR-14209
(cherry picked from commit 9bf5a5c)
2016-04-27 21:41:30 +02:00
Rossen Stoyanchev 9fa061431c XML config properly initialize WS message broker stats
Issue: SPR-14190
2016-04-26 17:24:48 -04:00
Rossen Stoyanchev 6314df367c Update spring-mvc-3.2.xsd
The backport in commit cf39078 changed the spring-mvc-3.2.xsd.
This change updates the same in the 4.2.x branch.

Issue: SPR-14186
2016-04-21 14:07:27 -04:00
Venil Noronha e67a274b32 Remove isOpen assertion when sending WebSocket message
Issue: SPR-14138
2016-04-18 09:45:01 -04:00
Venil Noronha 2eab3df4d1 Delegate sendMessage
Issue: SPR-14139
2016-04-18 09:29:33 -04:00
Juergen Hoeller e205a1b30a Upgrade to EhCache 3.0 GA
Issue: SPR-14185
2016-04-18 14:43:05 +02:00
Juergen Hoeller 4be22c4938 Consistent public constructors in ast package
Issue: SPR-14181
(cherry picked from commit e38bfb1)
2016-04-15 22:30:36 +02:00
Rob Winch 9438c41853 Add --no-daemon to Gradle import
Previously using the Gradle Daemon with import eclipse scripts would cause
issues with the merge plugin. Specifically, projects would randomly not
be associated to the classpath.

This change explicitly adds --no-daemon in the import scripts to ensure
that the problem does not occur.

Issue SPR-14102
(cherry picked from commit 970dc4a)
2016-04-15 22:30:11 +02:00
Rob Winch 0075240d8f Change Eclipse Settings to allow forbidden references
Spring uses lots of forbidden references. The current Eclipse settings
set forbiddenReference=error This was not ideal because there were lots of
errors in the workspace.

This commit changes forbiddenReference=warning since we nee to allow
forbidden references.
(cherry picked from commit 6489a76)
2016-04-15 22:30:03 +02:00
Juergen Hoeller f83e149f8a Strong Hibernate 5.1 recommendation
Issue: SPR-13480
Issue: SPR-14176
(cherry picked from commit 44a9c49)
2016-04-15 12:11:25 +02:00
Juergen Hoeller 4c41b9d4b9 Polishing
(cherry picked from commit 3b44c47)
2016-04-14 16:41:39 +02:00
Juergen Hoeller 1d39c97def Downgrade to Protobuf Java Format 1.2
Issue: SPR-14171
2016-04-14 15:54:52 +02:00
Juergen Hoeller fd954ef1d6 Upgrade to Jackson 2.6.6 and Protobuf Java Format 1.4 2016-04-14 14:48:57 +02:00
Juergen Hoeller 334b4a99b0 Jackson-based message converters consistently check media type first
Issue: SPR-14163
2016-04-14 14:22:23 +02:00
Juergen Hoeller 416a24c6bc Avoid unnecessary GenericHttpMessageConverter re-declaration
(cherry picked from commit 96875fe)
2016-04-13 19:02:52 +02:00
Juergen Hoeller 7f438dc9aa Consistent headers.getContentLength() checks 2016-04-13 18:44:56 +02:00
Juergen Hoeller bf3cadb908 AbstractJackson2HttpMessageConverter's canRead/canWrite checks media type first before delegating to Jackson
Issue: SPR-14163
(cherry picked from commit e366746)
2016-04-13 18:44:13 +02:00
Juergen Hoeller 863bae7d86 Drop outdated support for building on JDK 9 (not compatible with JDK 9 b111+) 2016-04-13 13:58:34 +02:00
Juergen Hoeller 09b7735b0f Polishing 2016-04-13 13:33:39 +02:00
Juergen Hoeller e6ae437038 Latest dependency updates (AspectJ 1.8.9, Rhino 1.7.7.1, WebJars Locator 0.30) 2016-04-13 13:13:11 +02:00
Juergen Hoeller b1c70729c2 Polishing 2016-04-12 23:33:58 +02:00
Juergen Hoeller 33dcef3583 SpringCacheAnnotationParser properly accepts empty @Caching annotation
Issue: SPR-14162
(cherry picked from commit da11261)
2016-04-12 23:32:42 +02:00
Juergen Hoeller 3829a77894 Polishing
(cherry picked from commit 74608e6)
2016-04-12 16:09:48 +02:00
Juergen Hoeller e9382b2c0b SimpleTransactionScope properly suspends and resumes scoped objects
Issue: SPR-14148
(cherry picked from commit 831f09c)
2016-04-12 16:09:43 +02:00
Stephane Nicoll e5477ea19d Add interface-based detection test
Add a test that explicitely validates that `@ManagedResource` and friends
can be set on an interface.

Issue: SPR-13138
(cherry picked from commit eb49f3c)
2016-04-11 22:07:52 +02:00
Juergen Hoeller b7890ca28e Consistent license header
(cherry picked from commit 537193a)
2016-04-11 21:14:05 +02:00
Juergen Hoeller b9fd8586ff Fixed XML example for setup of scheduled tasks
Issue: SPR-14145
(cherry picked from commit 550a320)
2016-04-11 20:52:54 +02:00
Juergen Hoeller e0642c77c3 HttpHeaders consistently ignores invalid date header values
Issue: SPR-14144
(cherry picked from commit 448621a)
2016-04-11 20:52:43 +02:00
Juergen Hoeller d303ac94dc Polishing 2016-04-11 12:22:37 +02:00
Juergen Hoeller 053ebb180e Polishing 2016-04-10 12:37:55 +02:00
Juergen Hoeller 2b6ec6a85e Upgrade to CGLIB 3.2.2
Issue: SPR-13934
(cherry picked from commit dc7ec44)
2016-04-09 23:13:30 +02:00
Juergen Hoeller aa5c12c534 Polishing 2016-04-08 22:52:36 +02:00
Stephane Nicoll 67a65ea600 Support Quartz trigger without JobDetail
This commit allows to create a Quartz trigger implementation via
either `CronTriggerFactoryBean` or `SimpleTriggerFactoryBean` even if no
job detail is provided.

Issue: SPR-13604
(cherry picked from commit 2970065)
2016-04-08 22:52:29 +02:00
Rossen Stoyanchev 35f0fce2ae Remove section on spring-framework-contrib group 2016-04-08 15:44:22 -04:00
Juergen Hoeller 9c30a1f8df Latest dependency updates (EhCache 3.0 RC3, Undertow 1.3.21)
(cherry picked from commit e365ffb)
2016-04-08 16:51:18 +02:00
Juergen Hoeller 0864834077 Cleanup of remaining direct BeanWrapper usage
Issue: SPR-14121
(cherry picked from commit 157dcab)
2016-04-07 14:52:03 +02:00
Juergen Hoeller 7659101843 BeanDefinitionBuilder keeps providing addConstructorArg(Object) for Spring Security 2.x compatibility
Issue: SPR-14123
(cherry picked from commit 4ea4257)
2016-04-07 14:51:57 +02:00
Juergen Hoeller 5f9113678f Consistent use of LinkedHashMap in StaticListableBeanFactory 2016-04-05 15:57:05 +02:00
Juergen Hoeller 51f356f518 Quartz ResourceLoaderClassLoadHelper explicitly falls back to classpath lookup
Issue: SPR-13706
(cherry picked from commit 6db6f23)
2016-04-05 12:23:44 +02:00
Juergen Hoeller 0ecbeafd2b Polishing
(cherry picked from commit d2d528d)
2016-04-05 11:42:17 +02:00
Juergen Hoeller 6b0f26c335 StatementCreatorUtils handles Types.BOOLEAN through PreparedStatement.setBoolean
Issue: SPR-14116
(cherry picked from commit 797f5db)
2016-04-05 11:40:50 +02:00
Juergen Hoeller 2166f2060f Latest applicable dependency updates (AspectJ 1.8.9, EhCache 3.0 RC2, Hibernate 5.0.9, Joda-Time 2.9.3, Netty 4.0.36, SLF4J 1.7.21, Tomcat 8.0.33, Undertow 1.3.20, Woodstox 5.0.2) 2016-04-05 11:38:51 +02:00
Rossen Stoyanchev 000a0a0006 Call resetRequest after writeFrame for polling sessions
Previous refactoring (fcf6ae and also 43d937) in the SockJsSession
hierarchy consolidated access to the request and response in the
base class AbstractHttpSockJsSession in order to keep synchronization
concerns there. However that also unintentionally removed the call to
resetRequest() after sending a heartbeat for any of the
PollingSockJsSession classes. In general a polling session should call
resetRequest after every frame written.

This commit brings back the writeFrame override in PollingSockJsSession
with an extra call to resetRequest().

Issue: SPR-14107
2016-04-04 19:30:33 -04:00
Juergen Hoeller 6d479b2060 Polishing 2016-04-04 20:59:40 +02:00
Stephane Nicoll 9443c1c5dd Fix Auto-Startup for @JmsListener
Ignore container's auto-startup once the context is refreshed.

Issue: SPR-14015
(cherry picked from commit 996c1cc)
2016-04-04 20:59:33 +02:00
Rossen Stoyanchev 01d50e9bde Fix incomplete log message
Commit 48236b from 2014 introduced a logging improvement to avoid
logging each removed session per line and instead log one line at
the end with all removed sessions ids. However that list of removed
session ids wasn't populated. This commit fixes that.

Issue: SPR-14111
2016-04-04 14:02:23 -04:00
Juergen Hoeller d7fe92d022 Abstract(Stax)XMLReader recognizes standard features as not supported
Issue: SPR-14056
(cherry picked from commit 35eb52e)
2016-04-04 15:10:08 +02:00
Juergen Hoeller 3b7ca7e76a Further tests for getBeanNamesForType(ResolvableType)
Issue: SPR-14097
(cherry picked from commit edea66a)
2016-04-04 15:10:02 +02:00
Juergen Hoeller dc6e512275 EhCacheManagerFactoryBean logs cache manager name
Issue: SPR-14110
(cherry picked from commit 8bfba6a)
2016-04-04 15:09:57 +02:00
Juergen Hoeller 0ed7f9aebb SimpleApplicationEventMulticaster leniently handles ClassCastException
Issue: SPR-14109
(cherry picked from commit 13f889e)
2016-04-04 15:09:52 +02:00
Juergen Hoeller 02a6f31807 ASM ClassReader leniently handles label offset mismatch
Issue: SPR-14089
(cherry picked from commit 3910350)
2016-03-30 10:46:45 +02:00
Juergen Hoeller 8f6ede519d RequestHeaderMapMethodArgumentResolver defensively checks for non-existing header values
Issue: SPR-14091
(cherry picked from commit b2a17ba)
2016-03-30 10:46:33 +02:00
Juergen Hoeller 756301b7c5 Polishing
(cherry picked from commit 94cb778)
2016-03-25 23:38:23 +01:00
Juergen Hoeller ccaa504378 Polishing
(cherry picked from commit 775bccc)
2016-03-24 21:47:56 +01:00
Juergen Hoeller 0891fbaf97 Consistent formatting 2016-03-24 19:54:28 +01:00
Juergen Hoeller 2ea7fcde3e Polishing
(cherry picked from commit 9af12d2)
2016-03-24 17:17:58 +01:00
Juergen Hoeller 7c5aac122a Restored lazy resolution of default executor for AsyncAnnotationBeanPostProcessor
Issue: SPR-14030
(cherry picked from commit 155fa37)
2016-03-24 17:17:52 +01:00
Juergen Hoeller 05ab769555 Bsh/GroovyScriptFactory reset script cache in case of compilation error
Issue: SPR-14007
(cherry picked from commit 0597ff1)
2016-03-24 17:17:10 +01:00
Juergen Hoeller a19be754c8 DefaultCorsProcessor checks for existing CORS response before attempting to compare origin
Issue: SPR-14080
(cherry picked from commit abe7345)
2016-03-24 17:17:04 +01:00
Juergen Hoeller 8994498b44 Revised newline handling tests pass on Windows now
Issue: SPR-13503
(cherry picked from commit 311d4c9)
2016-03-24 17:16:52 +01:00
Juergen Hoeller fcd155a92c Correct RFC 4648 references in method-level javadoc
Issue: SPR-14067
(cherry picked from commit ec7c3aa)
2016-03-24 17:16:41 +01:00
Juergen Hoeller bfe8d15e97 Removed invalid quoting of message arguments from MessageSource examples
Issue: SPR-14003
(cherry picked from commit 100f3c5)
2016-03-24 17:16:33 +01:00
Juergen Hoeller a5904efbde Upgrade to XStream 1.4.9
Issue: SPR-14084
(cherry picked from commit 7e4563a)
2016-03-24 17:16:24 +01:00
Brian Clozel ed34ea4876 Reset Expires HTTP header when caching configured
Just like SPR-13252 addressed this issue for the "Pragma" header, this
issue resets the HTTP 1.0 "Expires" header.
When such a header has been set (by a filter, for example) and HTTP
caching has been configured at the WebContentGenerator, this header
value is reset to "". In this case, "Cache-Control" and "Expires" might
have inconsistent values and we consider that the HTTP caching
configuration should take precedence.

Depending on the servlet container chosen to deploy the application,
this might result in empty "" header values or no header set at all.

Issue: SPR-14053
Cherry picked from 15fe8279e6
2016-03-23 16:35:53 +01:00
Kazuki Shimizu 2267b14055 Add newline at the beginning of textarea macro for FreeMarker and Velocity
Issue: SPR-13503
Cherry-picked from 9b2023111d
2016-03-23 11:56:28 +01:00
Stephane Nicoll 0c8a40bdbc Fix escaping of #
This commit disables the "quotes" substitutions on specific XML
examples that require to use the reserved `#` character.

Issue: SPR-14074
2016-03-21 12:51:40 +01:00
Rossen Stoyanchev d7062f6291 Ensure RedirectModel is initialized
This commit fixes an old bug in ModelAndViewContainer where getModel
returns a new ModelMap instance that isn't saved and re-used.

Issue: SPR-14045
2016-03-14 23:04:58 -04:00
Stephane Nicoll bd82acbf99 Support ResolvableTypeProvider on simple event pojo
Previously, the generic type of a simple pojo event implementing
ResolvableTypeProvider wasn't detected properly. This commit fixes the
logic when the generic type is not provided to reuse what
PayloadApplicationEvent is already doing anyway.

Issue: SPR-14029
2016-03-10 09:51:43 +01:00
Brian Clozel f76b38c506 Fix SpringUrl Velocity macro URI encoding
Prior to this commit, the springUrl Velocity macro would only prepend
the context to the given URL; this means that the
ServletHttpResponse.encodeUri method is not called and neither the
ResourceUrlProvider.

This commit changes this macro to use RequestContext.getContextUrl which
prepends the context and encodes the URI.

Issue: SPR-14027
Cherry-picked from 0a56667093
2016-03-08 18:01:29 +01:00
Brian Clozel b88c39955b Add newline at the beginning of textarea JSP tags
This commit adds a newline char at the beginning of textarea tags
values. As per the HTML 4.01 spec (and browsers behavior), a line break
following a start tag is ignored.

This can lead to Spring's textarea tag to ignore a line break char at
the beginning of a tag value.

See https://www.w3.org/TR/html401/appendix/notes.html#notes-line-breaks

Issue: SPR-13503
Cherry picked from 44c32128
2016-03-03 16:52:16 +01:00
Brian Clozel 0ef90df120 Relax SPR-13867 changes for ResourceHttpRequestHandler
Prior to this change, SPR-13867 made sure that any class extending
WebContentGenerator would not overwrite existing HTTP "Cache-Control"
response headers - set by a filter, a Controller handler, etc.

This caused issues with resource handling, since specifying a cache
configuration there would not overwrite default headers set by filters,
for example by Spring Security.

This commit restricts the previous changes to the
RequestMappingHandlerAdapter, in order to avoid overwriting header set
by a filter or a Controller handler in those cases.

Issue: SPR-14005
Cherry-picked from 50bcd67fb6
2016-03-02 17:45:50 +01:00
Juergen Hoeller 8a44560d82 RequestMappingHandlerAdapter properly invokes handler method in case of no session as well
Issue: SPR-13999
(cherry picked from commit a02fd7c)
2016-02-29 15:08:00 +01:00
Juergen Hoeller 0349abc565 RequestMappingHandlerAdapter properly invokes handler method in synchronizeOnSession mode again
Issue: SPR-13999
(cherry picked from commit 1815a6a)
2016-02-29 11:46:16 +01:00
Juergen Hoeller 9129ec2623 LinkedCaseInsensitiveMap provides reliable getOrDefault implementation
Issue: SPR-13981
(cherry picked from commit 7a32ce3)
2016-02-29 11:42:43 +01:00
Spring Buildmaster 2cbc5ff0c8 Next Development Version 2016-02-25 01:36:20 -08:00
Juergen Hoeller cafb99a33d Polishing
(cherry picked from commit 028a690)
2016-02-24 17:59:15 +01:00
Juergen Hoeller 9c5cabf4ba Refined ApplicationContextInitializer assignability exception
(cherry picked from commit ca19920)
2016-02-24 17:58:29 +01:00
Juergen Hoeller 97b017781a TimerScheduledFuture correctly calculates getDelay result
Issue: SPR-13977
(cherry picked from commit a68b910)
2016-02-24 17:56:30 +01:00
Juergen Hoeller 9f2b3ca8b8 Polishing
(cherry picked from commit 1899fb3)
2016-02-23 00:05:44 +01:00
Juergen Hoeller 3f795e64c6 Avoid NPE in case of @Lazy @Autowired(required=false)
Issue: SPR-13967
(cherry picked from commit b9fe6d8)
2016-02-23 00:05:17 +01:00
Juergen Hoeller 99dc7769a6 Latest dependency updates (EhCache 3.0 M5, Groovy 2.4.6, Gson 2.6.1, Hibernate ORM 5.0.8, Hibernate Validator 5.2.4, SLF4J 1.7.16, SnakeYAML 1.17, Undertow 1.3.18) 2016-02-23 00:04:49 +01:00
Juergen Hoeller a620770470 Polishing 2016-02-19 16:02:25 +01:00
Juergen Hoeller 167ba8387a ScriptUtils.executeSqlScript logs SQLWarnings at debug level
Issue: SPR-13959
(cherry picked from commit 9235345)
2016-02-19 15:59:47 +01:00
Juergen Hoeller 4320161172 Shared EntityManager Query unwrapping before passing it to addNamedQuery
Issue: SPR-13957
(cherry picked from commit 7fcb277)
2016-02-19 15:59:24 +01:00
Juergen Hoeller 659e44146c Consistent equals implementations across class hierarchies
Issue: SPR-13951
(cherry picked from commit ac44f9e)
2016-02-19 15:56:36 +01:00
Juergen Hoeller 08f2ab942c DefaultMessageListenerContainer stops if recovery failed after interrupt signal
Issue: SPR-11787
(cherry picked from commit 1253b45)
2016-02-19 15:54:52 +01:00
Juergen Hoeller d2b9dbf181 BeanMethodInterceptor does not pass on null arguments for singleton beans
Issue: SPR-13887
(cherry picked from commit 5ed9046)
2016-02-19 15:54:26 +01:00
Sebastien Deleuze 09db26af2b Improve Jackson 2.7 compatibility
This commit introduces a conditional call in
AbstractJackson2HttpMessageConverter#getJavaType() in order to avoid
calling TypeFactory#constructType() with a null contextClass parameter,
since this is not supported by Jackson 2.7 anymore.

It allows to use Spring Framework 4.2.x with Jackson 2.7.1+ for most use
cases, but with some limitations. For example, with Jackson 2.7
TypeVariable resolution from method parameters does not work.

As a consequence, after this commit Spring Framework 4.2.x still fully
supports Jackson up to version 2.6, but improves Jackson 2.7 compatibility.
Full support for Jackson 2.7 is provided as of Spring Framework 4.3.x.

Issue: SPR-13853
2016-02-11 13:45:49 +01:00
Juergen Hoeller 19c5462b13 Polishing 2016-02-10 20:48:10 +01:00
Juergen Hoeller 5047e90625 AbstractMarshaller defensively uses DocumentBuilderFactory within synchronized block
Issue: SPR-13935
(cherry picked from commit f61b998)
2016-02-10 20:47:54 +01:00
Juergen Hoeller cf3e460a8b ReflectiveMethodResolver lets local static methods override java.lang.Class methods
Issue: SPR-13918
(cherry picked from commit 43bcab9)
2016-02-10 20:47:41 +01:00
Juergen Hoeller c960d9733d DisposableBeanAdapter ignores bridge method conflicts
Issue: SPR-13922
(cherry picked from commit 903ae48)
2016-02-10 20:47:31 +01:00
Juergen Hoeller 9e7f6ba0b1 PathMatchingResourcePatternResolver consistently logs retrieval results
Issue: SPR-13923
(cherry picked from commit 449f704)
2016-02-10 20:47:24 +01:00
Juergen Hoeller d8a7b6f0f8 Latest dependency updates (Hibernate Validator 5.2.3, Joda-Time 2.9.2, OkHttp 2.7.4, SLF4J 1.7.15, Netty 4.0.34, Tomcat 8.0.32, Undertow 1.3.17) 2016-02-10 20:40:18 +01:00
Rossen Stoyanchev 6ef2d827c6 Reduce log level for @ExceptionHandler failure
Issue: SPR-13932
2016-02-09 12:58:08 -05:00
Rossen Stoyanchev b1a46ccbd9 Fix NPE in InvocableHandlerMethod
Issue: SPR-13917
2016-02-04 23:33:04 -05:00
Rossen Stoyanchev f053cdec51 Improve close in ConcurrentWebSocketSessionDecorator
Before this commit the concurrent session wrapper mainly protected the
sending of messages. The close itself however may also cause a message
to be sent as is the case of the SockJS protocol.

This change protects the close and checks if the session has exceeded
send time or buffer limits in which case the close status is changed
to SESSION_NOT_RELIABLE (introduced in commit cbd5af3a) which in turn
signals that extra care should be exercised when closing the session.

Issue: SPR-13904
2016-02-04 17:22:36 -05:00
Rossen Stoyanchev 39c05c56c4 BufferedImage converter writes Content-Type again
Issue: SPR-13906
2016-02-04 15:01:13 -05:00
Juergen Hoeller 4418331429 Polishing
(cherry picked from commit e903106)
2016-02-04 20:50:21 +01:00
Juergen Hoeller e48315549e AbstractXlsView does not explicitly flush (for compatibility with WebSphere Liberty)
Issue: SPR-13910
(cherry picked from commit 28e8af2)
2016-02-04 20:49:48 +01:00
Sam Brannen 484dd96606 Throw exception if TxMgr cannot be retrieved for @Transactional test
Prior to this commit, a @Transactional integration test would silently
be executed without a transaction if the transaction manager could not
be retrieved from the application context -- for example, it no such
bean was defined or if multiple beans were present but none satisfied
the qualifier.

This commit addresses this issue by throwing an IllegalStateException
if the PlatformTransactionManager cannot be retrieved for a
@Transactional test.

Issue: SPR-13895
(cherry picked from commit 6d2b9a0136)
2016-02-03 18:18:55 +01:00
Juergen Hoeller bb12e0ea70 Latest dependency updates (AspectJ 1.8.8, Hibernate ORM 5.0.7, Jackson 2.6.5, Jetty 9.3.7, Undertow 1.3.14, SLF4J 1.7.14) 2016-01-26 22:25:22 +01:00
Juergen Hoeller 30ef893c28 Polishing 2016-01-26 22:23:56 +01:00
Juergen Hoeller a58eee6ad1 RequestParamMethodArgumentResolver defensively handles MethodParameter nesting level and java.util.Optional access
Issue: SPR-13850
2016-01-26 22:07:27 +01:00
Juergen Hoeller 0866aa923a LocalSessionFactoryBuilder provides ClassLoader to Hibernate BootstrapServiceRegistry
Issue: SPR-13879
2016-01-26 20:35:30 +01:00
Juergen Hoeller d152259673 Clarify component scan include-filter semantics
Issue: SPR-13844
(cherry picked from commit 837cb75)
2016-01-26 20:30:34 +01:00
Juergen Hoeller 14babb78b4 Clarify environment property precedence rules
Issue: SPR-13845
(cherry picked from commit ebad8db)
2016-01-26 20:30:05 +01:00
Juergen Hoeller 4fc6ead548 SessionDisconnectEvent actually preserves given session user
Issue: SPR-13871
(cherry picked from commit cdc9bf7)
2016-01-26 20:29:08 +01:00
Juergen Hoeller c1f233c787 Shared EntityManager does not insist on actualTransactionActive flag anymore
Issue: SPR-13838
(cherry picked from commit 50829c9)
2016-01-26 20:28:07 +01:00
Juergen Hoeller 77b8f4d6af ImportStack extends ArrayDeque instead of Stack and relies on standard contains implementation
Issue: SPR-13852
(cherry picked from commit e14c2de)
2016-01-26 20:27:28 +01:00
Juergen Hoeller 8516de62e3 FastByteArrayInputStream consistently returns -1 when no data available
Issue: SPR-13858
(cherry picked from commit 5d4547d)
2016-01-26 20:26:44 +01:00
Brian Clozel bcebc9db7e Register prefixed path patterns with FixedVersionStrategy
Prior to this change, configuring a `FixedVersionStrategy` like so
would configure a single "/js/**" path pattern:

```
versionResourceResolver.addFixedVersionStrategy("v1.0.0","/js/**");
```

This commit makes sure that for each path pattern, its prefixed version
is added to the map. For example, the previous configuration also
adds "/v1.0.0/js/**".

Issue: SPR-13883
cherry-picked from 84fe46cd
2016-01-22 19:03:52 +01:00
Brian Clozel fc34b0c592 Reorder HTTP headers processing in RequestMappingHandlerAdapter
Prior to this change, the `RequestMappingHandlerAdapter` would first add
a "Cache-Control" HTTP header to the response (depending on its
`WebContentGenerator` configuration and `@SessionAttributes` on the
handler class); then, the Adapter would delegate the actual handler the
processing of the request.
This leads to issues, as the handler does not have full control to the
response and has to deal with pre-existing headers in the response. This
means that the Adapter and the handler can add incompatible
Cache-Control directives without knowing it, since one cannot see the
headers added by the other until the response is committed.

This commit switches the order of execution: first, the handler is
called (possibly adding HTTP headers), then the RMHA processes the
response and adds "Cache-Control" directives *only if there's no
Cache-Control header already defined*.

Issue: SPR-13867
cherry-picked from 8f1d06f19
2016-01-22 16:36:48 +01:00
Brian Clozel a4cb3cf900 Fix OutOfBoundsException in ResourceUrlEncodingFilter
Prior to this change, the `ResourceUrlEncodingFilter` would try to
lookup resources URLs as soon as the given URL would be longer than the
expected context+servlet prefix path. This can lead to
OutOfBoundsExceptions when the provided URL does not start with that
prefix and still has the required length.

This commit makes sure that all candidate URLs for resources lookup are
prefixed with the cached servlet and context path. This underlines the
fact that the `ResourceUrlEncodingFilter` does not support relative URLs
for now and delegates to the native servlet implementation in that case.

Issue: SPR-13861
cherry-picked from 2f6d86b7
2016-01-21 17:39:37 +01:00
Rossen Stoyanchev 33112df237 Fix second failing test 2016-01-20 23:13:34 -05:00
Rossen Stoyanchev e159086201 Fix failing test 2016-01-20 21:39:41 -05:00
Rossen Stoyanchev ab16adab2e Avoid double encoding URI in ServletServerHttpRequest
Issue: SPR-13876
2016-01-20 17:58:07 -05:00
Ian Chan 29692fcc21 Catch RejectedExecutionException in WebAsyncManager
Issue: SPR-13836
2016-01-14 15:50:20 -05:00
Rossen Stoyanchev 73df50db3c Fix javadoc issue in ResponseEntityExceptionHandler
Issue: SPR-13869
2016-01-14 14:28:15 -05:00
Brian Clozel 3af62bd0dd Polish
Issue: SPR-13817
(cherry picked from d681f77d)
2016-01-05 17:33:04 +01:00
Brian Clozel 1581597092 Preserve ETag HTTP header for versioned resources
Prior to this change, a resource handler chain configured with a
`VersionResourceResolver` would add the resource version to the request
attributes when serving that resource. This approach would not work when
a `CachingResourceResolver` is configured and the resource is already
cached. Indeed, that code path is not executed when the resource is
resolved from the cache.

This commit adds a new `VersionedResource` interface that's used by the
`VersionResourceResolver`, adding a `getVersion()` method that returns
the version string for that resource. This way, the version information
is cached with the resource itself and the request attributes are no
longer used for this.

Issue: SPR-13817
(cherry picked from commit 473cf9c)
2016-01-05 15:04:05 +01:00
Juergen Hoeller 84e5234eb5 Avoid getTypeForFactoryBean warn logging for lazy-init beans
Issue: SPR-13833
(cherry picked from commit 04f3181)
2015-12-31 11:52:55 +01:00
Juergen Hoeller 24e58c1ac3 Refined RequestMappingHandlerMapping bean definition
Issue: SPR-13832
(cherry picked from commit 9bffb9e)
2015-12-31 11:52:47 +01:00
holub 15da48eba5 Update SockJS client code snippet 2015-12-30 10:29:01 +01:00
Juergen Hoeller 342d760f70 Polishing
(cherry picked from commit 27c2e8c)
2015-12-29 21:51:04 +01:00
Juergen Hoeller acecda7153 Avoid sensitive Proxy.getInvocationHandler call in synthesizeAnnotation
Issue: SPR-13829
(cherry picked from commit aecb8b6)
2015-12-29 21:50:49 +01:00
Juergen Hoeller 4a863c9066 Upgrade to Undertow 1.3.11
(cherry picked from commit 873b173)
2015-12-29 11:26:52 +01:00
Juergen Hoeller 35b8696523 Polishing 2015-12-29 11:24:56 +01:00
Juergen Hoeller e1bdf5577e StatementCreatorUtils always tries getParameterType on Oracle 12c driver
Issue: SPR-13825
(cherry picked from commit e48ec4f)
2015-12-29 11:23:49 +01:00
Juergen Hoeller deae872912 Consistent use of varargs plus related polishing 2015-12-22 23:50:05 +01:00
Juergen Hoeller 36940e003d Polishing 2015-12-21 22:38:25 +01:00
Juergen Hoeller 935d714333 SimpleNamespaceContext implements all subtleties of the NamespaceContext contract
Issue: SPR-13713
(cherry picked from commit f8860e2)
2015-12-21 22:35:47 +01:00
Juergen Hoeller 9021f8fd71 Upgrade to JavaMail 1.5.5 and Hibernate ORM 5.0.6
(cherry picked from commit 06056e6)
2015-12-21 22:35:23 +01:00
Juergen Hoeller 6f2f3595e9 Backported import and declaration cleanup 2015-12-18 00:18:09 +01:00
Juergen Hoeller d59a97c101 Polishing 2015-12-18 00:02:48 +01:00
Juergen Hoeller 7344dd259c Allow for explicit spring-websocket-4.2.xsd declarations
Issue: SPR-13804
2015-12-18 00:02:14 +01:00
Juergen Hoeller f3ac64153e Correct spring-websocket-4.2 versus spring-websocket-4.1 xsd declarations
Issue: SPR-13804
(cherry picked from commit 2fd48c9)
2015-12-17 18:34:47 +01:00
Stephane Nicoll 7b35103135 Switch to 4.2.5.BUILD-SNAPSHOT 2015-12-17 12:53:44 +01:00
438 changed files with 6105 additions and 4356 deletions
-8
View File
@@ -29,14 +29,6 @@ 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.
### Discuss non-trivial contribution ideas with committers
If you're considering anything more than correcting a typo or fixing a minor
bug, please discuss it on the [spring-framework-contrib][] mailing list before
submitting a pull request. We're happy to provide guidance, but please spend an
hour or two researching the subject on your own, including searching the mailing
list for prior discussions.
### Sign the Individual Contributor License Agreement (ICLA)
If you have not previously done so, please fill out and submit the
+91 -107
View File
@@ -27,57 +27,51 @@ configure(allprojects) { project ->
group = "org.springframework"
version = qualifyVersionIfNecessary(version)
ext.aspectjVersion = "1.8.7"
ext.aspectjVersion = "1.8.9"
ext.eclipselinkVersion = "2.4.2"
ext.ehcacheVersion = "2.10.1"
ext.ehcacheVersion = "2.10.2"
ext.ehcachejcacheVersion = "1.0.1"
ext.ehcache3Version = "3.0.0.m4"
ext.ejbApiVersion = "3.0"
ext.ehcache3Version = "3.0.0"
ext.ejbVersion = "3.0"
ext.fileuploadVersion = "1.3.1"
ext.freemarkerVersion = "2.3.23"
ext.groovyVersion = "2.4.5"
ext.gsonVersion = "2.5"
ext.groovyVersion = "2.4.6"
ext.gsonVersion = "2.6.2"
ext.guavaVersion = "19.0"
ext.hamcrestVersion = "1.3"
ext.hibernate3Version = "3.6.10.Final"
ext.hibernate4Version = "4.3.11.Final"
ext.hibernate5Version = "5.0.5.Final"
ext.hibernate5Version = "5.0.9.Final"
ext.hibval4Version = "4.3.2.Final"
ext.hibval5Version = "5.2.2.Final"
ext.hibval5Version = "5.2.4.Final"
ext.hsqldbVersion = "2.3.3"
ext.htmlunitVersion = "2.19"
ext.httpasyncVersion = "4.1.1"
ext.httpclientVersion = "4.5.1"
ext.jackson2Version = "2.6.4"
ext.jasperreportsVersion = "6.2.0"
ext.javamailVersion = "1.5.4"
ext.jettyVersion = "9.3.6.v20151106"
ext.jodaVersion = "2.9.1"
ext.jrubyVersion = "1.7.23" // JRuby 9000 only supported through JSR-223 (StandardScriptFactory)
ext.jsonassertVersion = "1.2.3"
ext.jsonpathVersion = "2.1.0"
ext.httpclientVersion = "4.5.2"
ext.jackson2Version = "2.6.6"
ext.jasperreportsVersion = "6.2.1"
ext.javamailVersion = "1.5.5"
ext.jettyVersion = "9.3.8.v20160314"
ext.jodaVersion = "2.9.3"
ext.jrubyVersion = "1.7.25" // JRuby 9000 only supported through JSR-223 (StandardScriptFactory)
ext.jtaVersion = "1.2"
ext.junitVersion = "4.12"
ext.nettyVersion = "4.0.33.Final"
ext.okhttpVersion = "2.7.0"
ext.openjpaVersion = "2.4.0"
ext.nettyVersion = "4.0.36.Final"
ext.okhttpVersion = "2.7.5"
ext.openjpaVersion = "2.4.1"
ext.poiVersion = "3.13"
ext.protobufVersion = "2.6.1"
ext.reactorVersion = "2.0.7.RELEASE"
ext.reactorVersion = "2.0.8.RELEASE"
ext.romeVersion = "1.5.1"
ext.seleniumVersion = "2.48.2"
ext.slf4jVersion = "1.7.13"
ext.snakeyamlVersion = "1.16"
ext.slf4jVersion = "1.7.21"
ext.snakeyamlVersion = "1.17"
ext.snifferVersion = "1.14"
ext.testngVersion = "6.9.10"
ext.tiles2Version = "2.2.2"
ext.tiles3Version = "3.0.5"
ext.tomcatVersion = "8.0.30"
ext.tomcatVersion = "8.0.33"
ext.tyrusVersion = "1.3.5" // constrained by WebLogic 12.1.3 support
ext.undertowVersion = "1.3.10.Final"
ext.woodstoxVersion = "5.0.1"
ext.undertowVersion = "1.3.22.Final"
ext.xmlunitVersion = "1.6"
ext.xstreamVersion = "1.4.8"
ext.xstreamVersion = "1.4.9"
ext.gradleScriptDir = "${rootProject.projectDir}/gradle"
@@ -130,8 +124,6 @@ configure(allprojects) { project ->
repositories {
maven { url "https://repo.spring.io/libs-release" }
maven { url "https://repo.spring.io/milestone" }
maven { url "https://repo.spring.io/snapshot" } // reactor 2.0.6 snapshot
}
dependencies {
@@ -291,7 +283,7 @@ project("spring-core") {
// both into the spring-core jar. cglib 3.2 itself depends on asm 5.0 and is therefore
// further transformed by the JarJar task to depend on org.springframework.asm; this
// avoids including two different copies of asm unnecessarily.
def cglibVersion = "3.2.0"
def cglibVersion = "3.2.2"
def objenesisVersion = "2.2"
configurations {
@@ -356,7 +348,7 @@ project("spring-core") {
optional("log4j:log4j:1.2.17")
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
testCompile("xmlunit:xmlunit:${xmlunitVersion}")
testCompile("com.fasterxml.woodstox:woodstox-core:${woodstoxVersion}") {
testCompile("com.fasterxml.woodstox:woodstox-core:5.0.2") {
exclude group: "stax", module: "stax-api"
}
}
@@ -386,7 +378,7 @@ project("spring-beans") {
optional("org.yaml:snakeyaml:${snakeyamlVersion}")
testCompile("log4j:log4j:1.2.17")
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
}
}
}
project("spring-beans-groovy") {
@@ -477,7 +469,7 @@ project("spring-context") {
compile(files(project(":spring-core").cglibRepackJar))
optional(project(":spring-instrument"))
optional("javax.inject:javax.inject:1")
optional("javax.ejb:ejb-api:${ejbApiVersion}")
optional("javax.ejb:ejb-api:${ejbVersion}")
optional("javax.enterprise.concurrent:javax.enterprise.concurrent-api:1.0")
optional("javax.money:money-api:1.0")
optional("org.eclipse.persistence:javax.persistence:2.0.0")
@@ -548,7 +540,7 @@ project("spring-tx") {
optional("aopalliance:aopalliance:1.0")
optional("javax.transaction:javax.transaction-api:${jtaVersion}")
optional("javax.resource:connector-api:1.5")
optional("javax.ejb:ejb-api:${ejbApiVersion}")
optional("javax.ejb:ejb-api:${ejbVersion}")
optional("com.ibm.websphere:uow:6.0.2.17")
testCompile("org.aspectj:aspectjweaver:${aspectjVersion}")
testCompile("org.eclipse.persistence:javax.persistence:2.0.0")
@@ -566,11 +558,6 @@ project("spring-oxm") {
targetCompatibility = 1.6
}
if (!System.getProperty("java.version").contains("1.8.")) {
// necessary because castor and xjc tasks cannot find the JDK's compiler on JDK 9
compileTestJava.enabled = false
}
dependencies {
compile(project(":spring-beans"))
compile(project(":spring-core"))
@@ -630,7 +617,7 @@ project("spring-jdbc") {
optional("javax.transaction:javax.transaction-api:${jtaVersion}")
optional("com.mchange:c3p0:0.9.5.2")
optional("org.hsqldb:hsqldb:${hsqldbVersion}")
optional("com.h2database:h2:1.4.190")
optional("com.h2database:h2:1.4.191")
optional("org.apache.derby:derby:10.12.1.1")
optional("org.apache.derby:derbyclient:10.12.1.1")
}
@@ -649,7 +636,7 @@ project("spring-context-support") {
optional("javax.cache:cache-api:1.0.0")
optional("com.google.guava:guava:${guavaVersion}")
optional("net.sf.ehcache:ehcache:${ehcacheVersion}")
optional("org.quartz-scheduler:quartz:2.2.2")
optional("org.quartz-scheduler:quartz:2.2.3")
optional("org.codehaus.fabric3.api:commonj:1.1.0")
optional("org.apache.velocity:velocity:1.7")
optional("org.freemarker:freemarker:${freemarkerVersion}")
@@ -723,8 +710,8 @@ project("spring-web") {
exclude group: "javax.servlet", module: "javax.servlet-api"
}
optional("log4j:log4j:1.2.17")
optional("com.google.protobuf:protobuf-java:2.6.1")
optional("com.googlecode.protobuf-java-format:protobuf-java-format:1.2")
optional("com.google.protobuf:protobuf-java:${protobufVersion}")
optional("javax.mail:javax.mail-api:${javamailVersion}")
testCompile(project(":spring-context-support")) // for JafMediaTypeFactory
testCompile("xmlunit:xmlunit:${xmlunitVersion}")
@@ -739,52 +726,6 @@ project("spring-web") {
}
}
project("spring-websocket") {
description = "Spring WebSocket"
dependencies {
compile(project(":spring-core"))
compile(project(":spring-context"))
compile(project(":spring-web"))
optional(project(":spring-messaging"))
optional(project(":spring-webmvc"))
optional("javax.servlet:javax.servlet-api:3.1.0")
optional("javax.websocket:javax.websocket-api:1.0")
optional("org.apache.tomcat:tomcat-websocket:${tomcatVersion}") {
exclude group: "org.apache.tomcat", module: "tomcat-websocket-api"
exclude group: "org.apache.tomcat", module: "tomcat-servlet-api"
}
optional("org.glassfish.tyrus:tyrus-spi:${tyrusVersion}")
optional("org.glassfish.tyrus:tyrus-core:${tyrusVersion}")
optional("org.glassfish.tyrus:tyrus-server:${tyrusVersion}")
optional("org.glassfish.tyrus:tyrus-container-servlet:${tyrusVersion}")
optional("org.eclipse.jetty:jetty-webapp:${jettyVersion}") {
exclude group: "javax.servlet", module: "javax.servlet"
}
optional("org.eclipse.jetty.websocket:websocket-server:${jettyVersion}") {
exclude group: "javax.servlet", module: "javax.servlet"
}
optional("org.eclipse.jetty.websocket:websocket-client:${jettyVersion}")
optional("org.eclipse.jetty:jetty-client:${jettyVersion}")
optional("io.undertow:undertow-core:${undertowVersion}")
optional("io.undertow:undertow-servlet:${undertowVersion}") {
exclude group: "org.jboss.spec.javax.servlet", module: "jboss-servlet-api_3.1_spec"
exclude group: "org.jboss.spec.javax.annotation", module: "jboss-annotations-api_1.2_spec"
}
optional("io.undertow:undertow-websockets-jsr:${undertowVersion}") {
exclude group: "org.jboss.spec.javax.websocket", module: "jboss-websocket-api_1.1_spec"
}
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
testCompile("org.apache.tomcat.embed:tomcat-embed-websocket:${tomcatVersion}")
testCompile("org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}")
testCompile("io.projectreactor:reactor-net:${reactorVersion}")
testCompile("io.netty:netty-all:${nettyVersion}")
testCompile("log4j:log4j:1.2.17")
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
}
}
project("spring-orm") {
description = "Spring Object/Relational Mapping"
@@ -837,7 +778,7 @@ project("spring-orm-hibernate4") {
optional("org.hibernate:hibernate-core:${hibernate4Version}")
optional("org.hibernate:hibernate-entitymanager:${hibernate4Version}")
optional("javax.servlet:javax.servlet-api:3.0.1")
optional("aopalliance:aopalliance:1.0")
optional("aopalliance:aopalliance:1.0")
testCompile("javax.validation:validation-api:1.1.0.GA")
testCompile("org.hibernate:hibernate-validator:${hibval5Version}")
testCompile("javax.el:javax.el-api:2.2.5")
@@ -913,9 +854,9 @@ project("spring-webmvc") {
exclude group: "org.slf4j", module: "jcl-over-slf4j"
exclude group: "org.springframework", module: "spring-web"
}
optional('org.webjars:webjars-locator:0.28')
optional('org.webjars:webjars-locator:0.30')
testCompile(project(":spring-aop"))
testCompile("rhino:js:1.7R1")
testCompile("org.mozilla:rhino:1.7.7.1")
testCompile("xmlunit:xmlunit:${xmlunitVersion}")
testCompile("dom4j:dom4j:1.6.1") {
exclude group: "xml-apis", module: "xml-apis"
@@ -991,6 +932,52 @@ project("spring-webmvc-portlet") {
}
}
project("spring-websocket") {
description = "Spring WebSocket"
dependencies {
compile(project(":spring-core"))
compile(project(":spring-context"))
compile(project(":spring-web"))
optional(project(":spring-messaging"))
optional(project(":spring-webmvc"))
optional("javax.servlet:javax.servlet-api:3.1.0")
optional("javax.websocket:javax.websocket-api:1.0")
optional("org.apache.tomcat:tomcat-websocket:${tomcatVersion}") {
exclude group: "org.apache.tomcat", module: "tomcat-websocket-api"
exclude group: "org.apache.tomcat", module: "tomcat-servlet-api"
}
optional("org.glassfish.tyrus:tyrus-spi:${tyrusVersion}")
optional("org.glassfish.tyrus:tyrus-core:${tyrusVersion}")
optional("org.glassfish.tyrus:tyrus-server:${tyrusVersion}")
optional("org.glassfish.tyrus:tyrus-container-servlet:${tyrusVersion}")
optional("org.eclipse.jetty:jetty-webapp:${jettyVersion}") {
exclude group: "javax.servlet", module: "javax.servlet"
}
optional("org.eclipse.jetty.websocket:websocket-server:${jettyVersion}") {
exclude group: "javax.servlet", module: "javax.servlet"
}
optional("org.eclipse.jetty.websocket:websocket-client:${jettyVersion}")
optional("org.eclipse.jetty:jetty-client:${jettyVersion}")
optional("io.undertow:undertow-core:${undertowVersion}")
optional("io.undertow:undertow-servlet:${undertowVersion}") {
exclude group: "org.jboss.spec.javax.servlet", module: "jboss-servlet-api_3.1_spec"
exclude group: "org.jboss.spec.javax.annotation", module: "jboss-annotations-api_1.2_spec"
}
optional("io.undertow:undertow-websockets-jsr:${undertowVersion}") {
exclude group: "org.jboss.spec.javax.websocket", module: "jboss-websocket-api_1.1_spec"
}
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
testCompile("org.apache.tomcat.embed:tomcat-embed-websocket:${tomcatVersion}")
testCompile("org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}")
testCompile("io.projectreactor:reactor-net:${reactorVersion}")
testCompile("io.netty:netty-all:${nettyVersion}")
testCompile("log4j:log4j:1.2.17")
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
}
}
project("spring-test") {
description = "Spring TestContext Framework"
@@ -1018,15 +1005,15 @@ project("spring-test") {
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
optional("org.hamcrest:hamcrest-core:${hamcrestVersion}")
optional("com.jayway.jsonpath:json-path:${jsonpathVersion}")
optional("org.skyscreamer:jsonassert:${jsonassertVersion}")
optional("xmlunit:xmlunit:${xmlunitVersion}")
optional("net.sourceforge.htmlunit:htmlunit:${htmlunitVersion}")
optional("org.seleniumhq.selenium:selenium-htmlunit-driver:${seleniumVersion}")
optional("net.sourceforge.htmlunit:htmlunit:2.19")
optional("org.seleniumhq.selenium:selenium-htmlunit-driver:2.48.2")
optional("org.skyscreamer:jsonassert:1.2.3")
optional("com.jayway.jsonpath:json-path:2.1.0")
testCompile(project(":spring-context-support"))
testCompile(project(":spring-oxm"))
testCompile("javax.mail:javax.mail-api:${javamailVersion}")
testCompile("javax.ejb:ejb-api:${ejbApiVersion}")
testCompile("javax.ejb:ejb-api:${ejbVersion}")
testCompile("org.hibernate:hibernate-core:${hibernate4Version}")
testCompile("org.hibernate:hibernate-entitymanager:${hibernate4Version}")
testCompile("org.hibernate:hibernate-validator:${hibval5Version}")
@@ -1080,8 +1067,8 @@ project("spring-aspects") {
dependencies {
aspects(project(":spring-orm"))
ajc("org.aspectj:aspectjtools:1.9.0.BETA-2") // for the ability to build on JDK 9, not exposed in the POMs yet
rt("org.aspectj:aspectjrt:${aspectjVersion}") // regular AspectJ version here, to be exposed in the POMs
ajc("org.aspectj:aspectjtools:${aspectjVersion}")
rt("org.aspectj:aspectjrt:${aspectjVersion}")
compile("org.aspectj:aspectjweaver:${aspectjVersion}")
provided("org.eclipse.persistence:javax.persistence:2.0.0")
optional(project(":spring-aop")) // for @Async support
@@ -1099,8 +1086,7 @@ project("spring-aspects") {
eclipse.project {
natures += "org.eclipse.ajdt.ui.ajnature"
buildCommands = [new org.gradle.plugins.ide.eclipse.model.
BuildCommand("org.eclipse.ajdt.core.ajbuilder")]
buildCommands = [new org.gradle.plugins.ide.eclipse.model.BuildCommand("org.eclipse.ajdt.core.ajbuilder")]
}
}
@@ -1170,9 +1156,7 @@ configure(rootProject) {
separateOutputDirs = false
backends = ['docbook']
options doctype: 'book', eruby: 'erubis'
attributes 'spring-version': project.version,
'revnumber' : project.version,
'docinfo' : ""
attributes 'spring-version': project.version, 'revnumber': project.version, 'docinfo': ""
}
reference {
@@ -1308,7 +1292,7 @@ configure(rootProject) {
baseName = "spring-framework"
classifier = "dist"
description = "Builds -${classifier} archive, containing all jars and docs, " +
"suitable for community download page."
"suitable for community download page."
ext.baseDir = "${baseName}-${project.version}";
+1 -1
View File
@@ -1 +1 @@
version=4.2.4.BUILD-SNAPSHOT
version=4.2.6.RELEASE
+3 -3
View File
@@ -29,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 cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
SET COMMAND=gradlew cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse
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
echo.
echo -----------------------------------------------------------------------
@@ -69,7 +69,7 @@ echo When the above is complete, return here and press the enter key.
pause
set COMMAND=gradlew :eclipse
set COMMAND=gradlew --no-daemon :eclipse
echo.
echo -----------------------------------------------------------------------
+2 -2
View File
@@ -42,7 +42,7 @@ 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 cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
COMMAND="./gradlew --no-daemon cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
cat <<EOM
@@ -84,7 +84,7 @@ EOM
read
COMMAND="./gradlew :eclipse"
COMMAND="./gradlew --no-daemon :eclipse"
cat <<EOM
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@@ -86,7 +86,7 @@ public interface MethodMatcher {
* @return whether there's a runtime match
* @see MethodMatcher#matches(Method, Class)
*/
boolean matches(Method method, Class<?> targetClass, Object[] args);
boolean matches(Method method, Class<?> targetClass, Object... args);
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,12 +29,14 @@ class TrueMethodMatcher implements MethodMatcher, Serializable {
public static final TrueMethodMatcher INSTANCE = new TrueMethodMatcher();
/**
* Enforce Singleton pattern.
*/
private TrueMethodMatcher() {
}
@Override
public boolean isRuntime() {
return false;
@@ -46,11 +48,17 @@ class TrueMethodMatcher implements MethodMatcher, Serializable {
}
@Override
public boolean matches(Method method, 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.
@@ -60,9 +68,4 @@ class TrueMethodMatcher implements MethodMatcher, Serializable {
return INSTANCE;
}
@Override
public String toString() {
return "MethodMatcher.TRUE";
}
}
@@ -135,7 +135,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
*/
private int joinPointStaticPartArgumentIndex = -1;
private Map<String, Integer> argumentBindings = null;
private Map<String, Integer> argumentBindings;
private boolean argumentsIntrospected = false;
@@ -250,17 +250,17 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
this.argumentNames[i] + "' that is not a valid Java identifier");
}
}
if (argumentNames != null) {
if (aspectJAdviceMethod.getParameterTypes().length == argumentNames.length + 1) {
if (this.argumentNames != null) {
if (this.aspectJAdviceMethod.getParameterTypes().length == this.argumentNames.length + 1) {
// May need to add implicit join point arg name...
Class<?> firstArgType = aspectJAdviceMethod.getParameterTypes()[0];
Class<?> firstArgType = this.aspectJAdviceMethod.getParameterTypes()[0];
if (firstArgType == JoinPoint.class ||
firstArgType == ProceedingJoinPoint.class ||
firstArgType == JoinPoint.StaticPart.class) {
String[] oldNames = argumentNames;
argumentNames = new String[oldNames.length + 1];
argumentNames[0] = "THIS_JOIN_POINT";
System.arraycopy(oldNames, 0, argumentNames, 1, oldNames.length);
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);
}
}
}
@@ -456,8 +456,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
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.");
}
@@ -471,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);
@@ -482,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);
@@ -581,10 +581,9 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
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)");
throw new IllegalStateException("Required to bind " + this.adviceInvocationArgumentCount +
" arguments, but only bound " + numBound + " (JoinPointMatch " +
(jpMatch == null ? "was NOT" : "WAS") + " bound in invocation)");
}
return adviceInvocationArgs;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@@ -37,6 +37,7 @@ public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodI
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,6 +40,7 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice implement
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public boolean isBeforeAdvice() {
return false;
@@ -62,6 +63,7 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice implement
}
}
/**
* 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
@@ -96,7 +98,7 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice implement
else if (Object.class == type && void.class == method.getReturnType()) {
return true;
}
else{
else {
return ClassUtils.isAssignable(type, method.getReturnType());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@@ -37,6 +37,7 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice implements
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public boolean isBeforeAdvice() {
return false;
@@ -57,11 +58,11 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice implements
try {
return mi.proceed();
}
catch (Throwable t) {
if (shouldInvokeOnThrowing(t)) {
invokeAdviceMethod(getJoinPointMatch(), null, t);
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw t;
throw ex;
}
}
@@ -69,8 +70,8 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice implements
* In AspectJ semantics, after throwing advice that specifies a throwing clause
* is only invoked if the thrown exception is a subtype of the given throwing type.
*/
private boolean shouldInvokeOnThrowing(Throwable t) {
return getDiscoveredThrowingType().isAssignableFrom(t.getClass());
private boolean shouldInvokeOnThrowing(Throwable ex) {
return getDiscoveredThrowingType().isAssignableFrom(ex.getClass());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@@ -41,6 +41,7 @@ public class AspectJAroundAdvice extends AbstractAspectJAdvice implements Method
super(aspectJAroundAdviceMethod, pointcut, aif);
}
@Override
public boolean isBeforeAdvice() {
return false;
@@ -56,7 +57,6 @@ public class AspectJAroundAdvice extends AbstractAspectJAdvice implements Method
return true;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
@@ -305,7 +305,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
}
@Override
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
public boolean matches(Method method, Class<?> targetClass, Object... args) {
checkReadyToMatch();
ShadowMatch shadowMatch = getShadowMatch(AopUtils.getMostSpecificMethod(method, targetClass), method);
ShadowMatch originalShadowMatch = getShadowMatch(method, method);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@ public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
invokeAdviceMethod(getJoinPointMatch(), null, null);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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.
@@ -61,34 +61,6 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
private static final String AJC_MAGIC = "ajc$";
/**
* Find and return the first AspectJ annotation on the given method
* (there <i>should</i> only be one anyway...)
*/
@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 */
protected final Log logger = LogFactory.getLog(getClass());
@@ -181,6 +153,7 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
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;
@@ -191,7 +164,36 @@ 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...)
*/
@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;
}
}
protected enum AspectJAnnotationType {
AtPointcut,
AtBefore,
AtAfter,
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@@ -63,31 +63,31 @@ public interface AspectJAdvisorFactory {
/**
* Build Spring AOP Advisors for all annotated At-AspectJ methods
* on the specified aspect instance.
* @param aif the aspect instance factory (not the aspect instance itself
* in order to avoid eager instantiation)
* @param aspectInstanceFactory the aspect instance factory
* (not the aspect instance itself in order to avoid eager instantiation)
* @return a list of advisors for this class
*/
List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aif);
List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory);
/**
* Build a Spring AOP Advisor for the given AspectJ advice method.
* @param candidateAdviceMethod the candidate advice method
* @param aif the aspect instance factory
* @param declarationOrderInAspect the declaration order within the aspect
* @param aspectInstanceFactory the aspect instance factory
* @param declarationOrder 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
*/
Advisor getAdvisor(Method candidateAdviceMethod,
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName);
Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrder, String aspectName);
/**
* Build a Spring AOP Advice for the given AspectJ advice method.
* @param candidateAdviceMethod the candidate advice method
* @param pointcut the corresponding AspectJ expression pointcut
* @param aif the aspect instance factory
* @param declarationOrderInAspect the declaration order within the aspect
* @param expressionPointcut the AspectJ expression pointcut
* @param aspectInstanceFactory the aspect instance factory
* @param declarationOrder 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
@@ -98,7 +98,7 @@ public interface AspectJAdvisorFactory {
* @see org.springframework.aop.aspectj.AspectJAfterReturningAdvice
* @see org.springframework.aop.aspectj.AspectJAfterThrowingAdvice
*/
Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut pointcut,
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName);
Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName);
}
@@ -42,6 +42,13 @@ import org.springframework.aop.support.ComposablePointcut;
*/
public class AspectMetadata {
/**
* 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;
/**
* AspectJ reflection information (AspectJ 5 / Java 5 specific).
*/
@@ -54,13 +61,6 @@ public class AspectMetadata {
*/
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,10 +83,10 @@ public class AspectMetadata {
if (ajType == null) {
throw new IllegalArgumentException("Class '" + aspectClass.getName() + "' is not an @AspectJ aspect");
}
this.ajType = ajType;
if (this.ajType.getDeclarePrecedence().length > 0) {
if (ajType.getDeclarePrecedence().length > 0) {
throw new IllegalArgumentException("DeclarePrecendence not presently supported in Spring AOP");
}
this.ajType = ajType;
switch (this.ajType.getPerClause().getKind()) {
case SINGLETON :
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ 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.util.Assert;
import org.springframework.util.ClassUtils;
/**
@@ -66,6 +67,8 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
* @param type the type that should be introspected by AspectJ
*/
public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name, Class<?> type) {
Assert.notNull(beanFactory, "BeanFactory must not be null");
Assert.notNull(name, "Bean name must not be null");
this.beanFactory = beanFactory;
this.name = name;
this.aspectMetadata = new AspectMetadata(type, name);
@@ -79,12 +82,9 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
@Override
public ClassLoader getAspectClassLoader() {
if (this.beanFactory instanceof ConfigurableBeanFactory) {
return ((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader();
}
else {
return ClassUtils.getDefaultClassLoader();
}
return (this.beanFactory instanceof ConfigurableBeanFactory ?
((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() :
ClassUtils.getDefaultClassLoader());
}
@Override
@@ -92,6 +92,11 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
return this.aspectMetadata;
}
public Object getAspectCreationMutex() {
return (this.beanFactory instanceof ConfigurableBeanFactory ?
((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex() : this);
}
/**
* Determine the order for this factory's target aspect, either
* an instance-specific order expressed through implementing the
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,53 +42,55 @@ class InstantiationModelAwarePointcutAdvisorImpl
private final AspectJExpressionPointcut declaredPointcut;
private Pointcut pointcut;
private final Method aspectJAdviceMethod;
private final AspectJAdvisorFactory aspectJAdvisorFactory;
private final MetadataAwareAspectInstanceFactory aspectInstanceFactory;
private final Method method;
private final int declarationOrder;
private final String aspectName;
private final Pointcut pointcut;
private final boolean lazy;
private final AspectJAdvisorFactory atAspectJAdvisorFactory;
private Advice instantiatedAdvice;
private int declarationOrder;
private String aspectName;
private Boolean isBeforeAdvice;
private Boolean isAfterAdvice;
public InstantiationModelAwarePointcutAdvisorImpl(AspectJAdvisorFactory af, AspectJExpressionPointcut ajexp,
MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect, String aspectName) {
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
this.declaredPointcut = ajexp;
this.method = method;
this.atAspectJAdvisorFactory = af;
this.aspectInstanceFactory = aif;
this.declarationOrder = declarationOrderInAspect;
this.declaredPointcut = declaredPointcut;
this.aspectJAdviceMethod = aspectJAdviceMethod;
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
this.aspectInstanceFactory = aspectInstanceFactory;
this.declarationOrder = declarationOrder;
this.aspectName = aspectName;
if (aif.getAspectMetadata().isLazilyInstantiated()) {
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
// Static part of the pointcut is a lazy type.
Pointcut preInstantiationPointcut =
Pointcuts.union(aif.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
// If it's not a dynamic pointcut, it may be optimized out
// by the Spring AOP infrastructure after the first evaluation.
this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aif);
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
}
else {
// A singleton aspect.
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
this.pointcut = declaredPointcut;
this.pointcut = this.declaredPointcut;
this.lazy = false;
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
@@ -142,8 +144,8 @@ class InstantiationModelAwarePointcutAdvisorImpl
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
return this.atAspectJAdvisorFactory.getAdvice(
this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
}
public MetadataAwareAspectInstanceFactory getAspectInstanceFactory() {
@@ -191,7 +193,7 @@ class InstantiationModelAwarePointcutAdvisorImpl
*/
private void determineAdviceType() {
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.method);
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.aspectJAdviceMethod);
if (aspectJAnnotation == null) {
this.isBeforeAdvice = false;
this.isAfterAdvice = false;
@@ -220,7 +222,7 @@ class InstantiationModelAwarePointcutAdvisorImpl
@Override
public String toString() {
return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() +
"]; advice method [" + this.method + "]; perClauseKind=" +
"]; advice method [" + this.aspectJAdviceMethod + "]; perClauseKind=" +
this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind();
}
@@ -256,7 +258,7 @@ class InstantiationModelAwarePointcutAdvisorImpl
}
@Override
public boolean matches(Method method, 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,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,9 +43,13 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
@Override
public synchronized Object getAspectInstance() {
public Object getAspectInstance() {
if (this.materialized == null) {
synchronized (this) {
Object mutex = this;
if (this.maaif instanceof BeanFactoryAspectInstanceFactory) {
mutex = ((BeanFactoryAspectInstanceFactory) this.maaif).getAspectCreationMutex();
}
synchronized (mutex) {
if (this.materialized == null) {
this.materialized = this.maaif.getAspectInstance();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,8 +19,8 @@ package org.springframework.aop.aspectj.annotation;
import org.springframework.beans.factory.BeanFactory;
/**
* AspectInstanceFactory backed by a BeanFactory-provided prototype,
* enforcing prototype semantics.
* {@link org.springframework.aop.aspectj.AspectInstanceFactory} backed by a
* {@link 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}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@@ -77,8 +77,9 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
new Converter<Method, Annotation>() {
@Override
public Annotation convert(Method method) {
AspectJAnnotation<?> annotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
return annotation == null ? null : annotation.getAnnotation();
AspectJAnnotation<?> annotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
return (annotation != null ? annotation.getAnnotation() : null);
}
}));
comparator.addComparator(new ConvertingComparator<Method, String>(
@@ -93,17 +94,17 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) {
final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass();
final String aspectName = maaif.getAspectMetadata().getAspectName();
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
validate(aspectClass);
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
// so that it will only instantiate once.
final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(maaif);
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
final List<Advisor> advisors = new LinkedList<Advisor>();
List<Advisor> advisors = new LinkedList<Advisor>();
for (Method method : getAdvisorMethods(aspectClass)) {
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
@@ -169,18 +170,19 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
@Override
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aif,
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aif.getAspectMetadata().getAspectClass());
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
AspectJExpressionPointcut ajexp =
getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass());
if (ajexp == null) {
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
return new InstantiationModelAwarePointcutAdvisorImpl(
this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName);
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
@@ -189,6 +191,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
if (aspectJAnnotation == null) {
return null;
}
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
@@ -197,10 +200,10 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
@Override
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp,
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) {
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
Class<?> candidateAspectClass = aif.getAspectMetadata().getAspectClass();
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
AspectJAnnotation<?> aspectJAnnotation =
@@ -225,27 +228,32 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
switch (aspectJAnnotation.getAnnotationType()) {
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif);
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif);
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, ajexp, aif);
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, ajexp, aif);
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
case AtAround:
springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif);
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtPointcut:
if (logger.isDebugEnabled()) {
@@ -254,12 +262,12 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
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(declarationOrderInAspect);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
@@ -268,6 +276,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
return springAdvice;
}
/**
* Synthetic advisor that instantiates the aspect.
* Triggered by per-clause pointcut on non-singleton aspect.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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.
@@ -113,7 +113,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
* Create a AdvisedSupport instance with the given parameters.
* @param interfaces the proxied interfaces
*/
public AdvisedSupport(Class<?>[] interfaces) {
public AdvisedSupport(Class<?>... interfaces) {
this();
setInterfaces(interfaces);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,9 +22,9 @@ import org.springframework.aop.TargetSource;
import org.springframework.util.ClassUtils;
/**
* Factory for AOP proxies for programmatic use, rather than via a bean
* factory. This class provides a simple way of obtaining and configuring
* AOP proxies in code.
* Factory for AOP proxies for programmatic use, rather than via declarative
* setup in a bean factory. This class provides a simple way of obtaining
* and configuring AOP proxy instances in custom user code.
*
* @author Rod Johnson
* @author Juergen Hoeller
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,9 +31,12 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.core.task.support.TaskExecutorAdapter;
import org.springframework.lang.UsesJava8;
import org.springframework.util.ClassUtils;
@@ -58,6 +61,15 @@ import org.springframework.util.concurrent.ListenableFuture;
*/
public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
/**
* The default name of the {@link TaskExecutor} bean to pick up: "taskExecutor".
* <p>Note that the initial lookup happens by type; this is just the fallback
* in case of multiple executor beans found in the context.
* @since 4.2.6
*/
public static final String DEFAULT_TASK_EXECUTOR_BEAN_NAME = "taskExecutor";
// Java 8's CompletableFuture type present?
private static final boolean completableFuturePresent = ClassUtils.isPresent(
"java.util.concurrent.CompletableFuture", AsyncExecutionInterceptor.class.getClassLoader());
@@ -67,7 +79,7 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
private final Map<Method, AsyncTaskExecutor> executors = new ConcurrentHashMap<Method, AsyncTaskExecutor>(16);
private Executor defaultExecutor;
private volatile Executor defaultExecutor;
private AsyncUncaughtExceptionHandler exceptionHandler;
@@ -75,10 +87,22 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
/**
* Create a new {@link AsyncExecutionAspectSupport}, using the provided default
* executor unless individual async methods indicate via qualifier that a more
* specific executor should be used.
* @param defaultExecutor the executor to use when executing asynchronous methods
* Create a new instance with a default {@link AsyncUncaughtExceptionHandler}.
* @param defaultExecutor the {@code Executor} (typically a Spring {@code AsyncTaskExecutor}
* or {@link java.util.concurrent.ExecutorService}) to delegate to, unless a more specific
* executor has been requested via a qualifier on the async method, in which case the
* executor will be looked up at invocation time against the enclosing bean factory
*/
public AsyncExecutionAspectSupport(Executor defaultExecutor) {
this(defaultExecutor, new SimpleAsyncUncaughtExceptionHandler());
}
/**
* Create a new {@link AsyncExecutionAspectSupport} with the given exception handler.
* @param defaultExecutor the {@code Executor} (typically a Spring {@code AsyncTaskExecutor}
* or {@link java.util.concurrent.ExecutorService}) to delegate to, unless a more specific
* executor has been requested via a qualifier on the async method, in which case the
* executor will be looked up at invocation time against the enclosing bean factory
* @param exceptionHandler the {@link AsyncUncaughtExceptionHandler} to use
*/
public AsyncExecutionAspectSupport(Executor defaultExecutor, AsyncUncaughtExceptionHandler exceptionHandler) {
@@ -86,23 +110,16 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
this.exceptionHandler = exceptionHandler;
}
/**
* Create a new instance with a default {@link AsyncUncaughtExceptionHandler}.
*/
public AsyncExecutionAspectSupport(Executor defaultExecutor) {
this(defaultExecutor, new SimpleAsyncUncaughtExceptionHandler());
}
/**
* Supply the executor to be used when executing async methods.
* @param defaultExecutor the {@code Executor} (typically a Spring {@code
* AsyncTaskExecutor} or {@link java.util.concurrent.ExecutorService}) to delegate to
* unless a more specific executor has been requested via a qualifier on the async
* method, in which case the executor will be looked up at invocation time against the
* enclosing bean factory.
* @see #getExecutorQualifier
* @param defaultExecutor the {@code Executor} (typically a Spring {@code AsyncTaskExecutor}
* or {@link java.util.concurrent.ExecutorService}) to delegate to, unless a more specific
* executor has been requested via a qualifier on the async method, in which case the
* executor will be looked up at invocation time against the enclosing bean factory
* @see #getExecutorQualifier(Method)
* @see #setBeanFactory(BeanFactory)
* @see #getDefaultExecutor(BeanFactory)
*/
public void setExecutor(Executor defaultExecutor) {
this.defaultExecutor = defaultExecutor;
@@ -117,7 +134,10 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
}
/**
* Set the {@link BeanFactory} to be used when looking up executors by qualifier.
* Set the {@link BeanFactory} to be used when looking up executors by qualifier
* or when relying on the default executor lookup algorithm.
* @see #findQualifiedExecutor(BeanFactory, String)
* @see #getDefaultExecutor(BeanFactory)
*/
@Override
public void setBeanFactory(BeanFactory beanFactory) {
@@ -128,26 +148,32 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
/**
* Determine the specific executor to use when executing the given method.
* Should preferably return an {@link AsyncListenableTaskExecutor} implementation.
* @return the executor to use (or {@code null}, but just if no default executor has been set)
* @return the executor to use (or {@code null}, but just if no default executor is available)
*/
protected AsyncTaskExecutor determineAsyncExecutor(Method method) {
AsyncTaskExecutor executor = this.executors.get(method);
if (executor == null) {
Executor executorToUse = this.defaultExecutor;
Executor targetExecutor;
String qualifier = getExecutorQualifier(method);
if (StringUtils.hasLength(qualifier)) {
if (this.beanFactory == null) {
throw new IllegalStateException("BeanFactory must be set on " + getClass().getSimpleName() +
" to access qualified executor '" + qualifier + "'");
}
executorToUse = BeanFactoryAnnotationUtils.qualifiedBeanOfType(
this.beanFactory, Executor.class, qualifier);
targetExecutor = findQualifiedExecutor(this.beanFactory, qualifier);
}
else if (executorToUse == null) {
else {
targetExecutor = this.defaultExecutor;
if (targetExecutor == null) {
synchronized (this.executors) {
if (this.defaultExecutor == null) {
this.defaultExecutor = getDefaultExecutor(this.beanFactory);
}
targetExecutor = this.defaultExecutor;
}
}
}
if (targetExecutor == null) {
return null;
}
executor = (executorToUse instanceof AsyncListenableTaskExecutor ?
(AsyncListenableTaskExecutor) executorToUse : new TaskExecutorAdapter(executorToUse));
executor = (targetExecutor instanceof AsyncListenableTaskExecutor ?
(AsyncListenableTaskExecutor) targetExecutor : new TaskExecutorAdapter(targetExecutor));
this.executors.put(method, executor);
}
return executor;
@@ -160,11 +186,69 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
* been specified and that the {@linkplain #setExecutor(Executor) default executor}
* should be used.
* @param method the method to inspect for executor qualifier metadata
* @return the qualifier if specified, otherwise empty string or {@code null}
* @return the qualifier if specified, otherwise empty String or {@code null}
* @see #determineAsyncExecutor(Method)
* @see #findQualifiedExecutor(BeanFactory, String)
*/
protected abstract String getExecutorQualifier(Method method);
/**
* Retrieve a target executor for the given qualifier.
* @param qualifier the qualifier to resolve
* @return the target executor, or {@code null} if none available
* @since 4.2.6
* @see #getExecutorQualifier(Method)
*/
protected Executor findQualifiedExecutor(BeanFactory beanFactory, String qualifier) {
if (beanFactory == null) {
throw new IllegalStateException("BeanFactory must be set on " + getClass().getSimpleName() +
" to access qualified executor '" + qualifier + "'");
}
return BeanFactoryAnnotationUtils.qualifiedBeanOfType(beanFactory, Executor.class, qualifier);
}
/**
* Retrieve or build a default executor for this advice instance.
* An executor returned from here will be cached for further use.
* <p>The default implementation searches for a unique {@link TaskExecutor} bean
* in the context, or for an {@link Executor} bean named "taskExecutor" otherwise.
* If neither of the two is resolvable, this implementation will return {@code null}.
* @param beanFactory the BeanFactory to use for a default executor lookup
* @return the default executor, or {@code null} if none available
* @since 4.2.6
* @see #findQualifiedExecutor(BeanFactory, String)
* @see #DEFAULT_TASK_EXECUTOR_BEAN_NAME
*/
protected Executor getDefaultExecutor(BeanFactory beanFactory) {
if (beanFactory != null) {
try {
// Search for TaskExecutor bean... not plain Executor since that would
// match with ScheduledExecutorService as well, which is unusable for
// our purposes here. TaskExecutor is more clearly designed for it.
return beanFactory.getBean(TaskExecutor.class);
}
catch (NoUniqueBeanDefinitionException ex) {
try {
return beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class);
}
catch (NoSuchBeanDefinitionException ex2) {
if (logger.isInfoEnabled()) {
logger.info("More than one TaskExecutor bean found within the context, and none is named " +
"'taskExecutor'. Mark one of them as primary or name it 'taskExecutor' (possibly " +
"as an alias) in order to use it for async processing.");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
logger.debug("Could not find default TaskExecutor bean", ex);
// Giving up -> either using local default executor or none at all...
logger.info("No TaskExecutor bean found for async processing");
}
}
return null;
}
/**
* Delegate for actually executing the given task with the chosen executor.
* @param task the task to execute
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,9 +26,11 @@ import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.Ordered;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.util.ClassUtils;
/**
@@ -65,22 +67,27 @@ import org.springframework.util.ClassUtils;
*/
public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport implements MethodInterceptor, Ordered {
/**
* Create a new instance with a default {@link AsyncUncaughtExceptionHandler}.
* @param defaultExecutor the {@link Executor} (typically a Spring {@link AsyncTaskExecutor}
* or {@link java.util.concurrent.ExecutorService}) to delegate to;
* as of 4.2.6, a local executor for this interceptor will be built otherwise
*/
public AsyncExecutionInterceptor(Executor defaultExecutor) {
super(defaultExecutor);
}
/**
* Create a new {@code AsyncExecutionInterceptor}.
* @param defaultExecutor the {@link Executor} (typically a Spring {@link AsyncTaskExecutor}
* or {@link java.util.concurrent.ExecutorService}) to delegate to
* or {@link java.util.concurrent.ExecutorService}) to delegate to;
* as of 4.2.6, a local executor for this interceptor will be built otherwise
* @param exceptionHandler the {@link AsyncUncaughtExceptionHandler} to use
*/
public AsyncExecutionInterceptor(Executor defaultExecutor, AsyncUncaughtExceptionHandler exceptionHandler) {
super(defaultExecutor, exceptionHandler);
}
/**
* Create a new instance with a default {@link AsyncUncaughtExceptionHandler}.
*/
public AsyncExecutionInterceptor(Executor defaultExecutor) {
super(defaultExecutor);
}
/**
* Intercept the given method invocation, submit the actual calling of the method to
@@ -136,6 +143,20 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport imple
return null;
}
/**
* This implementation searches for a unique {@link org.springframework.core.task.TaskExecutor}
* bean in the context, or for an {@link Executor} bean named "taskExecutor" otherwise.
* If neither of the two is resolvable (e.g. if no {@code BeanFactory} was configured at all),
* this implementation falls back to a newly created {@link SimpleAsyncTaskExecutor} instance
* for local use if no default could be found.
* @see #DEFAULT_TASK_EXECUTOR_BEAN_NAME
*/
@Override
protected Executor getDefaultExecutor(BeanFactory beanFactory) {
Executor defaultExecutor = super.getDefaultExecutor(beanFactory);
return (defaultExecutor != null ? defaultExecutor : new SimpleAsyncTaskExecutor());
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@@ -91,17 +91,17 @@ public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher
}
@Override
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
++this.evaluations;
public boolean matches(Method method, Class<?> targetClass, Object... args) {
this.evaluations++;
ControlFlow cflow = ControlFlowFactory.createControlFlow();
return (this.methodName != null) ? cflow.under(this.clazz, this.methodName) : cflow.under(this.clazz);
return (this.methodName != null ? cflow.under(this.clazz, this.methodName) : cflow.under(this.clazz));
}
/**
* It's useful to know how many times we've fired, for optimization.
*/
public int getEvaluations() {
return evaluations;
return this.evaluations;
}
@@ -115,6 +115,7 @@ public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher
return this;
}
@Override
public boolean equals(Object other) {
if (this == other) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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.
@@ -138,7 +138,7 @@ public abstract class MethodMatchers {
}
@Override
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
public boolean matches(Method method, Class<?> targetClass, Object... args) {
return this.mm1.matches(method, targetClass, args) || this.mm2.matches(method, targetClass, args);
}
@@ -245,7 +245,7 @@ public abstract class MethodMatchers {
}
@Override
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
public boolean matches(Method method, Class<?> targetClass, Object... args) {
// Because a dynamic intersection may be composed of a static and dynamic part,
// we must avoid calling the 3-arg matches method on a dynamic matcher, as
// it will probably be an unsupported operation.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -71,7 +71,7 @@ public abstract class Pointcuts {
* @param args arguments to the method
* @return whether there's a runtime match
*/
public static boolean matches(Pointcut pointcut, Method method, Class<?> targetClass, Object[] args) {
public static boolean matches(Pointcut pointcut, Method method, Class<?> targetClass, Object... args) {
Assert.notNull(pointcut, "Pointcut must not be null");
if (pointcut == Pointcut.TRUE) {
return true;
@@ -98,9 +98,9 @@ public abstract class Pointcuts {
@Override
public boolean matches(Method method, Class<?> targetClass) {
return method.getName().startsWith("set") &&
method.getParameterTypes().length == 1 &&
method.getReturnType() == Void.TYPE;
return (method.getName().startsWith("set") &&
method.getParameterTypes().length == 1 &&
method.getReturnType() == Void.TYPE);
}
private Object readResolve() {
@@ -119,8 +119,8 @@ public abstract class Pointcuts {
@Override
public boolean matches(Method method, Class<?> targetClass) {
return method.getName().startsWith("get") &&
method.getParameterTypes().length == 0;
return (method.getName().startsWith("get") &&
method.getParameterTypes().length == 0);
}
private Object readResolve() {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@@ -32,7 +32,7 @@ public abstract class StaticMethodMatcher implements MethodMatcher {
}
@Override
public final boolean matches(Method method, Class<?> targetClass, Object[] args) {
public final boolean matches(Method method, Class<?> targetClass, Object... args) {
// should never be invoked because isRuntime() returns false
throw new UnsupportedOperationException("Illegal MethodMatcher usage");
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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.
@@ -53,17 +53,15 @@ public final class AspectJExpressionPointcutTests {
private Method setSomeNumber;
private Method isPostProcessed;
@Before
public void setUp() throws NoSuchMethodException {
getAge = TestBean.class.getMethod("getAge", (Class<?>[])null);
setAge = TestBean.class.getMethod("setAge", new Class[]{int.class});
setSomeNumber = TestBean.class.getMethod("setSomeNumber", new Class[]{Number.class});
isPostProcessed = TestBean.class.getMethod("isPostProcessed", (Class[]) null);
getAge = TestBean.class.getMethod("getAge");
setAge = TestBean.class.getMethod("setAge", int.class);
setSomeNumber = TestBean.class.getMethod("setSomeNumber", Number.class);
}
@Test
public void testMatchExplicit() {
String expression = "execution(int org.springframework.tests.sample.beans.TestBean.getAge())";
@@ -111,21 +109,9 @@ public final class AspectJExpressionPointcutTests {
testThisOrTarget("target");
}
public static class OtherIOther implements IOther {
@Override
public void absquatulate() {
// Empty
}
}
/**
* This and target are equivalent. Really instanceof pointcuts.
* @param which this or target
* @throws Exception
* @throws NoSuchMethodException
* @throws SecurityException
*/
private void testThisOrTarget(String which) throws SecurityException, NoSuchMethodException {
String matchesTestBean = which + "(org.springframework.tests.sample.beans.TestBean)";
@@ -138,11 +124,8 @@ public final class AspectJExpressionPointcutTests {
assertTrue(testBeanPc.matches(TestBean.class));
assertTrue(testBeanPc.matches(getAge, TestBean.class));
assertTrue(iOtherPc.matches(OtherIOther.class.getMethod("absquatulate", (Class<?>[])null),
OtherIOther.class));
assertFalse(testBeanPc.matches(OtherIOther.class.getMethod("absquatulate", (Class<?>[])null),
OtherIOther.class));
assertTrue(iOtherPc.matches(OtherIOther.class.getMethod("absquatulate"), OtherIOther.class));
assertFalse(testBeanPc.matches(OtherIOther.class.getMethod("absquatulate"), OtherIOther.class));
}
@Test
@@ -171,8 +154,7 @@ public final class AspectJExpressionPointcutTests {
assertEquals(matchSubpackages, withinBeansPc.matches(
DeepBean.class.getMethod("aMethod", String.class), DeepBean.class));
assertFalse(withinBeansPc.matches(String.class));
assertFalse(withinBeansPc.matches(OtherIOther.class.getMethod("absquatulate", (Class<?>[])null),
OtherIOther.class));
assertFalse(withinBeansPc.matches(OtherIOther.class.getMethod("absquatulate"), OtherIOther.class));
}
@Test
@@ -183,7 +165,7 @@ public final class AspectJExpressionPointcutTests {
fail();
}
catch (IllegalStateException ex) {
assertTrue(ex.getMessage().indexOf("expression") != -1);
assertTrue(ex.getMessage().contains("expression"));
}
}
@@ -195,7 +177,7 @@ public final class AspectJExpressionPointcutTests {
fail();
}
catch (IllegalStateException ex) {
assertTrue(ex.getMessage().indexOf("expression") != -1);
assertTrue(ex.getMessage().contains("expression"));
}
}
@@ -207,7 +189,7 @@ public final class AspectJExpressionPointcutTests {
fail();
}
catch (IllegalStateException ex) {
assertTrue(ex.getMessage().indexOf("expression") != -1);
assertTrue(ex.getMessage().contains("expression"));
}
}
@@ -226,10 +208,10 @@ public final class AspectJExpressionPointcutTests {
//assertDoesNotMatchStringClass(classFilter);
assertTrue("Should match with setSomeNumber with Double input",
methodMatcher.matches(setSomeNumber, TestBean.class, new Object[]{new Double(12)}));
methodMatcher.matches(setSomeNumber, TestBean.class, new Double(12)));
assertFalse("Should not match setSomeNumber with Integer input",
methodMatcher.matches(setSomeNumber, TestBean.class, new Object[]{new Integer(11)}));
assertFalse("Should not match getAge", methodMatcher.matches(getAge, TestBean.class, null));
methodMatcher.matches(setSomeNumber, TestBean.class, new Integer(11)));
assertFalse("Should not match getAge", methodMatcher.matches(getAge, TestBean.class));
assertTrue("Should be a runtime match", methodMatcher.isRuntime());
}
@@ -281,7 +263,6 @@ public final class AspectJExpressionPointcutTests {
}
catch (IllegalArgumentException ex) {
assertTrue(true);
System.out.println(ex.getMessage());
}
}
@@ -326,16 +307,14 @@ public final class AspectJExpressionPointcutTests {
@Test
public void testAndSubstitution() {
Pointcut pc = getPointcut("execution(* *(..)) and args(String)");
PointcutExpression expr =
((AspectJExpressionPointcut) pc).getPointcutExpression();
PointcutExpression expr = ((AspectJExpressionPointcut) pc).getPointcutExpression();
assertEquals("execution(* *(..)) && args(String)",expr.getPointcutExpression());
}
@Test
public void testMultipleAndSubstitutions() {
Pointcut pc = getPointcut("execution(* *(..)) and args(String) and this(Object)");
PointcutExpression expr =
((AspectJExpressionPointcut) pc).getPointcutExpression();
PointcutExpression expr = ((AspectJExpressionPointcut) pc).getPointcutExpression();
assertEquals("execution(* *(..)) && args(String) && this(Object)",expr.getPointcutExpression());
}
@@ -344,6 +323,15 @@ public final class AspectJExpressionPointcutTests {
pointcut.setExpression(expression);
return pointcut;
}
public static class OtherIOther implements IOther {
@Override
public void absquatulate() {
// Empty
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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.
@@ -36,7 +36,7 @@ import static org.junit.Assert.*;
* @author Rod Johnson
* @author Chris Beams
*/
public final class TigerAspectJExpressionPointcutTests {
public class TigerAspectJExpressionPointcutTests {
// TODO factor into static in AspectJExpressionPointcut
private Method getAge;
@@ -46,7 +46,7 @@ public final class TigerAspectJExpressionPointcutTests {
@Before
public void setUp() throws NoSuchMethodException {
getAge = TestBean.class.getMethod("getAge", (Class[]) null);
getAge = TestBean.class.getMethod("getAge");
// Assumes no overloading
for (Method m : HasGeneric.class.getMethods()) {
methodsOnHasGeneric.put(m.getName(), m);
@@ -54,18 +54,6 @@ public final class TigerAspectJExpressionPointcutTests {
}
public static class HasGeneric {
public void setFriends(List<TestBean> friends) {
}
public void setEnemies(List<TestBean> enemies) {
}
public void setPartners(List<?> partners) {
}
public void setPhoneNumbers(List<String> numbers) {
}
}
@Test
public void testMatchGenericArgument() {
String expression = "execution(* set*(java.util.List<org.springframework.tests.sample.beans.TestBean>) )";
@@ -132,15 +120,12 @@ public final class TigerAspectJExpressionPointcutTests {
public void testMatchAnnotationOnClassWithSubpackageWildcard() throws SecurityException, NoSuchMethodException {
String expression = "within(@(test.annotation..*) *)";
AspectJExpressionPointcut springAnnotatedPc = testMatchAnnotationOnClass(expression);
assertFalse(springAnnotatedPc.matches(TestBean.class.getMethod("setName", String.class),
TestBean.class));
assertTrue(springAnnotatedPc.matches(SpringAnnotated.class.getMethod("foo", (Class[]) null),
SpringAnnotated.class));
assertFalse(springAnnotatedPc.matches(TestBean.class.getMethod("setName", String.class), TestBean.class));
assertTrue(springAnnotatedPc.matches(SpringAnnotated.class.getMethod("foo"), SpringAnnotated.class));
expression = "within(@(test.annotation.transaction..*) *)";
AspectJExpressionPointcut springTxAnnotatedPc = testMatchAnnotationOnClass(expression);
assertFalse(springTxAnnotatedPc.matches(SpringAnnotated.class.getMethod("foo", (Class[]) null),
SpringAnnotated.class));
assertFalse(springTxAnnotatedPc.matches(SpringAnnotated.class.getMethod("foo"), SpringAnnotated.class));
}
@Test
@@ -154,7 +139,7 @@ public final class TigerAspectJExpressionPointcutTests {
ajexp.setExpression(expression);
assertFalse(ajexp.matches(getAge, TestBean.class));
assertTrue(ajexp.matches(HasTransactionalAnnotation.class.getMethod("foo", (Class[]) null), HasTransactionalAnnotation.class));
assertTrue(ajexp.matches(HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
assertTrue(ajexp.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
assertTrue(ajexp.matches(BeanB.class.getMethod("setName", String.class), BeanB.class));
assertFalse(ajexp.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
@@ -168,10 +153,10 @@ public final class TigerAspectJExpressionPointcutTests {
ajexp.setExpression(expression);
assertFalse(ajexp.matches(getAge, TestBean.class));
assertFalse(ajexp.matches(HasTransactionalAnnotation.class.getMethod("foo", (Class[]) null), HasTransactionalAnnotation.class));
assertFalse(ajexp.matches(HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
assertFalse(ajexp.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
assertFalse(ajexp.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
assertTrue(ajexp.matches(BeanA.class.getMethod("getAge", (Class[]) null), BeanA.class));
assertTrue(ajexp.matches(BeanA.class.getMethod("getAge"), BeanA.class));
assertFalse(ajexp.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
}
@@ -182,10 +167,10 @@ public final class TigerAspectJExpressionPointcutTests {
anySpringMethodAnnotation.setExpression(expression);
assertFalse(anySpringMethodAnnotation.matches(getAge, TestBean.class));
assertFalse(anySpringMethodAnnotation.matches(HasTransactionalAnnotation.class.getMethod("foo", (Class[]) null), HasTransactionalAnnotation.class));
assertFalse(anySpringMethodAnnotation.matches(HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
assertFalse(anySpringMethodAnnotation.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
assertFalse(anySpringMethodAnnotation.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
assertTrue(anySpringMethodAnnotation.matches(BeanA.class.getMethod("getAge", (Class[]) null), BeanA.class));
assertTrue(anySpringMethodAnnotation.matches(BeanA.class.getMethod("getAge"), BeanA.class));
assertFalse(anySpringMethodAnnotation.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
}
@@ -196,10 +181,10 @@ public final class TigerAspectJExpressionPointcutTests {
takesSpringAnnotatedArgument2.setExpression(expression);
assertFalse(takesSpringAnnotatedArgument2.matches(getAge, TestBean.class));
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("foo", (Class[]) null), HasTransactionalAnnotation.class));
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("getAge", (Class[]) null), BeanA.class));
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("getAge"), BeanA.class));
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
assertTrue(takesSpringAnnotatedArgument2.matches(
@@ -213,8 +198,7 @@ public final class TigerAspectJExpressionPointcutTests {
assertFalse(takesSpringAnnotatedArgument2.matches(
ProcessesSpringAnnotatedParameters.class.getMethod("takesNoAnnotatedParameters", TestBean.class, BeanA.class),
ProcessesSpringAnnotatedParameters.class,
new Object[] { new TestBean(), new BeanA()})
ProcessesSpringAnnotatedParameters.class, new TestBean(), new BeanA())
);
}
@@ -225,10 +209,10 @@ public final class TigerAspectJExpressionPointcutTests {
takesSpringAnnotatedArgument2.setExpression(expression);
assertFalse(takesSpringAnnotatedArgument2.matches(getAge, TestBean.class));
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("foo", (Class[]) null), HasTransactionalAnnotation.class));
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("getAge", (Class[]) null), BeanA.class));
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("getAge"), BeanA.class));
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
assertTrue(takesSpringAnnotatedArgument2.matches(
@@ -240,6 +224,19 @@ public final class TigerAspectJExpressionPointcutTests {
}
public static class HasGeneric {
public void setFriends(List<TestBean> friends) {
}
public void setEnemies(List<TestBean> enemies) {
}
public void setPartners(List<?> partners) {
}
public void setPhoneNumbers(List<String> numbers) {
}
}
public static class ProcessesSpringAnnotatedParameters {
public void takesAnnotatedParameters(TestBean tb, SpringAnnotated sa) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.aop.aspectj.annotation;
import java.io.FileNotFoundException;
@@ -961,7 +962,7 @@ abstract class AbstractMakeModifiable {
private Method getGetterFromSetter(Method setter) {
String getterName = setter.getName().replaceFirst("set", "get");
try {
return setter.getDeclaringClass().getMethod(getterName, (Class[]) null);
return setter.getDeclaringClass().getMethod(getterName);
}
catch (NoSuchMethodException ex) {
// must be write only
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,18 +31,21 @@ import static org.junit.Assert.*;
* @author Rod Johnson
* @author Chris Beams
*/
public final class AspectJPointcutAdvisorTests {
public class AspectJPointcutAdvisorTests {
private final AspectJAdvisorFactory af = new ReflectiveAspectJAdvisorFactory();
private AspectJAdvisorFactory af = new ReflectiveAspectJAdvisorFactory();
@Test
public void testSingleton() throws SecurityException, NoSuchMethodException {
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
ajexp.setExpression(AspectJExpressionPointcutTests.MATCH_ALL_METHODS);
InstantiationModelAwarePointcutAdvisorImpl ajpa = new InstantiationModelAwarePointcutAdvisorImpl(af, ajexp,
new SingletonMetadataAwareAspectInstanceFactory(new AbstractAspectJAdvisorFactoryTests.ExceptionAspect(null),"someBean"),
TestBean.class.getMethod("getAge", (Class[]) null),1,"someBean");
InstantiationModelAwarePointcutAdvisorImpl ajpa = new InstantiationModelAwarePointcutAdvisorImpl(
ajexp, TestBean.class.getMethod("getAge"), af,
new SingletonMetadataAwareAspectInstanceFactory(new AbstractAspectJAdvisorFactoryTests.ExceptionAspect(null), "someBean"),
1, "someBean");
assertSame(Pointcut.TRUE, ajpa.getAspectMetadata().getPerClausePointcut());
assertFalse(ajpa.isPerInstance());
}
@@ -52,34 +55,35 @@ public final class AspectJPointcutAdvisorTests {
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
ajexp.setExpression(AspectJExpressionPointcutTests.MATCH_ALL_METHODS);
InstantiationModelAwarePointcutAdvisorImpl ajpa = new InstantiationModelAwarePointcutAdvisorImpl(af, ajexp,
new SingletonMetadataAwareAspectInstanceFactory(new PerTargetAspect(),"someBean"), null, 1, "someBean");
InstantiationModelAwarePointcutAdvisorImpl ajpa = new InstantiationModelAwarePointcutAdvisorImpl(
ajexp, TestBean.class.getMethod("getAge"), af,
new SingletonMetadataAwareAspectInstanceFactory(new PerTargetAspect(), "someBean"),
1, "someBean");
assertNotSame(Pointcut.TRUE, ajpa.getAspectMetadata().getPerClausePointcut());
assertTrue(ajpa.getAspectMetadata().getPerClausePointcut() instanceof AspectJExpressionPointcut);
assertTrue(ajpa.isPerInstance());
assertTrue(ajpa.getAspectMetadata().getPerClausePointcut().getClassFilter().matches(TestBean.class));
assertFalse(ajpa.getAspectMetadata().getPerClausePointcut().getMethodMatcher().matches(
TestBean.class.getMethod("getAge", (Class[]) null),
TestBean.class));
TestBean.class.getMethod("getAge"), TestBean.class));
assertTrue(ajpa.getAspectMetadata().getPerClausePointcut().getMethodMatcher().matches(
TestBean.class.getMethod("getSpouse", (Class[]) null),
TestBean.class));
TestBean.class.getMethod("getSpouse"), TestBean.class));
}
@Test(expected=AopConfigException.class)
@Test(expected = AopConfigException.class)
public void testPerCflowTarget() {
testIllegalInstantiationModel(AbstractAspectJAdvisorFactoryTests.PerCflowAspect.class);
}
@Test(expected=AopConfigException.class)
@Test(expected = AopConfigException.class)
public void testPerCflowBelowTarget() {
testIllegalInstantiationModel(AbstractAspectJAdvisorFactoryTests.PerCflowBelowAspect.class);
}
private void testIllegalInstantiationModel(Class<?> c) throws AopConfigException {
new AspectMetadata(c,"someBean");
new AspectMetadata(c, "someBean");
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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.
@@ -37,7 +37,7 @@ public final class MethodInvocationTests {
@Test
public void testValidInvocation() throws Throwable {
Method m = Object.class.getMethod("hashCode", (Class[]) null);
Method m = Object.class.getMethod("hashCode");
Object proxy = new Object();
final Object returnValue = new Object();
List<Object> is = new LinkedList<Object>();
@@ -67,7 +67,7 @@ public final class MethodInvocationTests {
};
List<Object> is = new LinkedList<Object>();
Method m = Object.class.getMethod("hashCode", (Class[]) null);
Method m = Object.class.getMethod("hashCode");
Object proxy = new Object();
ReflectiveMethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, m, null, null, is);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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.
@@ -78,7 +78,7 @@ public final class ThrowsAdviceInterceptorTests {
ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
FileNotFoundException ex = new FileNotFoundException();
MethodInvocation mi = mock(MethodInvocation.class);
given(mi.getMethod()).willReturn(Object.class.getMethod("hashCode", (Class[]) null));
given(mi.getMethod()).willReturn(Object.class.getMethod("hashCode"));
given(mi.getThis()).willReturn(new Object());
given(mi.proceed()).willThrow(ex);
try {
@@ -140,12 +140,15 @@ public final class ThrowsAdviceInterceptorTests {
assertEquals(1, th.getCalls("remoteException"));
}
@SuppressWarnings("serial")
static class MyThrowsHandler extends MethodCounter implements ThrowsAdvice {
// Full method signature
public void afterThrowing(Method m, Object[] args, Object target, IOException ex) {
count("ioException");
}
public void afterThrowing(RemoteException ex) throws Throwable {
count("remoteException");
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@@ -54,8 +54,8 @@ public abstract class AbstractRegexpMethodPointcutTests {
}
protected void noPatternSuppliedTests(AbstractRegexpMethodPointcut rpc) throws Exception {
assertFalse(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), String.class));
assertFalse(rpc.matches(Object.class.getMethod("wait", (Class[]) null), Object.class));
assertFalse(rpc.matches(Object.class.getMethod("hashCode"), String.class));
assertFalse(rpc.matches(Object.class.getMethod("wait"), Object.class));
assertEquals(0, rpc.getPatterns().length);
}
@@ -69,38 +69,38 @@ public abstract class AbstractRegexpMethodPointcutTests {
protected void exactMatchTests(AbstractRegexpMethodPointcut rpc) throws Exception {
// assumes rpc.setPattern("java.lang.Object.hashCode");
assertTrue(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), String.class));
assertTrue(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), Object.class));
assertFalse(rpc.matches(Object.class.getMethod("wait", (Class[]) null), Object.class));
assertTrue(rpc.matches(Object.class.getMethod("hashCode"), String.class));
assertTrue(rpc.matches(Object.class.getMethod("hashCode"), Object.class));
assertFalse(rpc.matches(Object.class.getMethod("wait"), Object.class));
}
@Test
public void testSpecificMatch() throws Exception {
rpc.setPattern("java.lang.String.hashCode");
assertTrue(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), String.class));
assertFalse(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), Object.class));
assertTrue(rpc.matches(Object.class.getMethod("hashCode"), String.class));
assertFalse(rpc.matches(Object.class.getMethod("hashCode"), Object.class));
}
@Test
public void testWildcard() throws Exception {
rpc.setPattern(".*Object.hashCode");
assertTrue(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), Object.class));
assertFalse(rpc.matches(Object.class.getMethod("wait", (Class[]) null), Object.class));
assertTrue(rpc.matches(Object.class.getMethod("hashCode"), Object.class));
assertFalse(rpc.matches(Object.class.getMethod("wait"), Object.class));
}
@Test
public void testWildcardForOneClass() throws Exception {
rpc.setPattern("java.lang.Object.*");
assertTrue(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), String.class));
assertTrue(rpc.matches(Object.class.getMethod("wait", (Class[]) null), String.class));
assertTrue(rpc.matches(Object.class.getMethod("hashCode"), String.class));
assertTrue(rpc.matches(Object.class.getMethod("wait"), String.class));
}
@Test
public void testMatchesObjectClass() throws Exception {
rpc.setPattern("java.lang.Object.*");
assertTrue(rpc.matches(Exception.class.getMethod("hashCode", (Class[]) null), IOException.class));
assertTrue(rpc.matches(Exception.class.getMethod("hashCode"), IOException.class));
// Doesn't match a method from Throwable
assertFalse(rpc.matches(Exception.class.getMethod("getMessage", (Class[]) null), Exception.class));
assertFalse(rpc.matches(Exception.class.getMethod("getMessage"), Exception.class));
}
@Test
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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.
@@ -32,7 +32,7 @@ import static org.junit.Assert.*;
* @author Rod Johnson
* @author Chris Beams
*/
public final class ComposablePointcutTests {
public class ComposablePointcutTests {
public static MethodMatcher GETTER_METHOD_MATCHER = new StaticMethodMatcher() {
@Override
@@ -62,11 +62,12 @@ public final class ComposablePointcutTests {
}
};
@Test
public void testMatchAll() throws NoSuchMethodException {
Pointcut pc = new ComposablePointcut();
assertTrue(pc.getClassFilter().matches(Object.class));
assertTrue(pc.getMethodMatcher().matches(Object.class.getMethod("hashCode", (Class[]) null), Exception.class));
assertTrue(pc.getMethodMatcher().matches(Object.class.getMethod("hashCode"), Exception.class));
}
@Test
@@ -93,23 +94,23 @@ public final class ComposablePointcutTests {
public void testUnionMethodMatcher() {
// Matches the getAge() method in any class
ComposablePointcut pc = new ComposablePointcut(ClassFilter.TRUE, GET_AGE_METHOD_MATCHER);
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class, null));
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class));
pc.union(GETTER_METHOD_MATCHER);
// Should now match all getter methods
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class, null));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class, null));
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class));
pc.union(ABSQUATULATE_METHOD_MATCHER);
// Should now match absquatulate() as well
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class, null));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class, null));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class));
// But it doesn't match everything
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_SET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_SET_AGE, TestBean.class));
}
@Test
@@ -124,9 +125,9 @@ public final class ComposablePointcutTests {
assertTrue(pc.getMethodMatcher().matches(PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class));
pc.intersection(GET_AGE_METHOD_MATCHER);
// Use the Pointcuts matches method
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class, null));
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class));
}
@Test
@@ -153,4 +154,5 @@ public final class ComposablePointcutTests {
assertEquals(pc1, pc2);
assertEquals(pc1.hashCode(), pc2.hashCode());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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.
@@ -32,7 +32,7 @@ import static org.junit.Assert.*;
* @author Juergen Hoeller
* @author Chris Beams
*/
public final class MethodMatchersTests {
public class MethodMatchersTests {
private final Method EXCEPTION_GETMESSAGE;
@@ -44,10 +44,10 @@ public final class MethodMatchersTests {
public MethodMatchersTests() throws Exception {
EXCEPTION_GETMESSAGE = Exception.class.getMethod("getMessage", (Class[]) null);
ITESTBEAN_GETAGE = ITestBean.class.getMethod("getAge", (Class[]) null);
ITESTBEAN_SETAGE = ITestBean.class.getMethod("setAge", new Class[] { int.class });
IOTHER_ABSQUATULATE = IOther.class.getMethod("absquatulate", (Class[]) null);
EXCEPTION_GETMESSAGE = Exception.class.getMethod("getMessage");
ITESTBEAN_GETAGE = ITestBean.class.getMethod("getAge");
ITESTBEAN_SETAGE = ITestBean.class.getMethod("setAge", int.class);
IOTHER_ABSQUATULATE = IOther.class.getMethod("absquatulate");
}
@@ -82,12 +82,12 @@ public final class MethodMatchersTests {
MethodMatcher intersection = MethodMatchers.intersection(mm1, mm2);
assertTrue("Intersection is a dynamic matcher", intersection.isRuntime());
assertTrue("2Matched setAge method", intersection.matches(ITESTBEAN_SETAGE, TestBean.class));
assertTrue("3Matched setAge method", intersection.matches(ITESTBEAN_SETAGE, TestBean.class, new Object[] { new Integer(5) }));
assertTrue("3Matched setAge method", intersection.matches(ITESTBEAN_SETAGE, TestBean.class, new Integer(5)));
// Knock out dynamic part
intersection = MethodMatchers.intersection(intersection, new TestDynamicMethodMatcherWhichDoesNotMatch());
assertTrue("Intersection is a dynamic matcher", intersection.isRuntime());
assertTrue("2Matched setAge method", intersection.matches(ITESTBEAN_SETAGE, TestBean.class));
assertFalse("3 - not Matched setAge method", intersection.matches(ITESTBEAN_SETAGE, TestBean.class, new Object[] { new Integer(5) }));
assertFalse("3 - not Matched setAge method", intersection.matches(ITESTBEAN_SETAGE, TestBean.class, new Integer(5)));
}
@Test
@@ -125,18 +125,20 @@ public final class MethodMatchersTests {
}
}
private static class TestDynamicMethodMatcherWhichMatches extends DynamicMethodMatcher {
@Override
public boolean matches(Method m, Class<?> targetClass, Object[] args) {
public boolean matches(Method m, Class<?> targetClass, Object... args) {
return true;
}
}
private static class TestDynamicMethodMatcherWhichDoesNotMatch extends DynamicMethodMatcher {
@Override
public boolean matches(Method m, Class<?> targetClass, Object[] args) {
public boolean matches(Method m, Class<?> targetClass, Object... args) {
return false;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,7 +30,7 @@ import static org.junit.Assert.*;
* @author Rod Johnson
* @author Chris Beams
*/
public final class PointcutsTests {
public class PointcutsTests {
public static Method TEST_BEAN_SET_AGE;
public static Method TEST_BEAN_GET_AGE;
@@ -39,10 +39,10 @@ public final class PointcutsTests {
static {
try {
TEST_BEAN_SET_AGE = TestBean.class.getMethod("setAge", new Class[] { int.class });
TEST_BEAN_GET_AGE = TestBean.class.getMethod("getAge", (Class[]) null);
TEST_BEAN_GET_NAME = TestBean.class.getMethod("getName", (Class[]) null);
TEST_BEAN_ABSQUATULATE = TestBean.class.getMethod("absquatulate", (Class[]) null);
TEST_BEAN_SET_AGE = TestBean.class.getMethod("setAge", int.class);
TEST_BEAN_GET_AGE = TestBean.class.getMethod("getAge");
TEST_BEAN_GET_NAME = TestBean.class.getMethod("getName");
TEST_BEAN_ABSQUATULATE = TestBean.class.getMethod("absquatulate");
}
catch (Exception ex) {
throw new RuntimeException("Shouldn't happen: error in test suite");
@@ -125,22 +125,22 @@ public final class PointcutsTests {
@Test
public void testTrue() {
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_GET_AGE, TestBean.class, null));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_GET_AGE, TestBean.class, null));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_GET_AGE, TestBean.class));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_ABSQUATULATE, TestBean.class));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_GET_AGE, TestBean.class));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_ABSQUATULATE, TestBean.class));
}
@Test
public void testMatches() {
assertTrue(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertFalse(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertFalse(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertTrue(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertTrue(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
assertFalse(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_ABSQUATULATE, TestBean.class));
assertFalse(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
assertTrue(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_ABSQUATULATE, TestBean.class));
}
/**
@@ -149,29 +149,29 @@ public final class PointcutsTests {
@Test
public void testUnionOfSettersAndGetters() {
Pointcut union = Pointcuts.union(allClassGetterPointcut, allClassSetterPointcut);
assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class));
}
@Test
public void testUnionOfSpecificGetters() {
Pointcut union = Pointcuts.union(allClassGetAgePointcut, allClassGetNamePointcut);
assertFalse(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_NAME, TestBean.class, null));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_NAME, TestBean.class, null));
assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertFalse(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_NAME, TestBean.class));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_NAME, TestBean.class));
assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class));
// Union with all setters
union = Pointcuts.union(union, allClassSetterPointcut);
assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_NAME, TestBean.class, null));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_NAME, TestBean.class, null));
assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_NAME, TestBean.class));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_NAME, TestBean.class));
assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class));
assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
}
/**
@@ -180,16 +180,16 @@ public final class PointcutsTests {
*/
@Test
public void testUnionOfAllSettersAndSubclassSetters() {
assertFalse(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertTrue(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_SET_AGE, MyTestBean.class, new Object[] { new Integer(6)}));
assertFalse(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
assertTrue(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_SET_AGE, MyTestBean.class, new Integer(6)));
assertFalse(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_GET_AGE, TestBean.class));
Pointcut union = Pointcuts.union(myTestBeanSetterPointcut, allClassGetterPointcut);
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class, null));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, MyTestBean.class, null));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, MyTestBean.class));
// Still doesn't match superclass setter
assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, MyTestBean.class, new Object[] { new Integer(6)}));
assertFalse(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, MyTestBean.class, new Integer(6)));
assertFalse(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
}
/**
@@ -198,44 +198,44 @@ public final class PointcutsTests {
*/
@Test
public void testIntersectionOfSpecificGettersAndSubclassGetters() {
assertTrue(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_AGE, TestBean.class, null));
assertTrue(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_AGE, MyTestBean.class, null));
assertFalse(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_NAME, TestBean.class, null));
assertFalse(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_AGE, TestBean.class, null));
assertTrue(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_NAME, MyTestBean.class, null));
assertTrue(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_AGE, MyTestBean.class, null));
assertTrue(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_AGE, TestBean.class));
assertTrue(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_AGE, MyTestBean.class));
assertFalse(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_NAME, TestBean.class));
assertFalse(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_AGE, TestBean.class));
assertTrue(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_NAME, MyTestBean.class));
assertTrue(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_AGE, MyTestBean.class));
Pointcut intersection = Pointcuts.intersection(allClassGetAgePointcut, myTestBeanGetterPointcut);
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, TestBean.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBean.class, null));
assertTrue(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBean.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, TestBean.class));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBean.class));
assertTrue(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBean.class));
// Matches subclass of MyTestBean
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBeanSubclass.class, null));
assertTrue(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBeanSubclass.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBeanSubclass.class));
assertTrue(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBeanSubclass.class));
// Now intersection with MyTestBeanSubclass getters should eliminate MyTestBean target
intersection = Pointcuts.intersection(intersection, myTestBeanSubclassGetterPointcut);
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, TestBean.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBean.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBean.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, TestBean.class));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBean.class));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBean.class));
// Still matches subclass of MyTestBean
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBeanSubclass.class, null));
assertTrue(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBeanSubclass.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBeanSubclass.class));
assertTrue(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBeanSubclass.class));
// Now union with all TestBean methods
Pointcut union = Pointcuts.union(intersection, allTestBeanMethodsPointcut);
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_NAME, TestBean.class, null));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(union, TEST_BEAN_GET_NAME, MyTestBean.class, null));
assertFalse(Pointcuts.matches(union, TEST_BEAN_GET_AGE, MyTestBean.class, null));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_NAME, TestBean.class));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(union, TEST_BEAN_GET_NAME, MyTestBean.class));
assertFalse(Pointcuts.matches(union, TEST_BEAN_GET_AGE, MyTestBean.class));
// Still matches subclass of MyTestBean
assertFalse(Pointcuts.matches(union, TEST_BEAN_GET_NAME, MyTestBeanSubclass.class, null));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, MyTestBeanSubclass.class, null));
assertFalse(Pointcuts.matches(union, TEST_BEAN_GET_NAME, MyTestBeanSubclass.class));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, MyTestBeanSubclass.class));
assertTrue(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, MyTestBean.class, null));
assertTrue(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class));
assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, MyTestBean.class));
}
@@ -245,9 +245,9 @@ public final class PointcutsTests {
@Test
public void testSimpleIntersection() {
Pointcut intersection = Pointcuts.intersection(allClassGetterPointcut, allClassSetterPointcut);
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_ABSQUATULATE, TestBean.class));
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,47 +17,49 @@
package org.springframework.scheduling.aspectj;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.aop.interceptor.AsyncExecutionAspectSupport;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.util.concurrent.ListenableFuture;
/**
* Abstract aspect that routes selected methods asynchronously.
*
* <p>This aspect needs to be injected with an implementation of
* {@link Executor} to activate it for a specific thread pool.
* Otherwise it will simply delegate all calls synchronously.
* <p>This aspect needs to be injected with an implementation of a task-oriented
* {@link java.util.concurrent.Executor} to activate it for a specific thread pool,
* or with a {@link org.springframework.beans.factory.BeanFactory} for default
* executor lookup. Otherwise it will simply delegate all calls synchronously.
*
* @author Ramnivas Laddad
* @author Juergen Hoeller
* @author Chris Beams
* @author Stephane Nicoll
* @since 3.0.5
* @see #setExecutor
* @see #setBeanFactory
* @see #getDefaultExecutor
*/
public abstract aspect AbstractAsyncExecutionAspect extends AsyncExecutionAspectSupport {
/**
* Create an {@code AnnotationAsyncExecutionAspect} with a {@code null} default
* executor, which should instead be set via {@code #aspectOf} and
* {@link #setExecutor(Executor)}. The same applies for {@link #setExceptionHandler}
* Create an {@code AnnotationAsyncExecutionAspect} with a {@code null}
* default executor, which should instead be set via {@code #aspectOf} and
* {@link #setExecutor}. The same applies for {@link #setExceptionHandler}.
*/
public AbstractAsyncExecutionAspect() {
super(null);
}
/**
* Apply around advice to methods matching the {@link #asyncMethod()} pointcut,
* submit the actual calling of the method to the correct task executor and return
* immediately to the caller.
* @return {@link Future} if the original method returns {@code Future}; {@code null}
* otherwise.
* @return {@link Future} if the original method returns {@code Future};
* {@code null} otherwise
*/
@SuppressAjWarnings("adviceDidNotMatch")
Object around() : asyncMethod() {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,9 +33,17 @@ import org.springframework.scheduling.annotation.Async;
* on the return type. If, however, a class marked with {@code @Async} contains a method
* that violates this constraint, it produces only a warning.
*
* <p>This aspect needs to be injected with an implementation of a task-oriented
* {@link java.util.concurrent.Executor} to activate it for a specific thread pool,
* or with a {@link org.springframework.beans.factory.BeanFactory} for default
* executor lookup. Otherwise it will simply delegate all calls synchronously.
*
* @author Ramnivas Laddad
* @author Chris Beams
* @since 3.0.5
* @see #setExecutor
* @see #setBeanFactory
* @see #getDefaultExecutor
*/
public aspect AnnotationAsyncExecutionAspect extends AbstractAsyncExecutionAspect {
@@ -74,7 +82,6 @@ public aspect AnnotationAsyncExecutionAspect extends AbstractAsyncExecutionAspec
declare warning:
execution(!(void || Future+) (@Async *).*(..)):
"Methods in a class marked with @Async that do not return void or Future will " +
"be routed synchronously";
"Methods in a class marked with @Async that do not return void or Future will be routed synchronously";
}
@@ -31,7 +31,6 @@ import groovy.lang.GroovyObjectSupport;
import groovy.lang.GroovyShell;
import groovy.lang.GroovySystem;
import groovy.lang.MetaClass;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import org.codehaus.groovy.runtime.InvokerHelper;
@@ -337,8 +336,8 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
if (uri == null) {
throw new IllegalArgumentException("Namespace definition must supply a non-null URI");
}
NamespaceHandler namespaceHandler = this.groovyDslXmlBeanDefinitionReader.getNamespaceHandlerResolver().resolve(
uri);
NamespaceHandler namespaceHandler =
this.groovyDslXmlBeanDefinitionReader.getNamespaceHandlerResolver().resolve(uri);
if (namespaceHandler == null) {
throw new BeanDefinitionParsingException(new Problem("No namespace handler found for URI: " + uri,
new Location(new DescriptiveResource(("Groovy")))));
@@ -375,7 +374,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
throw new IllegalArgumentException("Argument to ref() is not a valid bean or was not found");
if (args[0] instanceof RuntimeBeanReference) {
refName = ((RuntimeBeanReference)args[0]).getBeanName();
refName = ((RuntimeBeanReference) args[0]).getBeanName();
}
else {
refName = args[0].toString();
@@ -388,7 +387,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
}
return new RuntimeBeanReference(refName, parentRef);
}
else if (this.namespaces.containsKey(name) && args.length > 0 && (args[0] instanceof Closure)) {
else if (this.namespaces.containsKey(name) && args.length > 0 && args[0] instanceof Closure) {
GroovyDynamicElementReader reader = createDynamicElementReader(name);
reader.invokeMethod("doCall", args);
}
@@ -396,7 +395,8 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
// abstract bean definition
return invokeBeanDefiningMethod(name, args);
}
else if (args.length > 0 && (args[0] instanceof Class || args[0] instanceof RuntimeBeanReference || args[0] instanceof Map)) {
else if (args.length > 0 &&
(args[0] instanceof Class || args[0] instanceof RuntimeBeanReference || args[0] instanceof Map)) {
return invokeBeanDefiningMethod(name, args);
}
else if (args.length > 1 && args[args.length -1] instanceof Closure) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -87,10 +87,10 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
}
}
private int autoGrowCollectionLimit = Integer.MAX_VALUE;
/** The wrapped object */
private Object object;
private Object wrappedObject;
private String nestedPath = "";
@@ -204,23 +204,23 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
public void setWrappedInstance(Object object, String nestedPath, Object rootObject) {
Assert.notNull(object, "Target object must not be null");
if (object.getClass() == javaUtilOptionalClass) {
this.object = OptionalUnwrapper.unwrap(object);
this.wrappedObject = OptionalUnwrapper.unwrap(object);
}
else {
this.object = object;
this.wrappedObject = object;
}
this.nestedPath = (nestedPath != null ? nestedPath : "");
this.rootObject = (!"".equals(this.nestedPath) ? rootObject : this.object);
this.rootObject = (!"".equals(this.nestedPath) ? rootObject : this.wrappedObject);
this.nestedPropertyAccessors = null;
this.typeConverterDelegate = new TypeConverterDelegate(this, this.object);
this.typeConverterDelegate = new TypeConverterDelegate(this, this.wrappedObject);
}
public final Object getWrappedInstance() {
return this.object;
return this.wrappedObject;
}
public final Class<?> getWrappedClass() {
return (this.object != null ? this.object.getClass() : null);
return (this.wrappedObject != null ? this.wrappedObject.getClass() : null);
}
/**
@@ -303,7 +303,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
catch (NotReadablePropertyException ex) {
throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
"Cannot access indexed value in property referenced " +
"in indexed property path '" + propertyName + "'", ex);
"in indexed property path '" + propertyName + "'", ex);
}
// Set value for last key.
String key = tokens.keys[tokens.keys.length - 1];
@@ -318,7 +318,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
else {
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName,
"Cannot access indexed value in property referenced " +
"in indexed property path '" + propertyName + "': returned null");
"in indexed property path '" + propertyName + "': returned null");
}
}
if (propValue.getClass().isArray()) {
@@ -367,8 +367,8 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
catch (NullPointerException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Cannot set element with index " + index + " in List of size " +
size + ", accessed using property path '" + propertyName +
"': List does not support filling up gaps with null elements");
size + ", accessed using property path '" + propertyName +
"': List does not support filling up gaps with null elements");
}
}
list.add(convertedValue);
@@ -405,7 +405,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
else {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Property referenced in indexed property path '" + propertyName +
"' is neither an array nor a List nor a Map; returned value was [" + propValue + "]");
"' is neither an array nor a List nor a Map; returned value was [" + propValue + "]");
}
}
@@ -451,7 +451,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
}
pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
}
ph.setValue(object, valueToApply);
ph.setValue(this.wrappedObject, valueToApply);
}
catch (TypeMismatchException ex) {
throw ex;
@@ -953,10 +953,9 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
tokens.actualName = (actualName != null ? actualName : propertyName);
tokens.canonicalName = tokens.actualName;
if (!keys.isEmpty()) {
tokens.canonicalName +=
PROPERTY_KEY_PREFIX +
StringUtils.collectionToDelimitedString(keys, PROPERTY_KEY_SUFFIX + PROPERTY_KEY_PREFIX) +
PROPERTY_KEY_SUFFIX;
tokens.canonicalName += PROPERTY_KEY_PREFIX +
StringUtils.collectionToDelimitedString(keys, PROPERTY_KEY_SUFFIX + PROPERTY_KEY_PREFIX) +
PROPERTY_KEY_SUFFIX;
tokens.keys = StringUtils.toStringArray(keys);
}
return tokens;
@@ -965,8 +964,8 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
@Override
public String toString() {
StringBuilder sb = new StringBuilder(getClass().getName());
if (this.object != null) {
sb.append(": wrapping object [").append(ObjectUtils.identityToString(this.object)).append("]");
if (this.wrappedObject != null) {
sb.append(": wrapping object [").append(ObjectUtils.identityToString(this.wrappedObject)).append("]");
}
else {
sb.append(": no wrapped object set");
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -278,8 +278,12 @@ public abstract class BeanUtils {
targetMethod = method;
numMethodsFoundWithCurrentMinimumArgs = 1;
}
else {
if (targetMethod.getParameterTypes().length == numParams) {
else if (!method.isBridge() && targetMethod.getParameterTypes().length == numParams) {
if (targetMethod.isBridge()) {
// Prefer regular method over bridge...
targetMethod = method;
}
else {
// Additional candidate with same length
numMethodsFoundWithCurrentMinimumArgs++;
}
@@ -289,7 +293,7 @@ public abstract class BeanUtils {
if (numMethodsFoundWithCurrentMinimumArgs > 1) {
throw new IllegalArgumentException("Cannot resolve method '" + methodName +
"' to a unique method. Attempted to resolve to overloaded method with " +
"the least number of parameters, but there were " +
"the least number of parameters but there were " +
numMethodsFoundWithCurrentMinimumArgs + " candidates.");
}
return targetMethod;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,6 +48,19 @@ import java.beans.PropertyDescriptor;
*/
public interface BeanWrapper extends ConfigurablePropertyAccessor {
/**
* Specify a limit for array and collection auto-growing.
* <p>Default is unlimited on a plain BeanWrapper.
* @since 4.1
*/
void setAutoGrowCollectionLimit(int autoGrowCollectionLimit);
/**
* Return the limit for array and collection auto-growing.
* @since 4.1
*/
int getAutoGrowCollectionLimit();
/**
* Return the bean instance wrapped by this object, if any.
* @return the bean instance, or {@code null} if none set
@@ -78,15 +91,4 @@ public interface BeanWrapper extends ConfigurablePropertyAccessor {
*/
PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException;
/**
* Specify a limit for array and collection auto-growing.
* <p>Default is unlimited on a plain BeanWrapper.
*/
void setAutoGrowCollectionLimit(int autoGrowCollectionLimit);
/**
* Return the limit for array and collection auto-growing.
*/
int getAutoGrowCollectionLimit();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -136,7 +136,30 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
@Override
public void setWrappedInstance(Object object, String nestedPath, Object rootObject) {
super.setWrappedInstance(object, nestedPath, rootObject);
setIntrospectionClass(getWrappedInstance().getClass());
setIntrospectionClass(getWrappedClass());
}
/**
* Set the class to introspect.
* Needs to be called when the target object changes.
* @param clazz the class to introspect
*/
protected void setIntrospectionClass(Class<?> clazz) {
if (this.cachedIntrospectionResults != null && this.cachedIntrospectionResults.getBeanClass() != clazz) {
this.cachedIntrospectionResults = null;
}
}
/**
* Obtain a lazily initializted CachedIntrospectionResults instance
* for the wrapped object.
*/
private CachedIntrospectionResults getCachedIntrospectionResults() {
Assert.state(getWrappedInstance() != null, "BeanWrapper does not hold a bean instance");
if (this.cachedIntrospectionResults == null) {
this.cachedIntrospectionResults = CachedIntrospectionResults.forClass(getWrappedClass());
}
return this.cachedIntrospectionResults;
}
/**
@@ -155,30 +178,6 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
return this.acc;
}
/**
* Set the class to introspect.
* Needs to be called when the target object changes.
* @param clazz the class to introspect
*/
protected void setIntrospectionClass(Class<?> clazz) {
if (this.cachedIntrospectionResults != null &&
!clazz.equals(this.cachedIntrospectionResults.getBeanClass())) {
this.cachedIntrospectionResults = null;
}
}
/**
* Obtain a lazily initializted CachedIntrospectionResults instance
* for the wrapped object.
*/
private CachedIntrospectionResults getCachedIntrospectionResults() {
Assert.state(getWrappedInstance() != null, "BeanWrapper does not hold a bean instance");
if (this.cachedIntrospectionResults == null) {
this.cachedIntrospectionResults = CachedIntrospectionResults.forClass(getWrappedClass());
}
return this.cachedIntrospectionResults;
}
/**
* Convert the given value for the specified property to the latter's type.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -109,6 +109,7 @@ public interface ListableBeanFactory extends BeanFactory {
* @return the names of beans (or objects created by FactoryBeans) matching
* the given object type (including subclasses), or an empty array if none
* @since 4.2
* @see #isTypeMatch(String, ResolvableType)
* @see FactoryBean#getObjectType
* @see BeanFactoryUtils#beanNamesForTypeIncludingAncestors(ListableBeanFactory, ResolvableType)
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -56,7 +56,7 @@ public class UnsatisfiedDependencyException extends BeanCreationException {
public UnsatisfiedDependencyException(
String resourceDescription, String beanName, String propertyName, BeansException ex) {
this(resourceDescription, beanName, propertyName, (ex != null ? ": " + ex.getMessage() : ""));
this(resourceDescription, beanName, propertyName, (ex != null ? ex.getMessage() : ""));
initCause(ex);
}
@@ -88,7 +88,7 @@ public class UnsatisfiedDependencyException extends BeanCreationException {
public UnsatisfiedDependencyException(
String resourceDescription, String beanName, int ctorArgIndex, Class<?> ctorArgType, BeansException ex) {
this(resourceDescription, beanName, ctorArgIndex, ctorArgType, (ex != null ? ": " + ex.getMessage() : ""));
this(resourceDescription, beanName, ctorArgIndex, ctorArgType, (ex != null ? ex.getMessage() : ""));
initCause(ex);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -196,6 +196,7 @@ public class DependencyDescriptor implements Serializable {
* Optionally set the concrete class that contains this dependency.
* This may differ from the class that declares the parameter/field in that
* it may be a subclass thereof, potentially substituting type variables.
* @since 4.0
*/
public void setContainingClass(Class<?> containingClass) {
this.containingClass = containingClass;
@@ -206,6 +207,7 @@ public class DependencyDescriptor implements Serializable {
/**
* Build a ResolvableType object for the wrapped parameter/field.
* @since 4.0
*/
public ResolvableType getResolvableType() {
return (this.field != null ? ResolvableType.forField(this.field, this.nestingLevel, this.containingClass) :
@@ -217,6 +219,7 @@ public class DependencyDescriptor implements Serializable {
* <p>This is {@code false} by default but may be overridden to return {@code true} in order
* to suggest to a {@link org.springframework.beans.factory.support.AutowireCandidateResolver}
* that a fallback match is acceptable as well.
* @since 4.0
*/
public boolean fallbackMatchAllowed() {
return false;
@@ -224,6 +227,7 @@ public class DependencyDescriptor implements Serializable {
/**
* Return a variant of this descriptor that is intended for a fallback match.
* @since 4.0
* @see #fallbackMatchAllowed()
*/
public DependencyDescriptor forFallbackMatch() {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -204,7 +204,7 @@ public class FieldRetrievingFactoryBean
// instance field
return this.fieldObject.get(this.targetObject);
}
else{
else {
// class field
return this.fieldObject.get(null);
}
@@ -1475,9 +1475,14 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
logger.debug("Bean currently in creation on FactoryBean type check: " + ex);
}
}
else if (mbd.isLazyInit()) {
if (logger.isDebugEnabled()) {
logger.debug("Bean creation exception on lazy FactoryBean type check: " + ex);
}
}
else {
if (logger.isWarnEnabled()) {
logger.warn("Bean creation exception on FactoryBean type check: " + ex);
logger.warn("Bean creation exception on non-lazy FactoryBean type check: " + ex);
}
}
onSuppressedException(ex);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -166,6 +166,17 @@ public class BeanDefinitionBuilder {
return this;
}
/**
* Add an indexed constructor arg value. The current index is tracked internally
* and all additions are at the present point.
* @deprecated since Spring 2.5, in favor of {@link #addConstructorArgValue}.
* This variant just remains around for Spring Security 2.x compatibility.
*/
@Deprecated
public BeanDefinitionBuilder addConstructorArg(Object value) {
return addConstructorArgValue(value);
}
/**
* Add an indexed constructor arg value. The current index is tracked internally
* and all additions are at the present point.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -300,7 +300,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
}
}
catch (IllegalArgumentException ex) {
throw new BeanDefinitionValidationException("Couldn't find a unique destroy method on bean with name '" +
throw new BeanDefinitionValidationException("Could not find unique destroy method on bean with name '" +
this.beanName + ": " + ex.getMessage());
}
}
@@ -17,7 +17,6 @@
package org.springframework.beans.factory.support;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ package org.springframework.beans.factory.support;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -59,7 +58,7 @@ import org.springframework.util.StringUtils;
public class StaticListableBeanFactory implements ListableBeanFactory {
/** Map from bean name to bean instance */
private final Map<String, Object> beans = new HashMap<String, Object>();
private final Map<String, Object> beans = new LinkedHashMap<String, Object>();
/**
@@ -265,7 +264,7 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
throws BeansException {
boolean isFactoryType = (type != null && FactoryBean.class.isAssignableFrom(type));
Map<String, T> matches = new HashMap<String, T>();
Map<String, T> matches = new LinkedHashMap<String, T>();
for (Map.Entry<String, Object> entry : this.beans.entrySet()) {
String beanName = entry.getKey();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,14 +24,13 @@ import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* {@link java.beans.PropertyEditor} implementation for
* {@link java.beans.PropertyEditor} implementation for standard JDK
* {@link java.util.ResourceBundle ResourceBundles}.
*
* <p>Only supports conversion <i>from</i> a String, but not
* <i>to</i> a String.
* <p>Only supports conversion <i>from</i> a String, but not <i>to</i> a String.
*
* Find below some examples of using this class in a
* (properly configured) Spring container using XML-based metadata:
* Find below some examples of using this class in a (properly configured)
* Spring container using XML-based metadata:
*
* <pre class="code"> &lt;bean id="errorDialog" class="..."&gt;
* &lt;!--
@@ -62,19 +61,20 @@ import org.springframework.util.StringUtils;
* &lt;/property&gt;
* &lt;/bean&gt;</pre>
*
* <p>Please note that this {@link java.beans.PropertyEditor} is
* <b>not</b> registered by default with any of the Spring infrastructure.
* <p>Please note that this {@link java.beans.PropertyEditor} is <b>not</b>
* registered by default with any of the Spring infrastructure.
*
* <p>Thanks to David Leal Valmana for the suggestion and initial prototype.
*
* @author Rick Evans
* @author Juergen Hoeller
* @since 2.0
*/
public class ResourceBundleEditor extends PropertyEditorSupport {
/**
* The separator used to distinguish between the base name and the
* locale (if any) when {@link #setAsText(String) converting from a String}.
* The separator used to distinguish between the base name and the locale
* (if any) when {@link #setAsText(String) converting from a String}.
*/
public static final String BASE_NAME_SEPARATOR = "_";
@@ -82,25 +82,23 @@ public class ResourceBundleEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
Assert.hasText(text, "'text' must not be empty");
ResourceBundle bundle;
String rawBaseName = text.trim();
int indexOfBaseNameSeparator = rawBaseName.indexOf(BASE_NAME_SEPARATOR);
if (indexOfBaseNameSeparator == -1) {
bundle = ResourceBundle.getBundle(rawBaseName);
String name = text.trim();
int separator = name.indexOf(BASE_NAME_SEPARATOR);
if (separator == -1) {
setValue(ResourceBundle.getBundle(name));
}
else {
// it potentially has locale information
String baseName = rawBaseName.substring(0, indexOfBaseNameSeparator);
// The name potentially contains locale information
String baseName = name.substring(0, separator);
if (!StringUtils.hasText(baseName)) {
throw new IllegalArgumentException("Bad ResourceBundle name : received '" + text + "' as argument to 'setAsText(String value)'.");
throw new IllegalArgumentException("Invalid ResourceBundle name: '" + text + "'");
}
String localeString = rawBaseName.substring(indexOfBaseNameSeparator + 1);
String localeString = name.substring(separator + 1);
Locale locale = StringUtils.parseLocaleString(localeString);
bundle = (StringUtils.hasText(localeString))
? ResourceBundle.getBundle(baseName, locale)
: ResourceBundle.getBundle(baseName);
setValue((StringUtils.hasText(localeString)) ? ResourceBundle.getBundle(baseName, locale) :
ResourceBundle.getBundle(baseName));
}
setValue(bundle);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -2890,7 +2890,13 @@ public class DefaultListableBeanFactoryTests {
}
public static class BeanWithDestroyMethod {
public static abstract class BaseClassWithDestroyMethod {
public abstract BaseClassWithDestroyMethod close();
}
public static class BeanWithDestroyMethod extends BaseClassWithDestroyMethod {
private static int closeCount = 0;
@@ -2900,8 +2906,10 @@ public class DefaultListableBeanFactoryTests {
this.inner = inner;
}
public void close() {
@Override
public BeanWithDestroyMethod close() {
closeCount++;
return this;
}
}
@@ -45,6 +45,7 @@ import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.Ordered;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.annotation.Order;
import org.springframework.tests.sample.beans.ITestBean;
@@ -1397,6 +1398,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertSame(1, bean.stringRepositoryMap.size());
assertSame(repo, bean.repositoryMap.get("repo"));
assertSame(repo, bean.stringRepositoryMap.get("repo"));
assertArrayEquals(new String[] {"repo"}, bf.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class)));
}
@Test
@@ -1777,6 +1780,9 @@ public class AutowiredAnnotationBeanPostProcessorTests {
GenericInterface1Impl bean1 = (GenericInterface1Impl) bf.getBean("bean1");
GenericInterface2Impl bean2 = (GenericInterface2Impl) bf.getBean("bean2");
assertSame(bean2, bean1.gi2);
assertArrayEquals(new String[] {"bean1"}, bf.getBeanNamesForType(ResolvableType.forClassWithGenerics(GenericInterface1.class, String.class)));
assertArrayEquals(new String[] {"bean2"}, bf.getBeanNamesForType(ResolvableType.forClassWithGenerics(GenericInterface2.class, String.class)));
}
@Test
@@ -2765,7 +2771,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
public interface GenericInterface1<T> {
public String doSomethingGeneric(T o);
String doSomethingGeneric(T o);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 the original author or authors.
* Copyright 2002-2015 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.
@@ -28,9 +28,10 @@ import static org.junit.Assert.*;
* @author Rick Evans
* @author Chris Beams
*/
public final class ResourceBundleEditorTests {
public class ResourceBundleEditorTests {
private static final String BASE_NAME = ResourceBundleEditorTests.class.getName();
private static final String MESSAGE_KEY = "punk";
@@ -40,7 +41,8 @@ public final class ResourceBundleEditorTests {
editor.setAsText(BASE_NAME);
Object value = editor.getValue();
assertNotNull("Returned ResourceBundle was null (must not be for valid setAsText(..) call).", value);
assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).", value instanceof ResourceBundle);
assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).",
value instanceof ResourceBundle);
ResourceBundle bundle = (ResourceBundle) value;
String string = bundle.getString(MESSAGE_KEY);
assertEquals(MESSAGE_KEY, string);
@@ -52,7 +54,8 @@ public final class ResourceBundleEditorTests {
editor.setAsText(BASE_NAME + "_");
Object value = editor.getValue();
assertNotNull("Returned ResourceBundle was null (must not be for valid setAsText(..) call).", value);
assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).", value instanceof ResourceBundle);
assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).",
value instanceof ResourceBundle);
ResourceBundle bundle = (ResourceBundle) value;
String string = bundle.getString(MESSAGE_KEY);
assertEquals(MESSAGE_KEY, string);
@@ -64,7 +67,8 @@ public final class ResourceBundleEditorTests {
editor.setAsText(BASE_NAME + "Lang" + "_en");
Object value = editor.getValue();
assertNotNull("Returned ResourceBundle was null (must not be for valid setAsText(..) call).", value);
assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).", value instanceof ResourceBundle);
assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).",
value instanceof ResourceBundle);
ResourceBundle bundle = (ResourceBundle) value;
String string = bundle.getString(MESSAGE_KEY);
assertEquals("yob", string);
@@ -76,7 +80,8 @@ public final class ResourceBundleEditorTests {
editor.setAsText(BASE_NAME + "LangCountry" + "_en_GB");
Object value = editor.getValue();
assertNotNull("Returned ResourceBundle was null (must not be for valid setAsText(..) call).", value);
assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).", value instanceof ResourceBundle);
assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).",
value instanceof ResourceBundle);
ResourceBundle bundle = (ResourceBundle) value;
String string = bundle.getString(MESSAGE_KEY);
assertEquals("chav", string);
@@ -88,31 +93,32 @@ public final class ResourceBundleEditorTests {
editor.setAsText(BASE_NAME + "LangCountryDialect" + "_en_GB_GLASGOW");
Object value = editor.getValue();
assertNotNull("Returned ResourceBundle was null (must not be for valid setAsText(..) call).", value);
assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).", value instanceof ResourceBundle);
assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).",
value instanceof ResourceBundle);
ResourceBundle bundle = (ResourceBundle) value;
String string = bundle.getString(MESSAGE_KEY);
assertEquals("ned", string);
}
@Test(expected=IllegalArgumentException.class)
@Test(expected = IllegalArgumentException.class)
public void testSetAsTextWithNull() throws Exception {
ResourceBundleEditor editor = new ResourceBundleEditor();
editor.setAsText(null);
}
@Test(expected=IllegalArgumentException.class)
@Test(expected = IllegalArgumentException.class)
public void testSetAsTextWithEmptyString() throws Exception {
ResourceBundleEditor editor = new ResourceBundleEditor();
editor.setAsText("");
}
@Test(expected=IllegalArgumentException.class)
@Test(expected = IllegalArgumentException.class)
public void testSetAsTextWithWhiteSpaceString() throws Exception {
ResourceBundleEditor editor = new ResourceBundleEditor();
editor.setAsText(" ");
}
@Test(expected=IllegalArgumentException.class)
@Test(expected = IllegalArgumentException.class)
public void testSetAsTextWithJustSeparatorString() throws Exception {
ResourceBundleEditor editor = new ResourceBundleEditor();
editor.setAsText("_");
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,20 +36,21 @@ import org.springframework.beans.factory.parsing.ReaderEventListener;
*/
public class CollectingReaderEventListener implements ReaderEventListener {
private final List defaults = new LinkedList();
private final List<DefaultsDefinition> defaults = new LinkedList<>();
private final Map componentDefinitions = new LinkedHashMap<>(8);
private final Map<String, ComponentDefinition> componentDefinitions = new LinkedHashMap<>(8);
private final Map aliasMap = new LinkedHashMap<>(8);
private final Map<String, List<AliasDefinition>> aliasMap = new LinkedHashMap<>(8);
private final List<ImportDefinition> imports = new LinkedList<>();
private final List imports = new LinkedList();
@Override
public void defaultsRegistered(DefaultsDefinition defaultsDefinition) {
this.defaults.add(defaultsDefinition);
}
public List getDefaults() {
public List<DefaultsDefinition> getDefaults() {
return Collections.unmodifiableList(this.defaults);
}
@@ -59,27 +60,27 @@ public class CollectingReaderEventListener implements ReaderEventListener {
}
public ComponentDefinition getComponentDefinition(String name) {
return (ComponentDefinition) this.componentDefinitions.get(name);
return this.componentDefinitions.get(name);
}
public ComponentDefinition[] getComponentDefinitions() {
Collection collection = this.componentDefinitions.values();
return (ComponentDefinition[]) collection.toArray(new ComponentDefinition[collection.size()]);
Collection<ComponentDefinition> collection = this.componentDefinitions.values();
return collection.toArray(new ComponentDefinition[collection.size()]);
}
@Override
public void aliasRegistered(AliasDefinition aliasDefinition) {
List aliases = (List) this.aliasMap.get(aliasDefinition.getBeanName());
if(aliases == null) {
aliases = new ArrayList();
List<AliasDefinition> aliases = this.aliasMap.get(aliasDefinition.getBeanName());
if (aliases == null) {
aliases = new ArrayList<>();
this.aliasMap.put(aliasDefinition.getBeanName(), aliases);
}
aliases.add(aliasDefinition);
}
public List getAliases(String beanName) {
List aliases = (List) this.aliasMap.get(beanName);
return aliases == null ? null : Collections.unmodifiableList(aliases);
public List<AliasDefinition> getAliases(String beanName) {
List<AliasDefinition> aliases = this.aliasMap.get(beanName);
return (aliases != null ? Collections.unmodifiableList(aliases) : null);
}
@Override
@@ -87,7 +88,7 @@ public class CollectingReaderEventListener implements ReaderEventListener {
this.imports.add(importDefinition);
}
public List getImports() {
public List<ImportDefinition> getImports() {
return Collections.unmodifiableList(this.imports);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -81,7 +81,7 @@ public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, Ini
/**
* Set the name of the EhCache CacheManager (if a specific name is desired).
* @see net.sf.ehcache.CacheManager#setName(String)
* @see net.sf.ehcache.config.Configuration#setName(String)
*/
public void setCacheManagerName(String cacheManagerName) {
this.cacheManagerName = cacheManagerName;
@@ -126,12 +126,17 @@ public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, Ini
@Override
public void afterPropertiesSet() throws CacheException {
logger.info("Initializing EhCache CacheManager");
if (logger.isInfoEnabled()) {
logger.info("Initializing EhCache CacheManager" +
(this.cacheManagerName != null ? " '" + this.cacheManagerName + "'" : ""));
}
Configuration configuration = (this.configLocation != null ?
EhCacheManagerUtils.parseConfiguration(this.configLocation) : ConfigurationFactory.parseConfiguration());
if (this.cacheManagerName != null) {
configuration.setName(this.cacheManagerName);
}
if (this.shared) {
// Old-school EhCache singleton sharing...
// No way to find out whether we actually created a new CacheManager
@@ -178,7 +183,10 @@ public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, Ini
@Override
public void destroy() {
if (this.locallyManaged) {
logger.info("Shutting down EhCache CacheManager");
if (logger.isInfoEnabled()) {
logger.info("Shutting down EhCache CacheManager" +
(this.cacheManagerName != null ? " '" + this.cacheManagerName + "'" : ""));
}
this.cacheManager.shutdown();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -134,7 +134,7 @@ public class TimerManagerTaskScheduler extends TimerManagerAccessor implements T
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(System.currentTimeMillis() - this.timer.getScheduledExecutionTime(), TimeUnit.MILLISECONDS);
return unit.convert(this.timer.getScheduledExecutionTime() - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -237,7 +237,9 @@ public class CronTriggerFactoryBean implements FactoryBean<CronTrigger>, BeanNam
CronTriggerImpl cti = new CronTriggerImpl();
cti.setName(this.name);
cti.setGroup(this.group);
cti.setJobKey(this.jobDetail.getKey());
if (this.jobDetail != null) {
cti.setJobKey(this.jobDetail.getKey());
}
cti.setJobDataMap(this.jobDataMap);
cti.setStartTime(this.startTime);
cti.setCronExpression(this.cronExpression);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,6 @@
package org.springframework.scheduling.quartz;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
@@ -73,43 +72,50 @@ public class ResourceLoaderClassLoadHelper implements ClassLoadHelper {
}
@Override
@SuppressWarnings("rawtypes")
public Class loadClass(String name) throws ClassNotFoundException {
public Class<?> loadClass(String name) throws ClassNotFoundException {
return this.resourceLoader.getClassLoader().loadClass(name);
}
@SuppressWarnings("unchecked")
public <T> Class<? extends T> loadClass(String name, Class<T> clazz) throws ClassNotFoundException {
return loadClass(name);
return (Class<? extends T>) loadClass(name);
}
@Override
public URL getResource(String name) {
Resource resource = this.resourceLoader.getResource(name);
try {
return resource.getURL();
if (resource.exists()) {
try {
return resource.getURL();
}
catch (IOException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Could not load " + resource);
}
return null;
}
}
catch (FileNotFoundException ex) {
return null;
}
catch (IOException ex) {
logger.warn("Could not load " + resource);
return null;
else {
return getClassLoader().getResource(name);
}
}
@Override
public InputStream getResourceAsStream(String name) {
Resource resource = this.resourceLoader.getResource(name);
try {
return resource.getInputStream();
if (resource.exists()) {
try {
return resource.getInputStream();
}
catch (IOException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Could not load " + resource);
}
return null;
}
}
catch (FileNotFoundException ex) {
return null;
}
catch (IOException ex) {
logger.warn("Could not load " + resource);
return null;
else {
return getClassLoader().getResourceAsStream(name);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -228,7 +228,9 @@ public class SimpleTriggerFactoryBean implements FactoryBean<SimpleTrigger>, Bea
SimpleTriggerImpl sti = new SimpleTriggerImpl();
sti.setName(this.name);
sti.setGroup(this.group);
sti.setJobKey(this.jobDetail.getKey());
if (this.jobDetail != null) {
sti.setJobKey(this.jobDetail.getKey());
}
sti.setJobDataMap(this.jobDataMap);
sti.setStartTime(this.startTime);
sti.setRepeatInterval(this.repeatInterval);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -72,8 +72,8 @@ public class SpringBeanJobFactory extends AdaptableJobFactory implements Schedul
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object job = super.createJobInstance(bundle);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(job);
if (isEligibleForPropertyPopulation(bw.getWrappedInstance())) {
if (isEligibleForPropertyPopulation(job)) {
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(job);
MutablePropertyValues pvs = new MutablePropertyValues();
if (this.schedulerContext != null) {
pvs.addPropertyValues(this.schedulerContext);
@@ -0,0 +1,41 @@
/*
* 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
*
* 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.scheduling.quartz;
import java.text.ParseException;
import org.junit.Test;
import org.quartz.CronTrigger;
import static org.junit.Assert.*;
/**
* @author Stephane Nicoll
*/
public class CronTriggerFactoryBeanTests {
@Test
public void createWithoutJobDetail() throws ParseException {
CronTriggerFactoryBean factory = new CronTriggerFactoryBean();
factory.setName("myTrigger");
factory.setCronExpression("0 15 10 ? * *");
factory.afterPropertiesSet();
CronTrigger trigger = factory.getObject();
assertEquals("0 15 10 ? * *", trigger.getCronExpression());
}
}
@@ -0,0 +1,43 @@
/*
* 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
*
* 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.scheduling.quartz;
import java.text.ParseException;
import org.junit.Test;
import org.quartz.SimpleTrigger;
import static org.junit.Assert.*;
/**
* @author Stephane Nicoll
*/
public class SimpleTriggerFactoryBeanTests {
@Test
public void createWithoutJobDetail() throws ParseException {
SimpleTriggerFactoryBean factory = new SimpleTriggerFactoryBean();
factory.setName("myTrigger");
factory.setRepeatCount(5);
factory.setRepeatInterval(1000L);
factory.afterPropertiesSet();
SimpleTrigger trigger = factory.getObject();
assertEquals(5, trigger.getRepeatCount());
assertEquals(1000L, trigger.getRepeatInterval());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,14 +27,16 @@ import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
/**
* Enables Spring's annotation-driven cache management capability, similar to
* the support found in Spring's {@code <cache:*>} XML namespace. To be used together
* Enables Spring's annotation-driven cache management capability, similar to the
* support found in Spring's {@code <cache:*>} XML namespace. To be used together
* with @{@link org.springframework.context.annotation.Configuration Configuration}
* classes as follows:
*
* <pre class="code">
* &#064;Configuration
* &#064;EnableCaching
* public class AppConfig {
*
* &#064;Bean
* public MyService myService() {
* // configure and return a class having &#064;Cacheable methods
@@ -52,11 +54,15 @@ import org.springframework.core.Ordered;
*
* <p>For reference, the example above can be compared to the following Spring XML
* configuration:
*
* <pre class="code">
* {@code
* <beans>
*
* <cache:annotation-driven/>
*
* <bean id="myService" class="com.foo.MyService"/>
*
* <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
* <property name="caches">
* <set>
@@ -66,8 +72,10 @@ import org.springframework.core.Ordered;
* </set>
* </property>
* </bean>
*
* </beans>
* }</pre>
*
* In both of the scenarios above, {@code @EnableCaching} and {@code
* <cache:annotation-driven/>} are responsible for registering the necessary Spring
* components that power annotation-driven cache management, such as the
@@ -90,12 +98,14 @@ import org.springframework.core.Ordered;
*
* <p>For those that wish to establish a more direct relationship between
* {@code @EnableCaching} and the exact cache manager bean to be used,
* the {@link CachingConfigurer} callback interface may be implemented - notice the
* the {@code @Override}-annotated methods below:
* the {@link CachingConfigurer} callback interface may be implemented.
* Notice the the {@code @Override}-annotated methods below:
*
* <pre class="code">
* &#064;Configuration
* &#064;EnableCaching
* public class AppConfig extends CachingConfigurerSupport {
*
* &#064;Bean
* public MyService myService() {
* // configure and return a class having &#064;Cacheable methods
@@ -118,6 +128,7 @@ import org.springframework.core.Ordered;
* return new MyKeyGenerator();
* }
* }</pre>
*
* This approach may be desirable simply because it is more explicit, or it may be
* necessary in order to distinguish between two {@code CacheManager} beans present in the
* same container.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -86,7 +86,10 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria
if (cachings != null) {
ops = lazyInit(ops);
for (Caching caching : cachings) {
ops.addAll(parseCachingAnnotation(ae, cachingConfig, caching));
Collection<CacheOperation> cachingOps = parseCachingAnnotation(ae, cachingConfig, caching);
if (cachingOps != null) {
ops.addAll(cachingOps);
}
}
}
@@ -195,7 +198,7 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria
}
private <A extends Annotation> Collection<A> getAnnotations(AnnotatedElement ae, Class<A> annotationType) {
Collection<A> anns = new ArrayList<A>(2);
Collection<A> anns = new ArrayList<A>(1);
// look at raw annotation
A ann = ae.getAnnotation(annotationType);
@@ -211,7 +214,7 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria
}
}
return (anns.isEmpty() ? null : anns);
return (!anns.isEmpty() ? anns : null);
}
/**
@@ -374,18 +374,15 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
for (CacheOperationContext context : cachePutContexts) {
try {
if (!context.isConditionPassing(ExpressionEvaluator.RESULT_UNAVAILABLE)) {
excluded.add(context);
excluded.add(context);
}
}
catch (VariableNotAvailableException e) {
// Ignoring failure due to missing result, consider the cache put has
// to proceed
// Ignoring failure due to missing result, consider the cache put has to proceed
}
}
// check if all puts have been excluded by condition
return cachePutContexts.size() != excluded.size();
// Check if all puts have been excluded by condition
return (cachePutContexts.size() != excluded.size());
}
private void processCacheEvicts(Collection<CacheOperationContext> contexts, boolean beforeInvocation, Object result) {
@@ -710,4 +707,5 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
return (this.cacheOperation.hashCode() * 31 + this.methodCacheKey.hashCode());
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,8 +21,8 @@ package org.springframework.cache.interceptor;
*
* <p>Does not provide a way to transmit checked exceptions but
* provide a special exception that should be used to wrap any
* exception that was thrown by the underlying invocation. Callers
* are expected to handle this issue type specifically.
* exception that was thrown by the underlying invocation.
* Callers are expected to handle this issue type specifically.
*
* @author Stephane Nicoll
* @since 4.1
@@ -38,11 +38,12 @@ public interface CacheOperationInvoker {
*/
Object invoke() throws ThrowableWrapper;
/**
* Wrap any exception thrown while invoking {@link #invoke()}
* Wrap any exception thrown while invoking {@link #invoke()}.
*/
@SuppressWarnings("serial")
public static class ThrowableWrapper extends RuntimeException {
class ThrowableWrapper extends RuntimeException {
private final Throwable original;
@@ -52,7 +53,7 @@ public interface CacheOperationInvoker {
}
public Throwable getOriginal() {
return original;
return this.original;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,7 +39,8 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
* public MyBean myBean() {
* // instantiate and configure MyBean obj
* return obj;
* }</pre>
* }
* </pre>
*
* <h3>Bean Names</h3>
*
@@ -55,7 +56,8 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
* public MyBean myBean() {
* // instantiate and configure MyBean obj
* return obj;
* }</pre>
* }
* </pre>
*
* <h3>Scope, DependsOn, Primary, and Lazy</h3>
*
@@ -70,7 +72,8 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
* public MyBean myBean() {
* // instantiate and configure MyBean obj
* return obj;
* }</pre>
* }
* </pre>
*
* <h3>{@code @Bean} Methods in {@code @Configuration} Classes</h3>
*
@@ -87,14 +90,17 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
* <pre class="code">
* &#064;Configuration
* public class AppConfig {
*
* &#064;Bean
* public FooService fooService() {
* return new FooService(fooRepository());
* }
*
* &#064;Bean
* public FooRepository fooRepository() {
* return new JdbcFooRepository(dataSource());
* }
*
* // ...
* }</pre>
*
@@ -152,7 +158,8 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
* &#064;Bean
* public static PropertyPlaceholderConfigurer ppc() {
* // instantiate, configure and return ppc ...
* }</pre>
* }
* </pre>
*
* By marking this method as {@code static}, it can be invoked without causing instantiation of its
* declaring {@code @Configuration} class, thus avoiding the above-mentioned lifecycle conflicts.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,17 +29,18 @@ import org.springframework.core.annotation.AnnotationUtils;
class BeanAnnotationHelper {
/**
* Return whether the given method is annotated directly or indirectly with @Bean.
* Return whether the given method is directly or indirectly annotated with
* the {@link Bean} annotation.
*/
public static boolean isBeanAnnotated(Method method) {
return AnnotationUtils.findAnnotation(method, Bean.class) != null;
return (AnnotationUtils.findAnnotation(method, Bean.class) != null);
}
public static String determineBeanNameFor(Method beanMethod) {
// by default the bean name is the name of the @Bean-annotated method
// By default, the bean name is the name of the @Bean-annotated method
String beanName = beanMethod.getName();
// check to see if the user has explicitly set the bean name
// Check to see if the user has explicitly set a custom bean name...
Bean bean = AnnotationUtils.findAnnotation(beanMethod, Bean.class);
if (bean != null && bean.name().length > 0) {
beanName = bean.name()[0];
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -125,10 +125,13 @@ public @interface ComponentScan {
/**
* Specifies which types are eligible for component scanning.
* <p>Further narrows the set of candidate components from everything in
* {@link #basePackages} to everything in the base packages that matches
* the given filter or filters.
* @see #resourcePattern
* <p>Further narrows the set of candidate components from everything in {@link #basePackages}
* to everything in the base packages that matches the given filter or filters.
* <p>Note that these filters will be applied in addition to the default filters, if specified.
* Any type under the specified base packages which matches a given filter will be included,
* even if it does not match the default filters (i.e. is not annotated with {@code @Component}).
* @see #resourcePattern()
* @see #useDefaultFilters()
*/
Filter[] includeFilters() default {};
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,12 +27,14 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* Indicates that a class declares one or more {@link Bean @Bean} methods and may be processed
* by the Spring container to generate bean definitions and service requests for those
* beans at runtime, for example:
* Indicates that a class declares one or more {@link Bean @Bean} methods and
* may be processed by the Spring container to generate bean definitions and
* service requests for those beans at runtime, for example:
*
* <pre class="code">
* &#064;Configuration
* public class AppConfig {
*
* &#064;Bean
* public MyBean myBean() {
* // instantiate, configure and return bean ...
@@ -40,25 +42,28 @@ import org.springframework.stereotype.Component;
* }</pre>
*
* <h2>Bootstrapping {@code @Configuration} classes</h2>
*
* <h3>Via {@code AnnotationConfigApplicationContext}</h3>
*
* {@code @Configuration} classes are typically bootstrapped using either
* {@link AnnotationConfigApplicationContext} or its web-capable variant,
* {@link org.springframework.web.context.support.AnnotationConfigWebApplicationContext
* AnnotationConfigWebApplicationContext}.
* A simple example with the former follows:
* AnnotationConfigWebApplicationContext}. A simple example with the former follows:
*
* <pre class="code">
* AnnotationConfigApplicationContext ctx =
* new AnnotationConfigApplicationContext();
* AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
* ctx.register(AppConfig.class);
* ctx.refresh();
* MyBean myBean = ctx.getBean(MyBean.class);
* // use myBean ...</pre>
* // use myBean ...
* </pre>
*
* See {@link AnnotationConfigApplicationContext} Javadoc for further details and see
* {@link org.springframework.web.context.support.AnnotationConfigWebApplicationContext
* AnnotationConfigWebApplicationContext} for {@code web.xml} configuration instructions.
*
* <h3>Via Spring {@code <beans>} XML</h3>
*
* <p>As an alternative to registering {@code @Configuration} classes directly against an
* {@code AnnotationConfigApplicationContext}, {@code @Configuration} classes may be
* declared as normal {@code <bean>} definitions within Spring XML files:
@@ -74,6 +79,7 @@ import org.springframework.stereotype.Component;
* post processors that facilitate handling {@code @Configuration} classes.
*
* <h3>Via component scanning</h3>
*
* <p>{@code @Configuration} is meta-annotated with {@link Component @Component}, therefore
* {@code @Configuration} classes are candidates for component scanning (typically using
* Spring XML's {@code <context:component-scan/>} element) and therefore may also take
@@ -82,6 +88,7 @@ import org.springframework.stereotype.Component;
* <p>{@code @Configuration} classes may not only be bootstrapped using
* component scanning, but may also themselves <em>configure</em> component scanning using
* the {@link ComponentScan @ComponentScan} annotation:
*
* <pre class="code">
* &#064;Configuration
* &#064;ComponentScan("com.acme.app.services")
@@ -89,18 +96,20 @@ import org.springframework.stereotype.Component;
* // various &#064;Bean definitions ...
* }</pre>
*
* See {@link ComponentScan @ComponentScan} Javadoc for details.
*
* See the {@link ComponentScan @ComponentScan} javadoc for details.
*
* <h2>Working with externalized values</h2>
*
* <h3>Using the {@code Environment} API</h3>
*
* Externalized values may be looked up by injecting the Spring
* {@link org.springframework.core.env.Environment Environment} into a
* {@code @Configuration} class using the {@code @Autowired} or the {@code @Inject}
* annotation:
* {@link org.springframework.core.env.Environment} into a {@code @Configuration}
* class using the {@code @Autowired} or the {@code @Inject} annotation:
*
* <pre class="code">
* &#064;Configuration
* public class AppConfig {
*
* &#064Inject Environment env;
*
* &#064;Bean
@@ -115,10 +124,12 @@ import org.springframework.stereotype.Component;
* source" objects, and {@code @Configuration} classes may contribute property sources to
* the {@code Environment} object using
* the {@link org.springframework.core.env.PropertySources @PropertySources} annotation:
*
* <pre class="code">
* &#064;Configuration
* &#064;PropertySource("classpath:/com/acme/app.properties")
* public class AppConfig {
*
* &#064Inject Environment env;
*
* &#064;Bean
@@ -131,12 +142,15 @@ import org.springframework.stereotype.Component;
* and {@link PropertySource @PropertySource} Javadoc for further details.
*
* <h3>Using the {@code @Value} annotation</h3>
*
* Externalized values may be 'wired into' {@code @Configuration} classes using
* the {@link Value @Value} annotation:
*
* <pre class="code">
* &#064;Configuration
* &#064;PropertySource("classpath:/com/acme/app.properties")
* public class AppConfig {
*
* &#064Value("${bean.name}") String beanName;
*
* &#064;Bean
@@ -155,14 +169,18 @@ import org.springframework.stereotype.Component;
* {@code PropertySourcesPlaceholderConfigurer}.
*
* <h2>Composing {@code @Configuration} classes</h2>
*
* <h3>With the {@code @Import} annotation</h3>
*
* <p>{@code @Configuration} classes may be composed using the {@link Import @Import} annotation,
* not unlike the way that {@code <import>} works in Spring XML. Because
* {@code @Configuration} objects are managed as Spring beans within the container,
* imported configurations may be injected using {@code @Autowired} or {@code @Inject}:
*
* <pre class="code">
* &#064;Configuration
* public class DatabaseConfig {
*
* &#064;Bean
* public DataSource dataSource() {
* // instantiate, configure and return DataSource
@@ -172,6 +190,7 @@ import org.springframework.stereotype.Component;
* &#064;Configuration
* &#064;Import(DatabaseConfig.class)
* public class AppConfig {
*
* &#064Inject DatabaseConfig dataConfig;
*
* &#064;Bean
@@ -188,13 +207,15 @@ import org.springframework.stereotype.Component;
* new AnnotationConfigApplicationContext(AppConfig.class);</pre>
*
* <h3>With the {@code @Profile} annotation</h3>
*
* {@code @Configuration} classes may be marked with the {@link Profile @Profile} annotation to
* indicate they should be processed only if a given profile or profiles are
* <em>active</em>:
* indicate they should be processed only if a given profile or profiles are <em>active</em>:
*
* <pre class="code">
* &#064;Profile("embedded")
* &#064;Configuration
* public class EmbeddedDatabaseConfig {
*
* &#064;Bean
* public DataSource dataSource() {
* // instantiate, configure and return embedded DataSource
@@ -204,25 +225,29 @@ import org.springframework.stereotype.Component;
* &#064;Profile("production")
* &#064;Configuration
* public class ProductionDatabaseConfig {
*
* &#064;Bean
* public DataSource dataSource() {
* // instantiate, configure and return production DataSource
* }
* }</pre>
*
* See {@link Profile @Profile} and {@link org.springframework.core.env.Environment Environment}
* Javadoc for further details.
* See the {@link Profile @Profile} and {@link org.springframework.core.env.Environment}
* javadocs for further details.
*
* <h3>With Spring XML using the {@code @ImportResource} annotation</h3>
*
* As mentioned above, {@code @Configuration} classes may be declared as regular Spring
* {@code <bean>} definitions within Spring XML files. It is also possible to
* import Spring XML configuration files into {@code @Configuration} classes using
* the {@link ImportResource @ImportResource} annotation. Bean definitions imported from XML can be
* injected using {@code @Autowired} or {@code @Inject}:
*
* <pre class="code">
* &#064;Configuration
* &#064;ImportResource("classpath:/com/acme/database-config.xml")
* public class AppConfig {
*
* &#064Inject DataSource dataSource; // from XML
*
* &#064;Bean
@@ -233,10 +258,13 @@ import org.springframework.stereotype.Component;
* }</pre>
*
* <h3>With nested {@code @Configuration} classes</h3>
*
* {@code @Configuration} classes may be nested within one another as follows:
*
* <pre class="code">
* &#064;Configuration
* public class AppConfig {
*
* &#064;Inject DataSource dataSource;
*
* &#064;Bean
@@ -264,6 +292,7 @@ import org.springframework.stereotype.Component;
* enclosing {@code @Configuration} class.
*
* <h2>Configuring lazy initialization</h2>
*
* <p>By default, {@code @Bean} methods will be <em>eagerly instantiated</em> at container
* bootstrap time. To avoid this, {@code @Configuration} may be used in conjunction with
* the {@link Lazy @Lazy} annotation to indicate that all {@code @Bean} methods declared within
@@ -271,9 +300,11 @@ import org.springframework.stereotype.Component;
* individual {@code @Bean} methods as well.
*
* <h2>Testing support for {@code @Configuration} classes</h2>
*
* The Spring <em>TestContext framework</em> available in the {@code spring-test} module
* provides the {@code @ContextConfiguration} annotation, which as of Spring 3.1 can
* accept an array of {@code @Configuration} {@code Class} objects:
*
* <pre class="code">
* &#064;RunWith(SpringJUnit4ClassRunner.class)
* &#064;ContextConfiguration(classes={AppConfig.class, DatabaseConfig.class})
@@ -292,6 +323,7 @@ import org.springframework.stereotype.Component;
* See TestContext framework reference documentation for details.
*
* <h2>Enabling built-in Spring features using {@code @Enable} annotations</h2>
*
* Spring features such as asynchronous method execution, scheduled task execution,
* annotation driven transaction management, and even Spring MVC can be enabled and
* configured from {@code @Configuration}
@@ -304,6 +336,7 @@ import org.springframework.stereotype.Component;
* for details.
*
* <h2>Constraints when authoring {@code @Configuration} classes</h2>
*
* <ul>
* <li>&#064;Configuration classes must be non-final
* <li>&#064;Configuration classes must be non-local (may not be declared within a method)
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -159,7 +159,7 @@ class ConfigurationClassEnhancer {
* Conditional {@link Callback}.
* @see ConditionalCallbackFilter
*/
private static interface ConditionalCallback extends Callback {
private interface ConditionalCallback extends Callback {
boolean isMatch(Method candidateMethod);
}
@@ -343,7 +343,8 @@ class ConfigurationClassEnhancer {
// The factory is calling the bean method in order to instantiate and register the bean
// (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
// create the bean instance.
if (BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
if (logger.isWarnEnabled() &&
BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
logger.warn(String.format("@Bean method %s.%s is non-static and returns an object " +
"assignable to Spring's BeanFactoryPostProcessor interface. This will " +
"result in a failure to process annotations such as @Autowired, " +
@@ -364,8 +365,20 @@ class ConfigurationClassEnhancer {
if (alreadyInCreation) {
beanFactory.setCurrentlyInCreation(beanName, false);
}
Object beanInstance = (!ObjectUtils.isEmpty(beanMethodArgs) ?
beanFactory.getBean(beanName, beanMethodArgs) : beanFactory.getBean(beanName));
boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
if (useArgs && beanFactory.isSingleton(beanName)) {
// Stubbed null arguments just for reference purposes,
// expecting them to be autowired for regular singleton references?
// A safe assumption since @Bean singleton arguments cannot be optional...
for (Object arg : beanMethodArgs) {
if (arg == null) {
useArgs = false;
break;
}
}
}
Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
beanFactory.getBean(beanName));
if (beanInstance != null && !ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
String msg = String.format("@Bean method %s.%s called as a bean reference " +
"for type [%s] but overridden by non-compatible bean instance of type [%s].",
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,10 +18,12 @@ package org.springframework.context.annotation;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -30,7 +32,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -622,7 +623,7 @@ class ConfigurationClassParser {
@SuppressWarnings("serial")
private static class ImportStack extends Stack<ConfigurationClass> implements ImportRegistry {
private static class ImportStack extends ArrayDeque<ConfigurationClass> implements ImportRegistry {
private final MultiValueMap<String, AnnotationMetadata> imports = new LinkedMultiValueMap<String, AnnotationMetadata>();
@@ -647,23 +648,6 @@ class ConfigurationClassParser {
return (!CollectionUtils.isEmpty(list) ? list.get(list.size() - 1) : null);
}
/**
* Simplified contains() implementation that tests to see if any {@link ConfigurationClass}
* exists within this stack that has the same name as <var>elem</var>. Elem must be of
* type ConfigurationClass.
*/
@Override
public boolean contains(Object elem) {
ConfigurationClass configClass = (ConfigurationClass) elem;
Comparator<ConfigurationClass> comparator = new Comparator<ConfigurationClass>() {
@Override
public int compare(ConfigurationClass first, ConfigurationClass second) {
return (first.getMetadata().getClassName().equals(second.getMetadata().getClassName()) ? 0 : 1);
}
};
return (Collections.binarySearch(this, configClass, comparator) != -1);
}
/**
* Given a stack containing (in order)
* <ul>
@@ -883,7 +867,7 @@ class ConfigurationClassParser {
*/
private static class CircularImportProblem extends Problem {
public CircularImportProblem(ConfigurationClass attemptedImport, Stack<ConfigurationClass> importStack) {
public CircularImportProblem(ConfigurationClass attemptedImport, Deque<ConfigurationClass> importStack) {
super(String.format("A circular @Import has been detected: " +
"Illegal attempt by @Configuration class '%s' to import class '%s' as '%s' is " +
"already present in the current import stack %s", importStack.peek().getSimpleName(),
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -382,6 +382,12 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
}
else if (logger.isWarnEnabled() && beanFactory.containsSingleton(beanName)) {
logger.warn("Cannot enhance @Configuration bean definition '" + beanName +
"' since its singleton instance has been created too early. The typical cause " +
"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
"return type: Consider declaring such methods as 'static'.");
}
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ import java.lang.reflect.Method;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
@@ -79,7 +80,12 @@ public class ContextAnnotationAutowireCandidateResolver extends QualifierAnnotat
}
@Override
public Object getTarget() {
return beanFactory.doResolveDependency(descriptor, beanName, null, null);
Object target = beanFactory.doResolveDependency(descriptor, beanName, null, null);
if (target == null) {
throw new NoSuchBeanDefinitionException(descriptor.getDependencyType(),
"Optional dependency not present for lazy injection point");
}
return target;
}
@Override
public void releaseTarget(Object target) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ import java.lang.annotation.Target;
* &#064;Configuration
* &#064;EnableAspectJAutoProxy
* public class AppConfig {
*
* &#064;Bean
* public FooService fooService() {
* return new FooService();
@@ -47,12 +48,14 @@ import java.lang.annotation.Target;
*
* <pre class="code">
* public class FooService {
*
* // various methods
* }</pre>
*
* <pre class="code">
* &#064;Aspect
* public class MyAspect {
*
* &#064;Before("execution(* FooService+.*(..))")
* public void advice() {
* // advise FooService methods as appropriate
@@ -66,6 +69,7 @@ import java.lang.annotation.Target;
* <p>Users can control the type of proxy that gets created for {@code FooService} using
* the {@link #proxyTargetClass()} attribute. The following enables CGLIB-style 'subclass'
* proxies as opposed to the default interface-based JDK proxy approach.
*
* <pre class="code">
* &#064;Configuration
* &#064;EnableAspectJAutoProxy(proxyTargetClass=true)
@@ -75,6 +79,7 @@ import java.lang.annotation.Target;
*
* <p>Note that {@code @Aspect} beans may be component-scanned like any other. Simply
* mark the aspect with both {@code @Aspect} and {@code @Component}:
*
* <pre class="code">
* package com.foo;
*
@@ -86,11 +91,13 @@ import java.lang.annotation.Target;
* public class MyAspect { ... }</pre>
*
* Then use the @{@link ComponentScan} annotation to pick both up:
*
* <pre class="code">
* &#064;Configuration
* &#064;ComponentScan("com.foo")
* &#064;EnableAspectJAutoProxy
* public class AppConfig {
*
* // no explicit &#064Bean definitions required
* }</pre>
*
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,22 +29,28 @@ import org.springframework.instrument.classloading.LoadTimeWeaver;
* Activates a Spring {@link LoadTimeWeaver} for this application context, available as
* a bean with the name "loadTimeWeaver", similar to the {@code <context:load-time-weaver>}
* element in Spring XML.
* To be used
* on @{@link org.springframework.context.annotation.Configuration Configuration} classes;
*
* <p>To be used on @{@link org.springframework.context.annotation.Configuration Configuration} classes;
* the simplest possible example of which follows:
*
* <pre class="code">
* &#064;Configuration
* &#064;EnableLoadTimeWeaving
* public class AppConfig {
*
* // application-specific &#064;Bean definitions ...
* }</pre>
*
* The example above is equivalent to the following Spring XML configuration:
*
* <pre class="code">
* {@code
* <beans>
*
* <context:load-time-weaver/>
*
* <!-- application-specific <bean> definitions -->
*
* </beans>
* }</pre>
*
@@ -61,10 +67,12 @@ import org.springframework.instrument.classloading.LoadTimeWeaver;
* {@code @EnableLoadTimeWeaving} may also implement the {@link LoadTimeWeavingConfigurer}
* interface and return a custom {@code LoadTimeWeaver} instance through the
* {@code #getLoadTimeWeaver} method:
*
* <pre class="code">
* &#064;Configuration
* &#064;EnableLoadTimeWeaving
* public class AppConfig implements LoadTimeWeavingConfigurer {
*
* &#064;Override
* public LoadTimeWeaver getLoadTimeWeaver() {
* MyLoadTimeWeaver ltw = new MyLoadTimeWeaver();
@@ -75,10 +83,13 @@ import org.springframework.instrument.classloading.LoadTimeWeaver;
* }</pre>
*
* <p>The example above can be compared to the following Spring XML configuration:
*
* <pre class="code">
* {@code
* <beans>
*
* <context:load-time-weaver weaverClass="com.acme.MyLoadTimeWeaver"/>
*
* </beans>
* }</pre>
*
@@ -94,6 +105,7 @@ import org.springframework.instrument.classloading.LoadTimeWeaver;
* be registered through {@link LoadTimeWeaver#addTransformer}. AspectJ weaving will be
* activated by default if a "META-INF/aop.xml" resource is present on the classpath.
* Example:
*
* <pre class="code">
* &#064;Configuration
* &#064;EnableLoadTimeWeaving(aspectjWeaving=ENABLED)
@@ -101,10 +113,13 @@ import org.springframework.instrument.classloading.LoadTimeWeaver;
* }</pre>
*
* <p>The example above can be compared to the following Spring XML configuration:
*
* <pre class="code">
* {@code
* <beans>
*
* <context:load-time-weaver aspectj-weaving="on"/>
*
* </beans>
* }</pre>
*
@@ -131,7 +146,8 @@ public @interface EnableLoadTimeWeaving {
*/
AspectJWeaving aspectjWeaving() default AspectJWeaving.AUTODETECT;
public enum AspectJWeaving {
enum AspectJWeaving {
/**
* Switches on Spring-based AspectJ load-time weaving.
@@ -151,4 +167,5 @@ public @interface EnableLoadTimeWeaving {
*/
AUTODETECT;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -75,12 +75,12 @@ public class LoadTimeWeavingConfiguration implements ImportAware, BeanClassLoade
LoadTimeWeaver loadTimeWeaver = null;
if (this.ltwConfigurer != null) {
// the user has provided a custom LTW instance
loadTimeWeaver = ltwConfigurer.getLoadTimeWeaver();
// The user has provided a custom LoadTimeWeaver instance
loadTimeWeaver = this.ltwConfigurer.getLoadTimeWeaver();
}
if (loadTimeWeaver == null) {
// no custom LTW provided -> fall back to the default
// No custom LoadTimeWeaver provided -> fall back to the default
loadTimeWeaver = new DefaultContextLoadTimeWeaver(this.beanClassLoader);
}
@@ -30,6 +30,7 @@ import java.lang.annotation.Target;
* conjunction with @{@link Configuration} classes.
*
* <h3>Example usage</h3>
*
* <p>Given a file {@code app.properties} containing the key/value pair
* {@code testbean.name=myTestBean}, the following {@code @Configuration} class
* uses {@code @PropertySource} to contribute {@code app.properties} to the
@@ -56,6 +57,7 @@ import java.lang.annotation.Target;
* the configuration above, a call to {@code testBean.getName()} will return "myTestBean".
*
* <h3>Resolving ${...} placeholders in {@code <bean>} and {@code @Value} annotations</h3>
*
* In order to resolve ${...} placeholders in {@code <bean>} definitions or {@code @Value}
* annotations using properties from a {@code PropertySource}, one must register
* a {@code PropertySourcesPlaceholderConfigurer}. This happens automatically when using
@@ -66,9 +68,11 @@ import java.lang.annotation.Target;
* for details and examples.
*
* <h3>Resolving ${...} placeholders within {@code @PropertySource} resource locations</h3>
*
* Any ${...} placeholders present in a {@code @PropertySource} {@linkplain #value()
* resource location} will be resolved against the set of property sources already
* registered against the environment. For example:
* registered against the environment. For example:
*
* <pre class="code">
* &#064;Configuration
* &#064;PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties")
@@ -92,6 +96,7 @@ import java.lang.annotation.Target;
* IllegalArgumentException} will be thrown.
*
* <h3>A note on property overriding with @PropertySource</h3>
*
* In cases where a given property key exists in more than one {@code .properties}
* file, the last {@code @PropertySource} annotation processed will 'win' and override.
*
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,8 @@ package org.springframework.context.event;
import java.util.concurrent.Executor;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
@@ -160,7 +162,13 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM
}
}
else {
listener.onApplicationEvent(event);
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
LogFactory.getLog(getClass()).debug("Non-matching event type for listener: " + listener, ex);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@ import org.springframework.util.ObjectUtils;
*
* @author Costin Leau
* @author Stephane Nicoll
* @since 4.2.0
* @since 4.2
* @see CachedExpressionEvaluator
*/
public final class AnnotatedElementKey {
@@ -36,12 +36,13 @@ public final class AnnotatedElementKey {
private final Class<?> targetClass;
/**
* Create a new instance with the specified {@link AnnotatedElement} and
* optional target {@link Class}.
*/
public AnnotatedElementKey(AnnotatedElement element, Class<?> targetClass) {
Assert.notNull(element, "AnnotatedElement must be set.");
Assert.notNull(element, "AnnotatedElement must not be null");
this.element = element;
this.targetClass = targetClass;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,13 +28,14 @@ import org.springframework.util.ObjectUtils;
* are defined on {@link java.lang.reflect.AnnotatedElement}.
*
* @author Stephane Nicoll
* @since 4.2.0
* @since 4.2
* @see AnnotatedElementKey
*/
public abstract class CachedExpressionEvaluator {
private final SpelExpressionParser parser;
/**
* Create a new instance with the specified {@link SpelExpressionParser}.
*/
@@ -50,6 +51,7 @@ public abstract class CachedExpressionEvaluator {
this(new SpelExpressionParser());
}
/**
* Return the {@link SpelExpressionParser} to use.
*/
@@ -57,6 +59,7 @@ public abstract class CachedExpressionEvaluator {
return this.parser;
}
/**
* Return the {@link Expression} for the specified SpEL value
* <p>Parse the expression if it hasn't been already.
@@ -66,6 +69,7 @@ public abstract class CachedExpressionEvaluator {
*/
protected Expression getExpression(Map<ExpressionKey, Expression> cache,
AnnotatedElementKey elementKey, String expression) {
ExpressionKey expressionKey = createKey(elementKey, expression);
Expression expr = cache.get(expressionKey);
if (expr == null) {
@@ -79,6 +83,7 @@ public abstract class CachedExpressionEvaluator {
return new ExpressionKey(elementKey, expression);
}
protected static class ExpressionKey {
private final AnnotatedElementKey key;
@@ -105,7 +110,7 @@ public abstract class CachedExpressionEvaluator {
@Override
public int hashCode() {
return this.key.hashCode() * 29 + (this.expression != null ? this.expression.hashCode() : 0);
return this.key.hashCode() + (this.expression != null ? this.expression.hashCode() * 29 : 0);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,8 +25,8 @@ import org.springframework.util.ObjectUtils;
/**
* A method-based {@link org.springframework.expression.EvaluationContext} that
* provides explicit support for method-based invocations.
* <p>
* Expose the actual method arguments using the following aliases:
*
* <p>Expose the actual method arguments using the following aliases:
* <ol>
* <li>pX where X is the index of the argument (p0 for the first argument)</li>
* <li>aX where X is the index of the argument (a1 for the second argument)</li>
@@ -34,7 +34,7 @@ import org.springframework.util.ObjectUtils;
* </ol>
*
* @author Stephane Nicoll
* @since 4.2.0
* @since 4.2
*/
public class MethodBasedEvaluationContext extends StandardEvaluationContext {
@@ -46,6 +46,7 @@ public class MethodBasedEvaluationContext extends StandardEvaluationContext {
private boolean paramLoaded = false;
public MethodBasedEvaluationContext(Object rootObject, Method method, Object[] args,
ParameterNameDiscoverer paramDiscoverer) {
@@ -55,6 +56,7 @@ public class MethodBasedEvaluationContext extends StandardEvaluationContext {
this.paramDiscoverer = paramDiscoverer;
}
@Override
public Object lookupVariable(String name) {
Object variable = super.lookupVariable(name);
@@ -369,7 +369,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
else {
applicationEvent = new PayloadApplicationEvent<Object>(this, event);
if (eventType == null) {
eventType = ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class, event.getClass());
eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -106,7 +106,7 @@ public class DefaultMessageSourceResolvable implements MessageSourceResolvable,
* the last one in the codes array.
*/
public String getCode() {
return (this.codes != null && this.codes.length > 0) ? this.codes[this.codes.length - 1] : null;
return (this.codes != null && this.codes.length > 0 ? this.codes[this.codes.length - 1] : null);
}
@Override
@@ -127,7 +127,7 @@ public class DefaultMessageSourceResolvable implements MessageSourceResolvable,
protected final String resolvableToString() {
StringBuilder result = new StringBuilder();
result.append("codes [").append(StringUtils.arrayToDelimitedString(this.codes, ","));
result.append("]; arguments [" + StringUtils.arrayToDelimitedString(this.arguments, ","));
result.append("]; arguments [").append(StringUtils.arrayToDelimitedString(this.arguments, ","));
result.append("]; default message [").append(this.defaultMessage).append(']');
return result.toString();
}
@@ -153,9 +153,9 @@ public class DefaultMessageSourceResolvable implements MessageSourceResolvable,
return false;
}
MessageSourceResolvable otherResolvable = (MessageSourceResolvable) other;
return ObjectUtils.nullSafeEquals(getCodes(), otherResolvable.getCodes()) &&
return (ObjectUtils.nullSafeEquals(getCodes(), otherResolvable.getCodes()) &&
ObjectUtils.nullSafeEquals(getArguments(), otherResolvable.getArguments()) &&
ObjectUtils.nullSafeEquals(getDefaultMessage(), otherResolvable.getDefaultMessage());
ObjectUtils.nullSafeEquals(getDefaultMessage(), otherResolvable.getDefaultMessage()));
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -344,16 +344,23 @@ class PostProcessorRegistrationDelegate {
/**
* BeanPostProcessor that detects beans which implement the ApplicationListener interface.
* This catches beans that can't reliably be detected by getBeanNamesForType.
* {@code BeanPostProcessor} that detects beans which implement the {@code ApplicationListener}
* interface. This catches beans that can't reliably be detected by {@code getBeanNamesForType}
* and related operations which only work against top-level beans.
*
* <p>With standard Java serialization, this post-processor won't get serialized as part of
* {@code DisposableBeanAdapter} to begin with. However, with alternative serialization
* mechanisms, {@code DisposableBeanAdapter.writeReplace} might not get used at all, so we
* defensively mark this post-processor's field state as {@code transient}.
*/
private static class ApplicationListenerDetector implements MergedBeanDefinitionPostProcessor, DestructionAwareBeanPostProcessor {
private static class ApplicationListenerDetector
implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor {
private static final Log logger = LogFactory.getLog(ApplicationListenerDetector.class);
private final AbstractApplicationContext applicationContext;
private transient final AbstractApplicationContext applicationContext;
private final Map<String, Boolean> singletonNames = new ConcurrentHashMap<String, Boolean>(256);
private transient final Map<String, Boolean> singletonNames = new ConcurrentHashMap<String, Boolean>(256);
public ApplicationListenerDetector(AbstractApplicationContext applicationContext) {
this.applicationContext = applicationContext;
@@ -361,7 +368,7 @@ class PostProcessorRegistrationDelegate {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if (beanDefinition.isSingleton()) {
if (this.applicationContext != null && beanDefinition.isSingleton()) {
this.singletonNames.put(beanName, Boolean.TRUE);
}
}
@@ -373,7 +380,7 @@ class PostProcessorRegistrationDelegate {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof ApplicationListener) {
if (this.applicationContext != null && bean instanceof ApplicationListener) {
// potentially not detected as a listener by getBeanNamesForType retrieval
Boolean flag = this.singletonNames.get(beanName);
if (Boolean.TRUE.equals(flag)) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -50,29 +50,20 @@ import org.springframework.util.StringUtils;
* reloading files based on timestamp changes, but also of loading properties files
* with a specific character encoding. It will detect XML property files as well.
*
* <p>In contrast to {@link ResourceBundleMessageSource}, this class supports
* reloading of properties files through the {@link #setCacheSeconds "cacheSeconds"}
* setting, and also through programmatically clearing the properties cache.
* Since application servers typically cache all files loaded from the classpath,
* it is necessary to store resources somewhere else (for example, in the
* "WEB-INF" directory of a web app). Otherwise changes of files in the
* classpath will <i>not</i> be reflected in the application.
*
* <p>Note that the base names set as {@link #setBasenames "basenames"} property
* <p>Note that the basenames set as {@link #setBasenames "basenames"} property
* are treated in a slightly different fashion than the "basenames" property of
* {@link ResourceBundleMessageSource}. It follows the basic ResourceBundle rule of not
* specifying file extension or language codes, but can refer to any Spring resource
* location (instead of being restricted to classpath resources). With a "classpath:"
* prefix, resources can still be loaded from the classpath, but "cacheSeconds" values
* other than "-1" (caching forever) will not work in this case.
*
* <p>This MessageSource implementation is usually slightly faster than
* {@link ResourceBundleMessageSource}, which builds on {@link java.util.ResourceBundle}
* - in the default mode, i.e. when caching forever. With "cacheSeconds" set to 1,
* message lookup takes about twice as long - with the benefit that changes in
* individual properties files are detected with a maximum delay of 1 second.
* Higher "cacheSeconds" values usually <i>do not</i> make a significant difference.
* other than "-1" (caching forever) might not work reliably in this case.
*
* <p>For a typical web application, message files could be placed into {@code WEB-INF}:
* e.g. a "WEB-INF/messages" basename would fine a "WEB-INF/messages.properties",
* "WEB-INF/messages_en.properties" etc arrangement as well as "WEB-INF/messages.xml",
* "WEB-INF/messages_en.xml" etc. Note that message definitions in a <i>previous</i>
* resource bundle will override ones in a later bundle, due to sequential lookup.
* <p>This MessageSource can easily be used outside of an
* {@link org.springframework.context.ApplicationContext}: It will use a
* {@link org.springframework.core.io.DefaultResourceLoader} as default,
@@ -244,6 +235,7 @@ public class ReloadableResourceBundleMessageSource extends AbstractMessageSource
* <p>Default is "true": This behavior is new as of Spring Framework 4.1,
* minimizing contention between threads. If you prefer the old behavior,
* i.e. to fully block on refresh, switch this flag to "false".
* @since 4.1
* @see #setCacheSeconds
*/
public void setConcurrentRefresh(boolean concurrentRefresh) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,11 +51,11 @@ import org.springframework.util.StringUtils;
* base class. The caching provided by this MessageSource is significantly faster
* than the built-in caching of the {@code java.util.ResourceBundle} class.
*
* <p>Unfortunately, {@code java.util.ResourceBundle} caches loaded bundles
* forever: Reloading a bundle during VM execution is <i>not</i> possible.
* As this MessageSource relies on ResourceBundle, it faces the same limitation.
* Consider {@link ReloadableResourceBundleMessageSource} for an alternative
* that is capable of refreshing the underlying bundle files.
* <p>The basenames follow {@link java.util.ResourceBundle} conventions: essentially,
* a fully-qualified classpath location. If it doesn't contain a package qualifier
* (such as {@code org.mypackage}), it will be resolved from the classpath root.
* Note that the JDK's standard ResourceBundle treats dots as package separators:
* This means that "test.theme" is effectively equivalent to "test/theme".
*
* @author Rod Johnson
* @author Juergen Hoeller
@@ -404,8 +404,7 @@ public class ResourceBundleMessageSource extends AbstractMessageSource implement
*/
@Override
public String toString() {
return getClass().getName() + ": basenames=[" +
StringUtils.arrayToCommaDelimitedString(this.basenames) + "]";
return getClass().getName() + ": basenames=[" + StringUtils.arrayToCommaDelimitedString(this.basenames) + "]";
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,7 +41,7 @@ import java.lang.annotation.Target;
* <p>Each attribute is mutually exclusive, so only set one attribute per annotation instance
* (the one most convenient one for your formatting needs).
* When the pattern attribute is specified, it takes precedence over both the style and ISO attribute.
* When the {@link #iso} attribute is specified, if takes precedence over the style attribute.
* When the {@link #iso} attribute is specified, it takes precedence over the style attribute.
* When no annotation attributes are specified, the default format applied is style-based
* with a style code of 'SS' (short date, short time).
*
@@ -17,7 +17,6 @@
package org.springframework.format.datetime.standard;
import java.text.ParseException;
import java.time.Instant;
import java.time.Period;
import java.util.Locale;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -97,15 +97,14 @@ public class ReflectiveLoadTimeWeaver implements LoadTimeWeaver {
Assert.notNull(classLoader, "ClassLoader must not be null");
this.classLoader = classLoader;
this.addTransformerMethod = ClassUtils.getMethodIfAvailable(
this.classLoader.getClass(), ADD_TRANSFORMER_METHOD_NAME,
new Class<?>[] {ClassFileTransformer.class});
this.classLoader.getClass(), ADD_TRANSFORMER_METHOD_NAME, ClassFileTransformer.class);
if (this.addTransformerMethod == null) {
throw new IllegalStateException(
"ClassLoader [" + classLoader.getClass().getName() + "] does NOT provide an " +
"'addTransformer(ClassFileTransformer)' method.");
}
this.getThrowawayClassLoaderMethod = ClassUtils.getMethodIfAvailable(
this.classLoader.getClass(), GET_THROWAWAY_CLASS_LOADER_METHOD_NAME, new Class<?>[0]);
this.classLoader.getClass(), GET_THROWAWAY_CLASS_LOADER_METHOD_NAME);
// getThrowawayClassLoader method is optional
if (this.getThrowawayClassLoaderMethod == null) {
if (logger.isInfoEnabled()) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,47 +29,57 @@ import org.springframework.util.Assert;
/**
*
* Reflective wrapper around a WebSphere 7 class loader. Used to
* Reflective wrapper around a WebSphere 7+ class loader. Used to
* encapsulate the classloader-specific methods (discovered and
* called through reflection) from the load-time weaver.
*
* @author Costin Leau
* @author Juergen Hoeller
* @since 3.1
*/
class WebSphereClassLoaderAdapter {
private static final String COMPOUND_CLASS_LOADER_NAME = "com.ibm.ws.classloader.CompoundClassLoader";
private static final String CLASS_PRE_PROCESSOR_NAME = "com.ibm.websphere.classloader.ClassLoaderInstancePreDefinePlugin";
private static final String PLUGINS_FIELD = "preDefinePlugins";
private ClassLoader classLoader;
private Class<?> wsPreProcessorClass;
private Method addPreDefinePlugin;
private Constructor<? extends ClassLoader> cloneConstructor;
private Field transformerList;
public WebSphereClassLoaderAdapter(ClassLoader classLoader) {
Class<?> wsCompoundClassLoaderClass = null;
Class<?> wsCompoundClassLoaderClass;
try {
wsCompoundClassLoaderClass = classLoader.loadClass(COMPOUND_CLASS_LOADER_NAME);
cloneConstructor = classLoader.getClass().getDeclaredConstructor(wsCompoundClassLoaderClass);
cloneConstructor.setAccessible(true);
this.cloneConstructor = classLoader.getClass().getDeclaredConstructor(wsCompoundClassLoaderClass);
this.cloneConstructor.setAccessible(true);
wsPreProcessorClass = classLoader.loadClass(CLASS_PRE_PROCESSOR_NAME);
addPreDefinePlugin = classLoader.getClass().getMethod("addPreDefinePlugin", wsPreProcessorClass);
transformerList = wsCompoundClassLoaderClass.getDeclaredField(PLUGINS_FIELD);
transformerList.setAccessible(true);
this.wsPreProcessorClass = classLoader.loadClass(CLASS_PRE_PROCESSOR_NAME);
this.addPreDefinePlugin = classLoader.getClass().getMethod("addPreDefinePlugin", this.wsPreProcessorClass);
this.transformerList = wsCompoundClassLoaderClass.getDeclaredField(PLUGINS_FIELD);
this.transformerList.setAccessible(true);
}
catch (Exception ex) {
throw new IllegalStateException(
"Could not initialize WebSphere LoadTimeWeaver because WebSphere 7 API classes are not available",
ex);
"Could not initialize WebSphere LoadTimeWeaver because WebSphere API classes are not available", ex);
}
if (!wsCompoundClassLoaderClass.isInstance(classLoader)) {
throw new IllegalArgumentException("ClassLoader must be instance of [" + COMPOUND_CLASS_LOADER_NAME + "]");
}
Assert.isInstanceOf(wsCompoundClassLoaderClass, classLoader,
"ClassLoader must be instance of [" + COMPOUND_CLASS_LOADER_NAME + "]");
this.classLoader = classLoader;
}
public ClassLoader getClassLoader() {
return this.classLoader;
}
@@ -79,9 +89,8 @@ class WebSphereClassLoaderAdapter {
try {
InvocationHandler adapter = new WebSphereClassPreDefinePlugin(transformer);
Object adapterInstance = Proxy.newProxyInstance(this.wsPreProcessorClass.getClassLoader(),
new Class<?>[] { this.wsPreProcessorClass }, adapter);
new Class<?>[] {this.wsPreProcessorClass}, adapter);
this.addPreDefinePlugin.invoke(this.classLoader, adapterInstance);
}
catch (InvocationTargetException ex) {
throw new IllegalStateException("WebSphere addPreDefinePlugin method threw exception", ex.getCause());
@@ -93,9 +102,9 @@ class WebSphereClassLoaderAdapter {
public ClassLoader getThrowawayClassLoader() {
try {
ClassLoader loader = cloneConstructor.newInstance(getClassLoader());
// clear out the transformers (copied as well)
List<?> list = (List<?>) transformerList.get(loader);
ClassLoader loader = this.cloneConstructor.newInstance(getClassLoader());
// Clear out the transformers (copied as well)
List<?> list = (List<?>) this.transformerList.get(loader);
list.clear();
return loader;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,7 +42,8 @@ public class AnnotationAsyncExecutionInterceptor extends AsyncExecutionIntercept
* Create a new {@code AnnotationAsyncExecutionInterceptor} with the given executor
* and a simple {@link AsyncUncaughtExceptionHandler}.
* @param defaultExecutor the executor to be used by default if no more specific
* executor has been qualified at the method level using {@link Async#value()}
* executor has been qualified at the method level using {@link Async#value()};
* as of 4.2.6, a local executor for this interceptor will be built otherwise
*/
public AnnotationAsyncExecutionInterceptor(Executor defaultExecutor) {
super(defaultExecutor);
@@ -51,7 +52,8 @@ public class AnnotationAsyncExecutionInterceptor extends AsyncExecutionIntercept
/**
* Create a new {@code AnnotationAsyncExecutionInterceptor} with the given executor.
* @param defaultExecutor the executor to be used by default if no more specific
* executor has been qualified at the method level using {@link Async#value()}
* executor has been qualified at the method level using {@link Async#value()};
* as of 4.2.6, a local executor for this interceptor will be built otherwise
* @param exceptionHandler the {@link AsyncUncaughtExceptionHandler} to use to
* handle exceptions thrown by asynchronous method executions with {@code void}
* return type
@@ -74,7 +76,7 @@ public class AnnotationAsyncExecutionInterceptor extends AsyncExecutionIntercept
*/
@Override
protected String getExecutorQualifier(Method method) {
// maintainer's note: changes made here should also be made in
// Maintainer's note: changes made here should also be made in
// AnnotationAsyncExecutionAspect#getExecutorQualifier
Async async = AnnotationUtils.findAnnotation(method, Async.class);
if (async == null) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -56,7 +56,7 @@ public @interface Async {
* bean definition.
* <p>When specified on a class level {@code @Async} annotation, indicates that the
* given executor should be used for all methods within the class. Method level use
* of {@link Async#value} always overrides any value set at the class level.
* of {@code Async#value} always overrides any value set at the class level.
* @since 3.1.2
*/
String value() default "";

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