Compare commits

...

281 Commits

Author SHA1 Message Date
Spring Buildmaster 330ba99049 Release version 4.3.4.RELEASE 2016-11-07 21:35:43 +00:00
Juergen Hoeller 37f4f43726 Consistent 4.x style NoClassDefFoundError handling
Issue: SPR-14883
2016-11-07 19:13:00 +01:00
Juergen Hoeller db1a84ede1 Polishing 2016-11-07 18:48:35 +01:00
Juergen Hoeller 3d2e4c338c Refined throwing of BeanCreationExceptions (and reflection exceptions)
Issue: SPR-14883
2016-11-07 18:47:54 +01:00
Juergen Hoeller b42d731fc8 Consistent throwing of BeanCreationExceptions (and reflection exceptions)
Issue: SPR-14883
2016-11-07 16:56:35 +01:00
Juergen Hoeller fd7045adac Polishing
(cherry picked from commit 9b57437)
2016-11-07 13:02:50 +01:00
Juergen Hoeller e26d3505f7 Upgrade to OkHttp 3.4.2 and Tiles 3.0.7 2016-11-04 14:55:37 +01:00
Juergen Hoeller fe0249bf8f Polishing 2016-11-04 13:37:06 +01:00
Juergen Hoeller 2ac682e125 Upgrade to Joda-Time 2.9.5 2016-11-04 13:30:25 +01:00
Juergen Hoeller 9be1710dca @Async docs explicitly mention ListenableFuture and CompletableFuture
Issue: SPR-14881
(cherry picked from commit 8df45dd)
2016-11-04 13:30:11 +01:00
Juergen Hoeller 7e7504f5ea Polishing 2016-11-03 23:20:33 +01:00
Juergen Hoeller e83c11667f ApplicationListenerDetector ignores non-managed bean instances
Issue: SPR-14879
(cherry picked from commit 8ae0bd6)
2016-11-03 23:20:06 +01:00
Juergen Hoeller 05547979de Polishing
Issue: SPR-14867
(cherry picked from commit a90e4b2)
2016-11-03 14:54:15 +01:00
Juergen Hoeller 9e67ba83a5 Consistent support for early placeholder resolution in properties locations
Issue: SPR-10502
(cherry picked from commit 8053fef)
2016-11-03 14:53:46 +01:00
Juergen Hoeller 2bb3522bbb ReloadableResourceBundleMessageSource sets file timestamp on merged holder
Issue: SPR-14583
(cherry picked from commit 03468fd)
2016-11-03 14:53:24 +01:00
Rossen Stoyanchev 8f4ec35697 Check SockJS session type
This commits adds a validation check whether the SockJS session type
matches the transport type and rejects requests for which they
don't match.

Issue: SPR-14867
2016-11-03 09:38:24 +02:00
Juergen Hoeller 17863dfbda AnnotatedElementAdapter explicitly declares isAnnotationPresent method
Issue: SPR-14872
2016-11-02 14:41:11 +01:00
Juergen Hoeller 56bb20d489 Upgrade to HtmlUnit 2.23 and JSONAssert 1.4 2016-11-02 14:40:10 +01:00
Juergen Hoeller 5baf32cd81 Upgrade to Caffeine 2.3.4 2016-11-02 14:02:49 +01:00
Andy Clement 38cd1ecff4 Rework compilation of OpNE/OpEQ SpEL operators
For SPR-14863 we need to adjust the code generation for OpNE
to use !x.equals(y) rather than x!=y. There are also further
cases in the equalityCheck() code in Operator that were not
being handled in the compilation case (when comparators are
used for example). This latter issue also affects OpEQ.

Rather than add yet more bytecode generation, both OpNE and
OpEQ generateCode() methods have been simplified. The
generated code now delegates to equalityCheck() in Operator
which is exactly what the interpreted case does.

This ensures that the compiled code continues to behave just
like the interpreted case. It ensures changes to the interpreted
case are automatically picked up for the compiled case. It
makes the bytecode generation simpler.

The benefit of compilation of SpEL expressions is to avoid
slow reflective calls - that doesn't apply for a basic
(in)equality test so there is no need to go crazy in bytecode
gen.

Issue: SPR-14863
(cherry picked from commit 9000acd)
2016-11-02 12:40:24 +01:00
Juergen Hoeller 77e00f1926 Polishing 2016-10-31 20:40:46 +01:00
Juergen Hoeller ade139f2d0 Polishing
(cherry picked from commit 45fc449)
2016-10-31 19:29:04 +01:00
Juergen Hoeller 653f35a3d8 Upgrade to H2 1.4.193 and Derby 10.13.1.1
(cherry picked from commit eaf8078)
2016-10-31 19:28:58 +01:00
Juergen Hoeller baa7aecf60 Polishing
(cherry picked from commit 7f280a3)
2016-10-31 12:40:44 +01:00
Juergen Hoeller d859826be6 ASM-generated class names get interned for better memory allocation
Issue: SPR-14862
2016-10-31 11:56:34 +01:00
Juergen Hoeller d759c96a98 Latest applicable dependency updates (Hibernate ORM 5.2.4, Gson 2.8, Guava 20) 2016-10-31 11:54:29 +01:00
Juergen Hoeller 7cbab0efe3 LocalSessionFactoryBean clears default MetadataSources on reinitialization
Issue: SPR-14815
2016-10-31 11:53:10 +01:00
Arjen Poutsma b6b536682e Make HttpComponentsAsyncClientHttpRequest abortable
This commit aborts the HttpComponentsAsyncClientHttpRequest whenever the
returned Future is canceled.

Issue: SPR-14845
(cherry picked from commit 8f84446)
2016-10-31 11:51:26 +01:00
Juergen Hoeller edf1df33cc ObjectToObjectConverter properly handles constructors on non-public classes
Issue: SPR-14304
(cherry picked from commit 9659bc5)
2016-10-31 11:51:05 +01:00
Juergen Hoeller bf0df54136 Consistent instanceof/casting of Class references
(cherry picked from commit ac80ac6)
2016-10-31 11:50:59 +01:00
Juergen Hoeller 7e80d2de79 Exceptions thrown from @ExceptionHandler methods logged at warn level (instead of debug)
Issue: SPR-14861
(cherry picked from commit 7627c38)
2016-10-31 11:50:45 +01:00
Juergen Hoeller 144f687ee9 Polishing
(cherry picked from commit 2f9ed59)
2016-10-31 11:50:36 +01:00
Juergen Hoeller 0ee8322947 Revised NoSuchBeanDefinitionException message and ResolvableType handling
Includes consistent quoting of qualified type names in related classes.

Issue: SPR-14831
(cherry picked from commit dc080cb)
2016-10-31 11:50:15 +01:00
Juergen Hoeller 997fb5fb48 DefaultListableBeanFactory allows early type matching against ScopedProxyFactoryBean
Issue: SPR-14816
(cherry picked from commit 3633244)
2016-10-31 11:50:02 +01:00
Juergen Hoeller 2b459881bd ApplicationListener detection for inner beans behind post-processors
Issue: SPR-14783
(cherry picked from commit c946924)
2016-10-31 11:49:06 +01:00
Juergen Hoeller e18e7eca47 No external locking for singleton advice/aspect beans
Issue: SPR-14324
(cherry picked from commit 5ac5ec1)
2016-10-31 11:48:12 +01:00
Juergen Hoeller 1c80d2ac2f Avoid deadlock between SockJS heartbeat and XHR polling
Issue: SPR-14833
(cherry picked from commit 72e1f7e)
2016-10-31 11:47:23 +01:00
Juergen Hoeller 62918ca779 TypeDescriptor supports merged annotation lookups (for composable formatting annotations)
Issue: SPR-14844
(cherry picked from commit bf9083d)
2016-10-31 11:46:30 +01:00
Juergen Hoeller 3cca57a801 Local merged annotation lookup in SpringCacheAnnotationParser
Issue: SPR-14781
Issue: SPR-14801
(cherry picked from commit 08972ef)
2016-10-31 11:45:35 +01:00
Juergen Hoeller 5578a2e46d Test for multi-character delimiter
Issue: SPR-14808
(cherry picked from commit 71d8338)
2016-10-31 11:45:01 +01:00
Juergen Hoeller fe19cfde28 Tightened StringValueResolver contract
Issue: SPR-14842
(cherry picked from commit 20419d7)
2016-10-31 11:44:46 +01:00
Juergen Hoeller fbad637235 SimpleApplicationEventMulticaster just swallows event downcast exceptions
Issue: SPR-14846
(cherry picked from commit 13001b9)
2016-10-31 11:44:26 +01:00
Juergen Hoeller 01e9307fb7 DataSourceTransactionManager triggers flush callbacks on registered transaction synchronizations
Issue: SPR-14847
(cherry picked from commit 2874066)
2016-10-31 11:44:17 +01:00
Juergen Hoeller 5697cb6c95 AccessorLValue reliably downcasts to CompilablePropertyAccessor in concurrent scenarios
Issue: SPR-14850
(cherry picked from commit e2b1dcb)
2016-10-31 11:44:08 +01:00
Juergen Hoeller 05ff83f95a ResourceHttpRequestHandler initializes PathExtensionContentNegotiationStrategy in afterPropertiesSet
Issue: SPR-14851
(cherry picked from commit b7d3a96)
2016-10-31 11:43:57 +01:00
Stephane Nicoll 1e3012cb49 Allow to customize TestDispatcherServlet
This commit introduces the `DispatcherServletCustomizer` callback
interface that can be used to customize the `DispatcherServlet` that a
`MockMvc` is using.

Previously, only the `dispatchOptions` flag can be customized. This
commit allows to customize any property of `DispatcherServlet` before it
is initialized.

Issue: SPR-14277
2016-10-29 11:09:48 +02:00
Rossen Stoyanchev 45b8cf350e Better handling for AsyncRequestTimeoutException
Avoid call to sendError when response is committed and log a short
error message instead.

Issue: SPR-14739
2016-10-28 17:41:48 +03:00
Stephane Nicoll 2c2c6f8e02 Fix broken build
This commit fixes the direct use of Java8 API

Issue: SPR-14853
2016-10-27 10:30:54 +02:00
Stephane Nicoll 4e3a6b9404 Polish 2016-10-27 10:01:51 +02:00
Stephane Nicoll 76bbccb4dc Allow @Cacheable method to return Optional
This commit further refines 240f254 to also support java.util.Optional
for synchronized cache access (i.e. when the `sync` attribute on
`@Cacheable` is set to `true`).

Issue: SPR-14853
2016-10-27 10:00:34 +02:00
Stephane Nicoll 1c4433555a Move NoOpCache to a top-level public class
This commit moves `NoOpCache` to a top-level public class to allow reuse
in custom CacheManager arrangement.

Issue: SPR-14856
2016-10-27 09:09:51 +02:00
Eric Jain faaced1d86 Escape (( and )) to prevent asciidoc processing
See http://asciidoctor.org/docs/user-manual/#user-index

Closes gh-1225
2016-10-27 08:50:27 +02:00
Stephane Nicoll 1a1d17e13a LiveBeansView does not rely on application contexts order anymore
This commit makes sure that the `unregister` order of registered
application contexts has no incidence on the removal of the LiveBeansView
MBean.

Rather than using the last application context's name to compute the
identity of the MBean to remove, the identity is stored when the MBean is
created.

This commit also adds missing tests.

Issue: SPR-14848
2016-10-26 15:03:44 +02:00
Stephane Nicoll 4254b6d0e2 Polish contribution
Closes gh-1203
2016-10-26 09:50:48 +02:00
Vitalii a211c2a955 Fix javadoc syntax
See gh-1203
2016-10-26 09:50:36 +02:00
Stephane Nicoll 196200bcc0 Clarify SpEL usage on @EventListener
Issue: SPR-14812
2016-10-25 17:45:36 +02:00
Rossen Stoyanchev c062835702 Respect ModelAndView.status in @ExceptionHandler
Issue: SPR-14006
2016-10-24 16:36:44 +01:00
Juergen Hoeller 664ef756c2 Latest dependency updates (EhCache 2.10.3, Jackson 2.8.4, Jetty 9.3.13, Netty 4.1.6) 2016-10-21 13:00:11 +02:00
Juergen Hoeller 9de28d640e Polishing
(cherry picked from commit 3726c6f)
2016-10-21 12:59:59 +02:00
Juergen Hoeller adb9dc7ede ResolvableType equals/hashCode does not consider TypeProvider source
Issue: SPR-14826
(cherry picked from commit be187ba)
2016-10-21 12:59:54 +02:00
Juergen Hoeller f9fcd24315 ConversionService detects generic type declaration on target class behind proxy as well
Issue: SPR-14822
(cherry picked from commit f7d740f)
2016-10-21 12:59:48 +02:00
Juergen Hoeller 6d95b999ad DefaultTransactionAttribute stores descriptor (method identification)
Issue: SPR-14760
(cherry picked from commit 52b029d)
2016-10-21 12:59:43 +02:00
Sebastien Deleuze 6731e52280 Better encapsulation for CORS default permit configuration
This commit also improves CorsRegistration Javadoc.

Issue: SPR-14798
2016-10-20 17:06:12 +02:00
Rossen Stoyanchev 970358b2af Relax generic type detection for ResponseEntity
Before this change the getHttpEntityType method in
HttpEntityMethodProcessor raised an ISE if the generic type cannot be
detected. That made sense for resolving a controller method argument
where the target body type is crucial. However for a return value
the generic type should not be required since we either have an
actual body or no body at all in which case it doesn't even matter.

This change relaxes the checks and defaults to Object.class for the
ResponseEntity generic type on the return value side.

Issue: SPR-14799
2016-10-13 13:59:13 -04:00
Juergen Hoeller 3d68950037 Upgrade to Tomcat 8.5.6 and JRuby 1.7.26 2016-10-12 17:52:36 +02:00
Juergen Hoeller d50b2a4804 Documentation for InjectionPoint argument on @Bean method
Issue:  SPR-14797
(cherry picked from commit 69116c2)
2016-10-12 17:48:50 +02:00
Juergen Hoeller 29a946163b Polishing
(cherry picked from commit eafaaa5)
2016-10-12 17:48:33 +02:00
Juergen Hoeller 9472025da7 BindingResult does not hold on to ConversionService when serialized in session
Issue: SPR-8282
(cherry picked from commit 74b6a5b)
2016-10-12 17:48:08 +02:00
Juergen Hoeller f5cd5387da StompSubProtocolHandler does not insist on SimpMessageHeaderAccessor
Issue: SPR-14791
(cherry picked from commit 66722af)
2016-10-12 17:47:58 +02:00
Stephane Nicoll 7a8bf8e9a5 Polish EnableAsync javadoc
Issue: SPR-14793
(cherry picked from commit ab232a5)
2016-10-12 17:47:28 +02:00
Sebastien Deleuze f5ecdda400 Remove duplicated elements in CorsConfiguration#combine()
Issue: SPR-14792
2016-10-11 10:53:33 +02:00
Sebastien Deleuze c2031aa651 Polish CorsConfigurationTests 2016-10-11 10:41:14 +02:00
Brian Clozel 8751c9931e Fix NumberFormatException with X-Forwarded-Host
This commit fixes `NumberFormatException`s that were thrown when parsing
IPv6 host values in `X-Forwarded-Host` request headers.

Issue: SPR-14761
(cherry picked from ea5ff87f8e)
2016-10-07 23:19:01 +02:00
Brian Clozel adbf9922f4 Configure default SSL context in Netty RequestFactory
This commit configures a default SslContext if none has been provided.
This also enforces separate Netty bootstrap instances for cleartext and
TLS exchanges.

Issue: SPR-14744
(cherry picked from 53441f8)
2016-10-06 16:50:27 +02:00
Stephane Nicoll b3a1e5f9e9 Fix table layout 2016-10-06 15:27:25 +02:00
Juergen Hoeller 22f70f9ac9 Upgrade to EhCache 3.1.3 and Hibernate ORM 5.2.3 2016-10-06 00:16:29 +02:00
Juergen Hoeller d2079f32d8 SpringValidatorAdapter declares ResolvableAttribute as serializable
Issue: SPR-14778
(cherry picked from commit ebed7b7)
2016-10-06 00:16:00 +02:00
Juergen Hoeller f2ac416f66 Consistent final logger fields
(cherry picked from commit cfa0f6c)
2016-10-06 00:15:45 +02:00
Juergen Hoeller 642fbfba9f @Lookup reference documentation
Issue: SPR-14765
(cherry picked from commit 684d6ab)
2016-10-06 00:15:38 +02:00
Brian Clozel c98cdd4f4c Fix missing ETag/LastModified headers in responses
Prior to this commit, the `HttpEntityMethodProcessor` would avoid
writing ETag/Last-Modified response headers before calling
`ServletWebRequest` to process conditional requests. This was done to
avoid duplicate response header values due to headers being already
written to the underlying servlet response.

This is still necessary for GET/HEAD requests, since this is properly
handled by `ServletWebRequest` for those cases. But
`HttpEntityMethodProcessor` should not make that decision for
PUT/PATCH/POST responses since developers are adding response headers on
purpose and should be in control of the situation — whereas
`ServletWebRequest` does not write those headers in those cases.

Issue: SPR-14767
Cherry-picked from: ee17f5662
2016-10-04 13:54:02 +02:00
Juergen Hoeller d04567b99c Polishing 2016-09-26 18:19:04 +02:00
Juergen Hoeller f2e1e1b890 Efficient STOMP content-length header check
Issue: SPR-14747
(cherry picked from commit a6b0b6e)
2016-09-26 17:30:45 +02:00
Juergen Hoeller 6c764f6b8a StompEncoder performance improvement plus related polishing
Issue: SPR-14747
2016-09-26 16:33:29 +02:00
Juergen Hoeller 49929f1e56 Clarified that getResource never returns null
(cherry picked from commit 36f7c7a)
2016-09-26 16:21:44 +02:00
Juergen Hoeller acdf139137 DefaultPersistenceUnitManager extracts jar file from default persistence unit root URL
Issue: SPR-14749
(cherry picked from commit bb7d207)
2016-09-26 16:21:33 +02:00
Juergen Hoeller 3346c594e4 YamlPropertiesFactoryBean consistently exposes String values
Issue: SPR-14737
(cherry picked from commit 74c6188)
2016-09-26 16:21:03 +02:00
Juergen Hoeller 0bb2cfe440 Latest dependency updates (Jackson 2.8.3, JavaMail 1.5.6, Jetty 9.3.12, Undertow 1.3.25) 2016-09-22 14:25:44 +02:00
Josh Long 11573b4ea4 fix spelling of word 'recommendation'
this PR fixes the spelling error for the word 'recommendation'
(cherry picked from commit 9b87ea0)
2016-09-22 14:25:25 +02:00
Spring Buildmaster 5934959b62 Next Development Version 2016-09-19 15:11:46 +00:00
Rossen Stoyanchev 81f6c22e51 Reset connection before delegating to handler
Resetting the connection first before invoking a failure callback on
the application handler ensures that any checks to isConnected will
return false.

Issue: SPR-14721
2016-09-19 09:06:11 -04:00
Stephane Nicoll 78a8245f4a Polish 2016-09-19 15:04:52 +02:00
Krzysztof Kosmatka 049861afb4 Documentation formatting fix
Removed unnecessary quotation marks that caused improper rendering
of in-line code.

Closes gh-1180
2016-09-19 15:04:39 +02:00
Krzysztof Kosmatka 3df7083f69 Add missing quotation mark
Closes gh-1181
2016-09-19 15:04:31 +02:00
Juergen Hoeller ca17edd5ac Revised checkResource implementation
Issue: SPR-14729
2016-09-18 21:04:37 +02:00
Sam Brannen c26bf871b7 Clean up warnings related to forthcoming removals in Tomcat 9
(cherry picked from commit b521aa8)
2016-09-18 21:04:29 +02:00
Sam Brannen 15d3e8c3e1 Introduce 'value' alias for @Bean's 'name' attribute
In order to simplify configuration for use cases involving @Bean where
only a bean name or aliases are supplied as an attribute, this commit
introduces a new 'value' attribute that is an @AliasFor 'name' in @Bean.

Issue: SPR-14728
(cherry picked from commit 8f62b63)
2016-09-18 21:04:25 +02:00
Brian Clozel 66b370e103 Check template availability in ScriptTemplateView
This commit overrides the `checkResource` implementation in
`ScriptTemplateView` in order to check if the template file resource is
available and if the resolver can then proceed with rendering the
template.

Issue: SPR-14729
Cherry-picked from: 97c9b05c15
2016-09-17 22:30:29 +02:00
Juergen Hoeller 2bbfbb1d50 What's New updated for significant refinements in 4.3.3 2016-09-16 14:31:53 +02:00
Juergen Hoeller ace25d4987 Polishing
(cherry picked from commit ed19dc7)
2016-09-16 14:30:41 +02:00
Juergen Hoeller 59cb9a4e60 Latest dependency updates (EhCache 3.1.2, Caffeine 2.3.3, Rome 1.7, Woodstox 5.0.3, Jettison 1.3.8) 2016-09-16 11:02:22 +02:00
Stephane Nicoll 0dce570157 Add Qualified element on RootBeanDefinition
Improve RootBeanDefinition to specify an AnnotatedElement that holds
qualifier information. When such element is present, any qualifier that
it defines will be used to find a matching candidate.

Issue: SPR-14725
(cherry picked from commit 2b0bf9f)
2016-09-16 11:02:03 +02:00
Juergen Hoeller 7ddaf49eb2 StringUtils.parseLocaleString accepts Java 7 variants
Issue: SPR-14718
(cherry picked from commit f24ce76)
2016-09-16 10:58:51 +02:00
Juergen Hoeller e947363a11 Timeout exceptions as RuntimeExceptions
Issue: SPR-14669
(cherry picked from commit 6dc1898)
2016-09-15 09:05:14 +02:00
Rossen Stoyanchev 5dbfe48d24 Improve async request timeout handling
Rather than setting the status to 503 directly from the timeout
interceptor which no longer seems to work reliably with Servlet
containers like Jetty even performing an additional ERROR dispatch back
to the original URL, we know rather set the DeferredResult to an
AsyncTimeoutException, which results in a dispatch and standard
handling within Spring MVC. This should be a more reliable way of
dealing with timeouts.

Issue: SPR-14669
2016-09-14 21:31:30 -04:00
Rossen Stoyanchev 07d5f8b123 Check both connection and connected flag
Issue: SPR-14703
2016-09-14 17:23:36 -04:00
kosmaty be99603f1b Fix doc style
Closes gh-1172
2016-09-14 11:08:29 +02:00
Juergen Hoeller 54db496815 Polishing
(cherry picked from commit 404e7cd)
2016-09-13 23:43:58 +02:00
Juergen Hoeller fbe7ddb640 PropertySourcesPropertyResolver does not log retrieved value by default
Issue: SPR-14709
2016-09-13 23:43:52 +02:00
Juergen Hoeller 55c37d2a57 Upgrade to Tomcat 8.5.5 2016-09-13 22:34:19 +02:00
Juergen Hoeller 4b445531f5 HibernateExceptionTranslator avoids JPA IllegalState/ArgumentException translation
Issue: SPR-14681
2016-09-13 22:32:57 +02:00
Juergen Hoeller 12afc263a4 HibernateTemplate reflectively calls getNamedQuery (for runtime compatibility with Hibernate 5.0/5.1 vs 5.2)
Issue: SPR-14676
2016-09-13 22:32:36 +02:00
Juergen Hoeller 040d131284 Polishing
(cherry picked from commit ce42ed4)
2016-09-13 22:31:47 +02:00
Juergen Hoeller 73bbe0849a Revised IllegalArgumentException handling for Formatter parse calls
Issue: SPR-14661
(cherry picked from commit c69e6a3)
2016-09-13 22:31:01 +02:00
Juergen Hoeller 09a0615df0 Consistent callbacks for TypeFilters, ImportSelectors and ImportBeanDefinitionRegistrars
Issue: SPR-14686
(cherry picked from commit 0c2e8a6)
2016-09-13 22:30:29 +02:00
Juergen Hoeller 669d5815c9 Configuration class processing uses MetadataReaderFactory for current ResourceLoader
Issue: SPR-14684
(cherry picked from commit 5405c07)
2016-09-13 22:30:12 +02:00
Juergen Hoeller bd24b97bd3 IdentityHashMap for scheduled tasks (avoiding hashCode calls on bean instances)
Issue: SPR-14666
(cherry picked from commit 480cd2c)
2016-09-13 22:29:59 +02:00
Juergen Hoeller db196ce5d8 Correct ISO DateTime example
Issue: SPR-14675
(cherry picked from commit d5c9cc6)
2016-09-13 22:28:28 +02:00
Juergen Hoeller 4396b211ce Avoid outdated Tibco workaround in shouldCommitAfterNoMessageReceived
Issue: SPR-14697
(cherry picked from commit edbc1e9)
2016-09-13 22:28:07 +02:00
Juergen Hoeller 367949e914 PropertyValue stores source object in common superclass field
Issue: SPR-8337
(cherry picked from commit fa820bc)
2016-09-13 22:27:17 +02:00
Juergen Hoeller ae2bbe7f19 MappingJackson2MessageConverter adds message id and destination to type resolution exception
Issue: SPR-14672
(cherry picked from commit 8c56606)
2016-09-13 22:26:37 +02:00
nkjackzhang 819e14f91b Fix typo
There is no attribute named `path` in `@RequestParam`, so I change it to
`name`.

Closes gh-1165
2016-09-10 07:49:48 +02:00
Brian Clozel fcf3ccba98 Fix default encoding in CONTRIBUTING documentation
Sources should be using UTF-8.

Issue: SPR-14674
Cherry-picked from: d1f60e3de1
2016-09-07 10:48:16 +02:00
nkjackzhang 558a10b54f Fix typo
Closes gh-1158
2016-09-07 09:38:00 +02:00
Brian Clozel 43c60a02f7 Fix response status check in ServletWrbRequest
Issue: SPR-14659
2016-09-06 19:13:03 +02:00
Brian Clozel 6501bc5d32 Align MVC checkNotModified with reactive support
Since SPR-14522, the web reactive framework supports checkNotModified
features. This commit aligns the existing MVC infrastructure with
web reactive's behavior.

Code duplication has been removed from `HttpEntityMethodProcessor`
but the Servlet 2.5 baseline is still respected.

Issue: SPR-14659
Cherry-picked from: cc5300c4d5
2016-09-06 18:17:47 +02:00
Brian Clozel f3dae0c9ad Mention AntPathMatcher regexp support
This commit documents the regexp support in `AntPathMatcher` when
matching for URL patterns. This support is also mentioned in places
where developers can register patterns for ViewControllers or resource
handlers.

Issue: SPR-14652
Cherry-picked from: a8ba065a6e
2016-09-02 11:40:11 +02:00
sylvainlaurent dc2cafc888 Fix class literal in instanceof
Closes gh-1151
2016-09-01 16:23:32 +02:00
Juergen Hoeller 49fc4923be Upgrade to JSR-354 API 1.0.1 and Jackson 2.8 javadocs 2016-09-01 12:56:25 +02:00
Juergen Hoeller efb5f17a60 Documentation updates around configuration classes
(cherry picked from commit aff914c)
2016-09-01 12:52:11 +02:00
Juergen Hoeller 086e764845 ResolvableType.java.forRawClass(Class) supports isAssignableFrom(ResolvableType) as well
Issue: SPR-14648
(cherry picked from commit 1a30252)
2016-08-31 14:57:27 +02:00
Juergen Hoeller c30290b43c @PathVariable supports 'required' attribute (for model attribute methods)
Issue: SPR-14646
(cherry picked from commit e08b1b7)
2016-08-31 14:57:21 +02:00
Brian Clozel d26421fe3b Fix missing ResourceHttpRequestHandler init in registry
Issue: SPR-14577
Cherry-picked from: 7a88776329
2016-08-31 10:47:18 +02:00
Juergen Hoeller 37670924f6 Polishing 2016-08-31 01:53:03 +02:00
Juergen Hoeller ee5143b54b Upgrade to Jackson 2.8.2 and Netty 4.1.5 2016-08-31 00:45:34 +02:00
Juergen Hoeller acbb2544bf Polishing
(cherry picked from commit 4ef428d)
2016-08-31 00:45:25 +02:00
Juergen Hoeller d8f7347000 Consistent comma splitting without regex overhead
Issue: SPR-14635
(cherry picked from commit 03609c1)
2016-08-31 00:44:52 +02:00
Juergen Hoeller 3b91dec462 ApplicationListenerMethodAdapter resolves order on construction
Issue: SPR-14642
(cherry picked from commit 58fa63f)
2016-08-31 00:44:43 +02:00
Juergen Hoeller 05f74b4218 CommonsMultipartResolver explicitly converts FileSizeLimitExceededException
Issue: SPR-14638
(cherry picked from commit 58ffca7)
2016-08-31 00:44:19 +02:00
Juergen Hoeller 8e98177fb3 Avoid collection lookups in StompCommand
Issue: SPR-14636
(cherry picked from commit 899ebd8)
2016-08-31 00:44:14 +02:00
Rossen Stoyanchev 815a3ad0de Relax ServletContext check for resource handling
This is a follow-up on commit fe4046 relaxing the expectation that a
ServletContext is present. Instead we check defensively and fall back
on PathExtensionContentNegotiationStrategy which can use JAF.

Issue: SPR-14577
2016-08-30 12:57:35 -04:00
Rossen Stoyanchev 5075dd4dfa Harden synchronization around SockJS heartbeats
Create an explicit heartbeat task with an experiration flag so that
it can be cancelled reliably vs relying on the ScheduledFutureTask
cancel method which may return true even if the task is already
running.

Issue: SPR-14356
2016-08-30 09:20:07 -04:00
Rossen Stoyanchev ca09dcbe89 Polish media type change in ResourceHttpRequestHandler 2016-08-29 19:48:06 -04:00
Rossen Stoyanchev 198a74d793 Support receipt on DISCONNECT with simple broker
Issue: SPR-14568
2016-08-29 18:30:17 -04:00
Rossen Stoyanchev fe404628e9 Fix media type regression in resource handling
Issue: SPR-14577
2016-08-29 16:39:07 -04:00
Juergen Hoeller 5a004c3b2a LiveBeansView exposes aliases as well
Issue: SPR-14632
(cherry picked from commit 57cb7c7)
2016-08-26 20:18:39 +02:00
Juergen Hoeller 430180aa96 Polishing 2016-08-26 18:33:13 +02:00
Juergen Hoeller e828be96f0 Polishing 2016-08-26 17:29:16 +02:00
Juergen Hoeller 52447efb97 Avoid getParameterType use with Oracle 12c driver by default
Issue: SPR-14629
Issue: SPR-14574
Issue: SPR-14191
2016-08-26 17:29:00 +02:00
Rossen Stoyanchev d09b0fe83a Support target type in JsonPath assertions
This change adds support for a target type in JsonPath assertions in
Spring MVC Test.

The existing assertValue(String expression, Object expectedValue)
transparently falls back on using an alternative JsonPath API that
allows specifying the target type to coerce to.

There is also a new overloaded method
assertValue(String expression, Matcher<T> matcher, Class<T> targetType)
for use with Hamcrest matchers where the target type can be specified.

Issue: SPR-14498
(cherry picked from commit 7fdb892)
2016-08-26 17:28:37 +02:00
Brian Clozel 798d8668a4 Fix server errors for invalid If-None-Match request headers
HttpEntityMethodProcessor should not throw IllegalArgumentExceptions for
invalid If-None-Match headers.

For those cases, this commit makes sure that both
`HttpEntityMethodProcessor` and `ServletWebRequest` have a consistent
behavior and stop processing the request as conditional and leave the
handler handle it.

Issue: SPR-14559
2016-08-26 15:33:02 +02:00
Juergen Hoeller 2a82b8fed9 Consistent use of Charset.forName over JDK 7 StandardCharsets in 4.x line 2016-08-26 13:11:39 +02:00
Juergen Hoeller 696f687419 Moved encodeHttpHeaderFieldParam method to HttpHeaders itself (including tests)
This commit also sets the test source encoding to UTF-8.

Issue: SPR-14547
(cherry picked from commit a8f7f75)
2016-08-26 12:55:34 +02:00
Brian Clozel 9b91b9db8c Add RFC5987 support for HTTP header field params
This commit adds support for HTTP header field parameters encoding, as
described in RFC5987.
Note that the default implementation still relies on US-ASCII encoding,
as the latest rfc7230 Section 3.2.4 says that:

> Newly defined header fields SHOULD limit their field values to
  US-ASCII octets

Issue: SPR-14547
Cherry-picked from: f2faf84f31
2016-08-25 14:39:07 +02:00
Juergen Hoeller 026473280b Polishing 2016-08-25 00:10:06 +02:00
Juergen Hoeller a7849b2861 DefaultListableBeanFactory does not trigger early candidate creation ahead of primary bean selection
Issue: SPR-14611
(cherry picked from commit c4fcdb6)
2016-08-24 23:37:59 +02:00
Juergen Hoeller 74bf659c56 GenericApplicationContext picks up ClassLoader from custom ResourceLoader
Issue: SPR-14626
(cherry picked from commit 405e74b)
2016-08-24 23:36:33 +02:00
Juergen Hoeller c2feedb7a2 Revised assertions in StompHeaderAccessor
Issue: SPR-14625
(cherry picked from commit f3f691c)
2016-08-24 23:36:23 +02:00
Juergen Hoeller 0735e9ba98 Avoid unnecessary String concatenation in StompSubProtocolHandler
Issue: SPR-14624
(cherry picked from commit 56b197b)
2016-08-24 23:36:13 +02:00
Juergen Hoeller ab686732d0 Refined exception message
Issue: SPR-14609
2016-08-24 15:05:43 +02:00
Juergen Hoeller 6d86437369 TransactionAspectSupport stores given PlatformTransactionManager instance as strong reference
Issue: SPR-14609
(cherry picked from commit 951ac5e)
2016-08-24 14:39:19 +02:00
Juergen Hoeller 184285ab27 Polishing 2016-08-24 13:01:54 +02:00
Juergen Hoeller 1e8065d040 Unit test for empty Access-Control-Request-Headers (Chrome 52)
Includes optimized method/header resolution in CorsConfiguration.

Issue: SPR-14617
(cherry picked from commit d047174)
2016-08-24 11:53:44 +02:00
Juergen Hoeller f735d12247 UnsatisfiedDependencyException avoids duplicate nested exception message
Issue: SPR-14607
(cherry picked from commit 93d2287)
2016-08-24 11:53:36 +02:00
Juergen Hoeller 7135bc2dc2 Reintroduced MessageMethodArgumentResolver default constructor
Issue: SPR-14616
(cherry picked from commit c4fff6d)
2016-08-24 11:53:30 +02:00
Stephane Nicoll 9044706796 Remove reference to PayloadApplicationEvent
Issue: SPR-14594
2016-08-19 14:22:52 +02:00
Stephane Nicoll 5f68da3153 Document support for @ManagedBean
Issue: SPR-14600
2016-08-19 13:53:07 +02:00
Juergen Hoeller 5222489a01 Various @since tags (and varargs on setInterceptors)
(cherry picked from commit aac0e63)
2016-08-18 12:40:22 +02:00
Juergen Hoeller 27f830f345 Polishing 2016-08-18 10:28:31 +02:00
Juergen Hoeller 8d7db8e450 DelegatingWebMvcConfiguration properly delegates extendHandlerExceptionResolvers
Also fixes the declared visibility of configurePathMatch and configureAsyncSupport.

Issue: SPR-14599
(cherry picked from commit d2e3a1a)
2016-08-18 09:53:15 +02:00
Juergen Hoeller da56758054 Updated note on CompilationCustomizer and CompilerConfiguration
Issue: SPR-14585
2016-08-17 22:31:13 +02:00
Juergen Hoeller 66dcc4b6db Upgrade to Caffeine 2.3.2 2016-08-17 22:29:21 +02:00
Juergen Hoeller 6eab5622c7 Renamed setDefaultPersistenceUnitRootLocation to setPersistenceUnitRootLocation
(cherry picked from commit f1ab37c)
2016-08-17 22:18:19 +02:00
Juergen Hoeller af53f3d6cf Upgrade to Gradle 2.14.1
Issue: SPR-14570
2016-08-17 21:35:32 +02:00
Juergen Hoeller 188e5327ee Removed duplicate NoHandlerFoundException entry
Issue: SPR-14598
(cherry picked from commit e9f48a4)
2016-08-17 21:30:41 +02:00
Juergen Hoeller 1932a9d729 Polishing
(cherry picked from commit de91b1a)
2016-08-17 21:30:30 +02:00
Juergen Hoeller c926ec477a Polishing 2016-08-17 17:47:14 +02:00
Juergen Hoeller 7b11fa18a1 Revised NoSuchBeanDefinitionException message for proper array class names
Issue: SPR-14595
(cherry picked from commit 022b013)
2016-08-17 17:47:14 +02:00
Juergen Hoeller e6cefdca25 RootBeanDefinition accepts ResolvableType for target type hint
Issue: SPR-14580
(cherry picked from commit 4b06b60)
2016-08-17 17:47:14 +02:00
Juergen Hoeller fbeff475b3 Consistent support for CompilationCustomizers as well as custom CompilerConfiguration
Issue: SPR-14585
(cherry picked from commit 6a0d9d3)
2016-08-17 17:47:14 +02:00
Stephane Nicoll d057099c17 Add setter for defaultPersistenceUnitRootLocation
This commit adds a setter for the default persistence unit's
defaultPersistenceUnitRootLocation attribute.
2016-08-17 17:41:47 +02:00
Stephane Nicoll 411700d7e6 Clarify use of Ehcache
Since we have a dedicated section regarding Ehcache that is only
applicable to Ehcache 2.x, this commit clarifies that Ehcache 3.x is
JSR-107 compliant and the JCache support should be used with it
rather than attempting to configure the Ehcache 2.x support.
2016-08-16 14:03:26 +02:00
Stephane Nicoll b4e9d918f2 Better document #result semantic
Commit 240f254 has introduced support for `java.util.Optional` in the
cache abstraction. If such type is present, the contained value is cached
if it is present.

This new feature slightly changed the semantic of `#result` that was
documented up till this commit as the "return value of the method
invocation". This is no longer true as `#result` for `Optional<T>`
refers to the `T` instance and not the `Optional` instance.

This commit clarifies both the javadoc and the documentation.

Issue: SPR-14587
2016-08-16 13:45:46 +02:00
Igor Mukhin 2756c364d2 Add aditional example to CronSequenceGenerator
CronSequenceGenerator supports comma separated expressions but does not
provide an example for it. This commit adds such an example.

Closes gh-1132
2016-08-16 11:43:15 +02:00
Rob Winch 43faabd4cc Fix HtmlUnitRequestBuilder merge
Previously invoking HtmlUnitRequestBuilder merge caused the pathInfo of
the parent to be corrupted. This could additional invocations with the
same parent.

This fix ensures that the parent is no longer directly used. Instead,
we create a copy of the parent by merging the parent that was passed in
with the copy.

Fixes SPR-14584
2016-08-12 20:49:48 -05:00
Juergen Hoeller a4a71a8904 Polishing 2016-08-11 23:45:50 +02:00
Juergen Hoeller e23ac031ff Avoid stack overflow in case of chained factory-bean references to FactoryBean class
Issue: SPR-14551
(cherry picked from commit 8b5d355)
2016-08-11 23:25:41 +02:00
Juergen Hoeller 79a56967a1 PersistenceAnnotationBeanPostProcessor obtains default EntityManagerFactory via getBean(Class) algorithm
Issue: SPR-7549
(cherry picked from commit 6157fad)
2016-08-11 23:25:35 +02:00
Juergen Hoeller 0bc0453700 Polishing 2016-08-10 16:59:22 +02:00
Juergen Hoeller 35e247aa26 Polishing 2016-08-10 16:21:35 +02:00
Juergen Hoeller 67ba187b6f Polishing
(cherry picked from commit 59a24b4)
2016-08-10 14:57:50 +02:00
Juergen Hoeller 67f0b1986c Consistent spelling for StandaloneMockMvcBuilder's addPlaceholderValue
(cherry picked from commit a4b6682)
2016-08-10 14:57:43 +02:00
Stephane Nicoll 60e0177d00 Fix typo
See gh-1129
2016-08-10 10:46:43 +02:00
Juergen Hoeller 4543a28e51 MethodBasedEvaluationContext reliably exposes varargs
Issue: SPR-14554
(cherry picked from commit fae503d)
2016-08-09 21:31:29 +02:00
Juergen Hoeller aade2d1ec9 Polishing
(cherry picked from commit 9475c06)
2016-08-09 12:37:07 +02:00
Juergen Hoeller 4627545a3b Polishing
(cherry picked from commit eae079a)
2016-08-09 11:03:51 +02:00
Juergen Hoeller e2ba7c9b8c MockClientHttpResponse closes body stream on close()
Issue: SPR-14563
(cherry picked from commit 47e9360)
2016-08-09 11:03:46 +02:00
Juergen Hoeller 6f5596ac5c Upgrade to Hibernate ORM 5.2.2 and Undertow 1.3.24 2016-08-08 16:07:34 +02:00
Juergen Hoeller 7d1c2f191a Consistent default connection release mode with Hibernate 5.1
Issue: SPR-14548
2016-08-08 14:27:24 +02:00
Juergen Hoeller 4ada571384 PathEditor tries file system path in case of non-existing resource
Issue: SPR-14549
(cherry picked from commit d69afaa)
2016-08-08 14:22:46 +02:00
Juergen Hoeller ad8ebbaa05 Test injection for @Lookup-declaring bean
Issue: SPR-14550
(cherry picked from commit d128830)
2016-08-08 14:22:42 +02:00
Stephane Nicoll 4854989db4 Polish Javadoc
Issue: SPR-14552
2016-08-06 17:17:25 +02:00
Sebastien Deleuze 7c5050cf80 Prevent StackOverflowError in AbstractJackson2HttpMessageConverter
Issue: SPR-14520
2016-08-04 11:28:20 -07:00
Spring Buildmaster 14ae8be547 Next Development Version 2016-07-28 08:26:01 +00:00
Juergen Hoeller ff878ea9dc ConfigurationClassParser uses unified ImportStack with chained import analysis
Issue: SPR-14517
(cherry picked from commit d96a66a)
2016-07-28 00:13:05 +02:00
Juergen Hoeller 7021a4be44 JndiPropertySource defensively skips invalid JNDI lookup for property name with colon in resource-ref mode
Issue: SPR-14518
(cherry picked from commit 328e04f)
2016-07-28 00:12:50 +02:00
Juergen Hoeller 5c4737c3d0 Upgrade to Netty 4.1.4 2016-07-27 16:49:37 +02:00
Juergen Hoeller fbf3807af1 Polishing
(cherry picked from commit 5db4495)
2016-07-27 16:49:18 +02:00
Juergen Hoeller 703c37ec88 Isolated circular import detection for scanned configuration classes
Issue: SPR-14517
(cherry picked from commit 316244d)
2016-07-27 16:49:04 +02:00
Juergen Hoeller 96440878bb Polishing 2016-07-27 13:00:30 +02:00
Juergen Hoeller b5c11ffb1c Expose DefaultSubscriptionRegistry's cache limit through SimpleBrokerMessageHandler and MessageBrokerRegistry
Issue: SPR-14516
(cherry picked from commit 6d5af60)
2016-07-27 12:34:28 +02:00
Juergen Hoeller 7f5b323d50 Upgrade to Jetty 9.3.11 (includes fixed Quartz javadoc URL) 2016-07-26 22:19:56 +02:00
Juergen Hoeller 67176e2b75 TransactionAspectSupport avoids hard references to transaction manager beans
Issue: SPR-14511
(cherry picked from commit 02374d7)
2016-07-26 21:46:49 +02:00
Juergen Hoeller 79f3cf3263 Build against Undertow 1.3.x in 4.3.x branch (retaining runtime compatibility Undertow 1.4)
Issue: SPR-14328
2016-07-26 10:08:06 +02:00
Juergen Hoeller 9ee1dc79fd Deprecate JpaSystemException(PersistenceException) constructor to prepare for removal in Spring 5
Issue: SPR-13827
2016-07-26 01:29:51 +02:00
Juergen Hoeller 9e2c34dfa6 Fixed ConcurrentMap declaration
(cherry picked from commit 23135b1)
2016-07-26 00:28:40 +02:00
Juergen Hoeller cc93c2a559 Polishing 2016-07-26 00:03:21 +02:00
Juergen Hoeller 15c7044c4d Upgrade to EhCache 3.1.1 and OkHttp 3.4.1 2016-07-25 15:20:08 +02:00
Juergen Hoeller 0ef80d3579 JasperReportsMultiFormatViewTests does not check for CUSTOM_COMPILATION anymore
Issue: SPR-10423
2016-07-25 15:19:50 +02:00
Juergen Hoeller 95c2e0a996 Upgrade JiBX (and BCEL) towards support of 1.8 bytecode level
This commit also drops the now-unused CUSTOM_COMPILATION test group and the outdated JavaVersion class.

Issue: SPR-10423
(cherry picked from commit 01110f6)
2016-07-25 14:58:43 +02:00
Juergen Hoeller da3e8611e1 Upgrade JiBX (and BCEL) towards support of 1.8 bytecode level
Issue: SPR-10423
2016-07-25 13:08:46 +02:00
Juergen Hoeller 64595597f3 LinkedCaseInsensitiveMap properly overrides HashMap.clone()
Issue: SPR-14509
(cherry picked from commit dd65f7a)
2016-07-25 12:14:51 +02:00
Juergen Hoeller 82f2983cd4 Consistent throwing of BeanNotOfRequiredTypeException even for existing proxy
Issue: SPR-14504
(cherry picked from commit 4a85309)
2016-07-24 15:47:06 +02:00
Juergen Hoeller 9451177c35 Polishing
(cherry picked from commit 382a931)
2016-07-22 22:45:14 +02:00
Juergen Hoeller 9ed087d5da Consistent support for multiple Accept headers
Issue: SPR-14506
(cherry picked from commit e59a599)
2016-07-22 22:45:04 +02:00
Juergen Hoeller 77f22e9674 DataSource adapters expose setCatalog/setSchema next to setUsername/setPassword
Issue: SPR-14501
(cherry picked from commit 610bdf1)
2016-07-21 14:13:37 +02:00
Juergen Hoeller 8ccfdbbcf9 ResourcePatternUtils.getResourcePatternResolver actually accepts null argument
Issue: SPR-14500
(cherry picked from commit e756a5b)
2016-07-21 14:09:32 +02:00
Juergen Hoeller 5a92aa4e06 Polishing
(cherry picked from commit a39276a)
2016-07-20 23:23:30 +02:00
Juergen Hoeller 7b1010cf61 Polishing 2016-07-20 22:31:45 +02:00
Juergen Hoeller 45b2f5bac4 Upgrade to Jackson 2.8.1 2016-07-20 22:31:25 +02:00
Juergen Hoeller 36e1c82ef5 Backported refinements and polishing 2016-07-20 21:46:25 +02:00
Juergen Hoeller 503d65d570 Avoid JDK proxy against CGLIB Factory interface and assert required type when resolving dependency
Issue: SPR-14478
(cherry picked from commit 0e3f0bd)
2016-07-20 21:45:41 +02:00
Juergen Hoeller fe17f8da41 BeanWrapperImpl.setBeanInstance correctly exposes root object
Issue: SPR-14474
(cherry picked from commit 938b56c)
2016-07-20 21:44:46 +02:00
Juergen Hoeller b583aa1579 Avoid dependency on WebUtils for extracting file extension
Issue: SPR-14479
(cherry picked from commit adc595b)
2016-07-20 21:44:37 +02:00
Juergen Hoeller e0d81b97bb SerializableTypeWrapper reobtains type accessors from declaring interface
Issue: SPR-14487
(cherry picked from commit 8580483)
2016-07-20 21:41:42 +02:00
Juergen Hoeller 90752f9d87 Deprecate mock.staticmock package
Issue: SPR-14485
2016-07-20 21:41:30 +02:00
Juergen Hoeller 3663aa675a GenericSqlQuery configured with RowMapper instance
Issue: SPR-14489
(cherry picked from commit 7287bae)
2016-07-20 21:40:48 +02:00
Juergen Hoeller 1ca4b81856 Reinstated tests for implicit aliases
Issue: SPR-14437
(cherry picked from commit 5ea8c26)
2016-07-20 21:40:33 +02:00
Juergen Hoeller 4e7e06f549 Reliably pass CurrentTenantIdentifierResolver to SessionFactory
Issue: SPR-14476
2016-07-20 21:40:26 +02:00
Sebastien Deleuze b2f0bdb0f4 Polishing
Issue: SPR-14470
2016-07-20 09:16:50 +02:00
Rossen Stoyanchev d98bd34200 Remove isAsyncStarted assertion
Issue: SPR-14444
2016-07-19 16:44:46 -04:00
Sebastien Deleuze 940bdd878e Fix ParameterizedType + contextClass support in Jackson converter
Issue: SPR-14470
2016-07-19 18:10:51 +02:00
Vladimir L df556333a8 Add StreamingResponseBody MockMvc sample tests
Issue: SPR-14456
(cherry picked from 7da63c)
2016-07-19 10:48:29 -04:00
Stephane Nicoll 116f05eda6 Revert "Upgrade to EJB 3.1" 2016-07-18 13:37:43 +02:00
Stephane Nicoll b187bbeca3 Upgrade to EJB 3.1 2016-07-18 13:22:54 +02:00
Do Nhu Vy 479a83b628 Fix broken hyperlink
Closes gh-1114
2016-07-18 08:17:49 +02:00
Fredrik Sundberg 1c18100143 Fix javadoc reference
Method is called nextBackOff() and not nextBackOffMillis().

Closes gh-1115
2016-07-18 08:15:41 +02:00
Juergen Hoeller 5d3c0f33f6 Upgrade to Netty 4.1.3 and Tomcat 8.5.4 2016-07-15 22:47:22 +02:00
Juergen Hoeller afe106e254 Polishing 2016-07-15 22:47:12 +02:00
Juergen Hoeller 69dd40ec89 Javadoc fixes and pruning of deprecated references 2016-07-15 22:47:05 +02:00
Sam Brannen dee50d5e28 Polish annotation utils
(cherry picked from commit 177f4ec)
2016-07-15 22:21:23 +02:00
Juergen Hoeller 9e93403857 ConfigurationClassParser load annotations through source class loader
Issue: SPR-10343
2016-07-15 16:02:06 +02:00
Juergen Hoeller 12bff6b3a0 Velocity deprecation note in reference documentation
Issue: SPR-14460
2016-07-15 15:44:13 +02:00
Juergen Hoeller 70e666b4a3 MultipartResolutionDelegate's resolveMultipartArgument properly operates on Servlet 2.5
Issue: SPR-14461
2016-07-15 15:42:32 +02:00
Juergen Hoeller 29f980ec72 Unwrap JPA PersistenceException on flush failure (for Hibernate 5.2)
Issue: SPR-14457
2016-07-15 15:40:38 +02:00
Juergen Hoeller 1d39d762f0 HibernateExceptionTranslator converts JPA exceptions as well (for Hibernate 5.2)
Issue: SPR-14455
2016-07-15 15:40:26 +02:00
Juergen Hoeller 4d6d5e0ddd Consistent alias processing behind AnnotatedTypeMetadata abstraction (also for ASM)
Issue: SPR-14427
(cherry picked from commit 3d3407c)
2016-07-15 15:40:01 +02:00
Juergen Hoeller 4ea5f070a4 MessageHeaderAccessor properly removes header even in case of null value
Issue: SPR-14468
(cherry picked from commit b166358)
2016-07-15 15:39:33 +02:00
Juergen Hoeller da59b4da9b CronSequenceGenerator prevents stack overflow in case of inverted range
Issue: SPR-14462
(cherry picked from commit e431624)
2016-07-15 15:39:17 +02:00
Juergen Hoeller 0065a160cc StandardTypeConverter initializes default ConversionService against volatile field
Issue: SPR-14465
(cherry picked from commit 6d91d54)
2016-07-15 15:39:09 +02:00
Juergen Hoeller 52f46c7fea Aspect actually applies in PersistenceExceptionTranslationPostProcessorTests
Issue: SPR-14457
(cherry picked from commit 04e9c2b)
2016-07-15 15:38:44 +02:00
Juergen Hoeller f0a826ec0c AbstractHandlerMethodMapping adds type+method info to getMappingForMethod exceptions
Issue: SPR-14452
(cherry picked from commit 8ccd727)
2016-07-15 15:38:23 +02:00
Juergen Hoeller 5c3c0f73c1 Configurable UrlPathHelper in PathExtensionContentNegotiationStrategy
This commit also aligns ResourceUrlProvider's and RequestMappingInfo's UrlPathHelper setter/getter signatures.

Issue: SPR-14454
(cherry picked from commit 84afc60)
2016-07-15 15:37:56 +02:00
Juergen Hoeller be0b71ce31 Fixed typo: "occured"->"occurred"
(cherry picked from commit c43e749)
2016-07-15 15:37:11 +02:00
Juergen Hoeller f85d48dd31 Added PathEditor for NIO file system resolution
Issue: SPR-14436
(cherry picked from commit 23c2b6a)
2016-07-15 15:37:02 +02:00
Juergen Hoeller a1b58ee601 DigestUtils processes InputStream with buffered read instead of full copy
Issue: SPR-14427
(cherry picked from commit 61db8e9)
2016-07-15 15:34:36 +02:00
Juergen Hoeller e30429051d Polishing
(cherry picked from commit 6aa5931)
2016-07-15 15:34:27 +02:00
fisache 942ead75e2 Polish doc
Closes gh-1108
2016-07-14 19:16:20 +02:00
nkjackzhang 453688f6df Polish doc
Closes gh-1110
2016-07-14 11:57:41 +02:00
Stephane Nicoll 7d7a161102 Polish contribution
Closes gh-1070
2016-07-14 11:26:31 +02:00
spodgurskiy aaa223ae66 Fix MethodBasedEvaluationContext.lazyLoadArguments
This commit fix a potential `ArrayIndexOutOfBoundsException` if
`lazyLoadArguments` is called with an empty variable argument.

See gh-1070
2016-07-14 11:26:20 +02:00
Brian Clozel d11c624fb0 Polish AntPathMatcher.setTrimTokens javadoc
Issue: SPR-14247
Cherry-picked from 147a35f
2016-07-12 14:50:00 +02:00
nkjackzhang 275e51b19d Polish doc
Closes gh-1107
2016-07-12 08:51:35 +02:00
Stephane Nicoll ab62edeeaa Fix NoOpCache handling of get(key,callable)
This commit fixes the method that takes a Callable to actually always
invoke it rather than returning null.

Issue: SPR-14445
2016-07-11 10:36:51 +02:00
Sam Brannen 813108a928 Ensure TestContextManager always tracks after-class exception
This commit fixes a minor bug introduced in 0adc4921ed.

Issue: SPR-14447
2016-07-10 16:00:30 +02:00
Juergen Hoeller 3c14911401 Polishing 2016-07-06 17:59:49 +02:00
Juergen Hoeller 4337f14627 Upgrade to Jackson 2.8 GA 2016-07-06 17:42:10 +02:00
Juergen Hoeller 92d78c10a2 Polishing (backported from master) 2016-07-06 17:13:18 +02:00
Juergen Hoeller 16d5ba9b3a Restored binary compatibility with Hibernate 5.0/5.1's Query type
Issue: SPR-14425
2016-07-06 16:11:15 +02:00
Juergen Hoeller 52065a736b Avoid canonicalName call for already-seen bean name
Issue: SPR-14433
(cherry picked from commit 5890758)
2016-07-06 16:09:32 +02:00
Stephane Nicoll 11cb109114 Upgrade copyright 2016-07-04 12:45:34 +02:00
Stephane Nicoll d7eadd41d6 Switch to 4.3.2.BUILD-SNAPSHOT 2016-07-04 12:28:13 +02:00
650 changed files with 11381 additions and 7875 deletions
+4 -5
View File
@@ -88,15 +88,14 @@ present in the framework.
1. Preserve existing formatting; i.e. do not reformat code for its own sake
1. Search the codebase using `git grep` and other tools to discover common
naming conventions, etc.
1. Latin-1 (ISO-8859-1) encoding for Java sources; use `native2ascii` to convert
if necessary
1. UTF-8 encoding for Java sources
### Add Apache license header to all new classes
```java
/*
* 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.
@@ -124,11 +123,11 @@ modified a file in 2015 whose header still reads:
* Copyright 2002-2011 the original author or authors.
```
Then be sure to update it to 2015 accordingly:
Then be sure to update it to 2016 accordingly:
```java
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
```
### Use @since tags for newly-added public API types and methods
+40 -47
View File
@@ -32,51 +32,51 @@ configure(allprojects) { project ->
version = qualifyVersionIfNecessary(version)
ext.aspectjVersion = "1.8.9"
ext.caffeineVersion = "2.3.1"
ext.caffeineVersion = "2.3.4"
ext.eclipselinkVersion = "2.4.2"
ext.ehcacheVersion = "2.10.2"
ext.ehcacheVersion = "2.10.3"
ext.ehcachejcacheVersion = "1.0.1"
ext.ehcache3Version = "3.1.0"
ext.ehcache3Version = "3.1.3"
ext.ejbVersion = "3.0"
ext.fileuploadVersion = "1.3.2"
ext.freemarkerVersion = "2.3.23"
ext.groovyVersion = "2.4.7"
ext.gsonVersion = "2.7"
ext.guavaVersion = "19.0"
ext.gsonVersion = "2.8.0"
ext.guavaVersion = "20.0"
ext.hamcrestVersion = "1.3"
ext.hibernate3Version = "3.6.10.Final"
ext.hibernate4Version = "4.3.11.Final"
ext.hibernate5Version = "5.2.1.Final"
ext.hibernate5Version = "5.2.4.Final"
ext.hibval4Version = "4.3.2.Final"
ext.hibval5Version = "5.2.4.Final"
ext.hsqldbVersion = "2.3.4"
ext.httpasyncVersion = "4.1.2"
ext.httpclientVersion = "4.5.2"
ext.jackson2Version = "2.8.0.rc2"
ext.jackson2Version = "2.8.4"
ext.jasperreportsVersion = "6.2.1" // our tests fail with JR-internal NPEs against 6.2.2 and higher
ext.javamailVersion = "1.5.5"
ext.jettyVersion = "9.3.10.v20160621"
ext.jodaVersion = "2.9.4"
ext.jrubyVersion = "1.7.25" // JRuby 9000 only supported through JSR-223 (StandardScriptFactory)
ext.javamailVersion = "1.5.6"
ext.jettyVersion = "9.3.13.v20161014"
ext.jodaVersion = "2.9.5"
ext.jrubyVersion = "1.7.26" // JRuby 9000 only supported through JSR-223 (StandardScriptFactory)
ext.jtaVersion = "1.2"
ext.junitVersion = "4.12"
ext.log4jVersion = "1.2.17"
ext.nettyVersion = "4.1.1.Final"
ext.nettyVersion = "4.1.6.Final"
ext.okhttpVersion = "2.7.5"
ext.okhttp3Version = "3.3.1"
ext.okhttp3Version = "3.4.2"
ext.openjpaVersion = "2.4.1"
ext.poiVersion = "3.14"
ext.reactorVersion = "2.0.8.RELEASE"
ext.romeVersion = "1.6.0"
ext.romeVersion = "1.7.0"
ext.slf4jVersion = "1.7.21"
ext.snakeyamlVersion = "1.17"
ext.snifferVersion = "1.15"
ext.testngVersion = "6.9.10"
ext.tiles2Version = "2.2.2"
ext.tiles3Version = "3.0.5"
ext.tomcatVersion = "8.5.3"
ext.tiles3Version = "3.0.7"
ext.tomcatVersion = "8.5.6"
ext.tyrusVersion = "1.3.5" // constrained by WebLogic 12.1.3 support
ext.undertowVersion = "1.4.0.CR2"
ext.undertowVersion = "1.3.25.Final"
ext.xmlunitVersion = "1.6"
ext.xstreamVersion = "1.4.9"
@@ -110,11 +110,13 @@ configure(allprojects) { project ->
compileJava {
sourceCompatibility = 1.6
targetCompatibility = 1.6
options.encoding = 'UTF-8'
}
compileTestJava {
sourceCompatibility = 1.8
targetCompatibility = 1.8
options.encoding = 'UTF-8'
options.compilerArgs += "-parameters"
}
@@ -199,10 +201,10 @@ configure(allprojects) { project ->
"http://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/",
"http://ehcache.org/apidocs/${ehcacheVersion}",
"http://ehcache.org/apidocs/${ehcache3Version}",
"http://quartz-scheduler.org/api/2.2.0/",
"http://fasterxml.github.io/jackson-core/javadoc/2.7/",
"http://fasterxml.github.io/jackson-databind/javadoc/2.7/",
"http://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.7/",
"http://quartz-scheduler.org/api/2.2.1/",
"http://fasterxml.github.io/jackson-core/javadoc/2.8/",
"http://fasterxml.github.io/jackson-databind/javadoc/2.8/",
"http://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.8/",
"http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/"
] as String[]
}
@@ -355,7 +357,7 @@ project("spring-core") {
optional("log4j:log4j:${log4jVersion}")
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
testCompile("xmlunit:xmlunit:${xmlunitVersion}")
testCompile("com.fasterxml.woodstox:woodstox-core:5.0.2") {
testCompile("com.fasterxml.woodstox:woodstox-core:5.0.3") {
exclude group: "stax", module: "stax-api"
}
}
@@ -477,7 +479,7 @@ project("spring-context") {
optional("javax.inject:javax.inject:1")
optional("javax.ejb:ejb-api:${ejbVersion}")
optional("javax.enterprise.concurrent:javax.enterprise.concurrent-api:1.0")
optional("javax.money:money-api:1.0")
optional("javax.money:money-api:1.0.1")
optional("org.eclipse.persistence:javax.persistence:2.0.0")
optional("javax.validation:validation-api:1.0.0.GA")
optional("org.hibernate:hibernate-validator:${hibval4Version}")
@@ -556,13 +558,6 @@ project("spring-oxm") {
description = "Spring Object/XML Marshalling"
apply from: "oxm.gradle"
compileTestJava {
// necessary to avoid java.lang.VerifyError on jibx compilation
// see http://jira.codehaus.org/browse/JIBX-465
sourceCompatibility = 1.6
targetCompatibility = 1.6
}
dependencies {
compile(project(":spring-beans"))
compile(project(":spring-core"))
@@ -581,14 +576,12 @@ project("spring-oxm") {
testCompile(project(":spring-context"))
testCompile("xmlunit:xmlunit:${xmlunitVersion}")
testCompile("xpp3:xpp3:1.1.4c")
testCompile("org.codehaus.jettison:jettison:1.3.7") {
testCompile("org.codehaus.jettison:jettison:1.3.8") {
exclude group: 'stax', module: 'stax-api'
}
if (compileTestJava.enabled) {
testCompile(files(genCastor.classesDir).builtBy(genCastor))
testCompile(files(genJaxb.classesDir).builtBy(genJaxb))
testCompile(files(genXmlbeans.classesDir).builtBy(genXmlbeans))
}
testCompile(files(genCastor.classesDir).builtBy(genCastor))
testCompile(files(genJaxb.classesDir).builtBy(genJaxb))
testCompile(files(genXmlbeans.classesDir).builtBy(genXmlbeans))
}
}
@@ -621,9 +614,9 @@ 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.192")
optional("org.apache.derby:derby:10.12.1.1")
optional("org.apache.derby:derbyclient:10.12.1.1")
optional("com.h2database:h2:1.4.193")
optional("org.apache.derby:derby:10.13.1.1")
optional("org.apache.derby:derbyclient:10.13.1.1")
}
}
@@ -879,10 +872,10 @@ project("spring-webmvc") {
testCompile("commons-io:commons-io:1.3")
testCompile("joda-time:joda-time:${jodaVersion}")
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
testCompile("org.jruby:jruby:${jrubyVersion}")
testCompile("org.python:jython-standalone:2.5.3")
testCompile("org.mozilla:rhino:1.7.7.1")
testCompile("org.webjars:underscorejs:1.8.3")
testRuntime("org.jruby:jruby:${jrubyVersion}")
testRuntime("org.python:jython-standalone:2.5.3")
testRuntime("org.webjars:underscorejs:1.8.3")
}
}
@@ -1008,10 +1001,10 @@ project("spring-test") {
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
optional("org.hamcrest:hamcrest-core:${hamcrestVersion}")
optional("xmlunit:xmlunit:${xmlunitVersion}")
optional("net.sourceforge.htmlunit:htmlunit:2.22")
optional("org.seleniumhq.selenium:htmlunit-driver:2.21")
optional("net.sourceforge.htmlunit:htmlunit:2.23")
optional("org.seleniumhq.selenium:htmlunit-driver:2.23.2")
optional("org.seleniumhq.selenium:selenium-java:2.53.1")
optional("org.skyscreamer:jsonassert:1.3.0")
optional("org.skyscreamer:jsonassert:1.4.0")
optional("com.jayway.jsonpath:json-path:2.2.0")
testCompile(project(":spring-context-support"))
testCompile(project(":spring-oxm"))
@@ -1036,7 +1029,7 @@ project("spring-test") {
testCompile("javax.cache:cache-api:1.0.0")
testRuntime("log4j:log4j:${log4jVersion}")
testRuntime("org.ehcache:ehcache:${ehcache3Version}")
testRuntime("org.terracotta:management-model:2.0.0")
testRuntime("org.terracotta:management-model:2.3.0")
}
task testNG(type: Test) {
@@ -1367,7 +1360,7 @@ configure(rootProject) {
task wrapper(type: Wrapper) {
description = "Generates gradlew[.bat] scripts"
gradleVersion = "2.13"
gradleVersion = "2.14.1"
doLast() {
def gradleOpts = "-XX:MaxMetaspaceSize=1024m -Xmx1024m"
+1 -1
View File
@@ -1 +1 @@
version=4.3.1.BUILD-SNAPSHOT
version=4.3.4.RELEASE
Binary file not shown.
+2 -2
View File
@@ -1,6 +1,6 @@
#Wed Jun 15 12:59:30 CEST 2016
#Wed Aug 17 21:21:18 CEST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip
@@ -46,7 +46,7 @@ public interface MethodInterceptor extends Interceptor {
* after the invocation. Polite implementations would certainly
* like to invoke {@link Joinpoint#proceed()}.
* @param invocation the method invocation joinpoint
* @return the result of the call to {@link Joinpoint#proceed();
* @return the result of the call to {@link Joinpoint#proceed()};
* might be intercepted by the interceptor
* @throws Throwable if the interceptors or the target object
* throws an exception
@@ -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.
@@ -55,10 +55,12 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
return this.aspectClass.newInstance();
}
catch (InstantiationException ex) {
throw new AopConfigException("Unable to instantiate aspect class [" + this.aspectClass.getName() + "]", ex);
throw new AopConfigException(
"Unable to instantiate aspect class: " + this.aspectClass.getName(), ex);
}
catch (IllegalAccessException ex) {
throw new AopConfigException("Cannot access element class [" + this.aspectClass.getName() + "]", ex);
throw new AopConfigException(
"Could not access aspect constructor: " + this.aspectClass.getName(), ex);
}
}
@@ -97,8 +97,19 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
@Override
public Object getAspectCreationMutex() {
return (this.beanFactory instanceof ConfigurableBeanFactory ?
((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex() : this);
if (this.beanFactory != null) {
if (this.beanFactory.isSingleton(name)) {
// Rely on singleton semantics provided by the factory -> no local lock.
return null;
}
else if (this.beanFactory instanceof ConfigurableBeanFactory) {
// No singleton guarantees from the factory -> let's lock locally but
// reuse the factory's singleton lock, just in case a lazy dependency
// of our advice bean happens to trigger the singleton lock implicitly...
return ((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex();
}
}
return this;
}
/**
@@ -48,9 +48,15 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
@Override
public Object getAspectInstance() {
if (this.materialized == null) {
synchronized (this.maaif.getAspectCreationMutex()) {
if (this.materialized == null) {
this.materialized = this.maaif.getAspectInstance();
Object mutex = this.maaif.getAspectCreationMutex();
if (mutex == null) {
this.materialized = this.maaif.getAspectInstance();
}
else {
synchronized (mutex) {
if (this.materialized == null) {
this.materialized = this.maaif.getAspectInstance();
}
}
}
}
@@ -41,7 +41,7 @@ public interface MetadataAwareAspectInstanceFactory extends AspectInstanceFactor
/**
* Return the best possible creation mutex for this factory.
* @return the mutex object (never {@code null})
* @return the mutex object (may be {@code null} for no mutex to use)
* @since 4.3
*/
Object getAspectCreationMutex();
@@ -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.
@@ -71,7 +71,7 @@ public abstract class AbstractInterceptorDrivenBeanDefinitionDecorator implement
BeanDefinition interceptorDefinition = createInterceptorDefinition(node);
// generate name and register the interceptor
String interceptorName = existingBeanName + "." + getInterceptorNameSuffix(interceptorDefinition);
String interceptorName = existingBeanName + '.' + getInterceptorNameSuffix(interceptorDefinition);
BeanDefinitionReaderUtils.registerBeanDefinition(
new BeanDefinitionHolder(interceptorDefinition, interceptorName), registry);
@@ -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.
@@ -139,7 +139,8 @@ public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanC
* @return whether the given interface is an internal language interface
*/
protected boolean isInternalLanguageInterface(Class<?> ifc) {
return ifc.getName().equals("groovy.lang.GroovyObject");
return (ifc.getName().equals("groovy.lang.GroovyObject") ||
ifc.getName().endsWith(".cglib.proxy.Factory"));
}
}
@@ -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.
@@ -246,7 +246,7 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
*/
@Override
protected Object invokeUnderTrace(MethodInvocation invocation, Log logger) throws Throwable {
String name = invocation.getMethod().getDeclaringClass().getName() + "." + invocation.getMethod().getName();
String name = ClassUtils.getQualifiedMethodName(invocation.getMethod());
StopWatch stopWatch = new StopWatch(name);
Object returnValue = null;
boolean exitThroughException = false;
@@ -46,7 +46,7 @@ public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcu
private BeanFactory beanFactory;
private transient Advice advice;
private transient volatile Advice advice;
private transient volatile Object adviceMonitor = new Object();
@@ -98,12 +98,28 @@ public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcu
@Override
public Advice getAdvice() {
synchronized (this.adviceMonitor) {
if (this.advice == null && this.adviceBeanName != null) {
Assert.state(this.beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'");
this.advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
Advice advice = this.advice;
if (advice != null || this.adviceBeanName == null) {
return advice;
}
Assert.state(this.beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'");
if (this.beanFactory.isSingleton(this.adviceBeanName)) {
// Rely on singleton semantics provided by the factory.
advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
this.advice = advice;
return advice;
}
else {
// No singleton guarantees from the factory -> let's lock locally but
// reuse the factory's singleton lock, just in case a lazy dependency
// of our advice bean happens to trigger the singleton lock implicitly...
synchronized (this.adviceMonitor) {
if (this.advice == null) {
this.advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
}
return this.advice;
}
return this.advice;
}
}
@@ -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 java.util.Arrays;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -129,8 +130,8 @@ public abstract class AbstractRegexpMethodPointcut extends StaticMethodMatcherPo
*/
@Override
public boolean matches(Method method, Class<?> targetClass) {
return ((targetClass != null && matchesPattern(targetClass.getName() + "." + method.getName())) ||
matchesPattern(method.getDeclaringClass().getName() + "." + method.getName()));
return ((targetClass != null && matchesPattern(ClassUtils.getQualifiedMethodName(method, targetClass))) ||
matchesPattern(ClassUtils.getQualifiedMethodName(method)));
}
/**
@@ -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.
@@ -39,7 +39,7 @@ import org.springframework.aop.TargetSource;
public abstract class AbstractRefreshableTargetSource implements TargetSource, Refreshable {
/** Logger available to subclasses */
protected Log logger = LogFactory.getLog(getClass());
protected final Log logger = LogFactory.getLog(getClass());
protected Object targetObject;
@@ -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.
@@ -16,6 +16,8 @@
package org.springframework.aop.scope;
import java.util.Arrays;
import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
@@ -28,18 +30,21 @@ import static org.springframework.tests.TestResourceUtils.*;
/**
* @author Mark Fisher
* @author Chris Beams
* @author Juergen Hoeller
*/
public final class ScopedProxyAutowireTests {
public class ScopedProxyAutowireTests {
private static final Class<?> CLASS = ScopedProxyAutowireTests.class;
private static final Resource SCOPED_AUTOWIRE_TRUE_CONTEXT = qualifiedResource(CLASS, "scopedAutowireTrue.xml");
private static final Resource SCOPED_AUTOWIRE_FALSE_CONTEXT = qualifiedResource(CLASS, "scopedAutowireFalse.xml");
@Test
public void testScopedProxyInheritsAutowireCandidateFalse() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(SCOPED_AUTOWIRE_FALSE_CONTEXT);
assertTrue(Arrays.asList(bf.getBeanNamesForType(TestBean.class, false, false)).contains("scoped"));
TestBean autowired = (TestBean) bf.getBean("autowired");
TestBean unscoped = (TestBean) bf.getBean("unscoped");
assertSame(unscoped, autowired.getChild());
@@ -49,6 +54,7 @@ public final class ScopedProxyAutowireTests {
public void testScopedProxyReplacesAutowireCandidateTrue() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(SCOPED_AUTOWIRE_TRUE_CONTEXT);
assertTrue(Arrays.asList(bf.getBeanNamesForType(TestBean.class, false, false)).contains("scoped"));
TestBean autowired = (TestBean) bf.getBean("autowired");
TestBean scoped = (TestBean) bf.getBean("scoped");
assertSame(scoped, autowired.getChild());
@@ -1,6 +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,27 +28,21 @@ public class NopInterceptor implements MethodInterceptor {
private int count;
/**
* @see org.aopalliance.intercept.MethodInterceptor#invoke(MethodInvocation)
*/
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
increment();
return invocation.proceed();
}
protected void increment() {
this.count++;
}
public int getCount() {
return this.count;
}
protected void increment() {
++count;
}
@Override
public int hashCode() {
return 0;
}
@Override
public boolean equals(Object other) {
@@ -62,5 +55,9 @@ public class NopInterceptor implements MethodInterceptor {
return this.count == ((NopInterceptor) other).count;
}
@Override
public int hashCode() {
return NopInterceptor.class.hashCode();
}
}
@@ -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.
@@ -28,22 +28,10 @@ import org.springframework.util.ObjectUtils;
@SuppressWarnings("serial")
public class SerializablePerson implements Person, Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
@Override
public int getAge() {
return age;
}
@Override
public void setAge(int age) {
this.age = age;
}
@Override
public String getName() {
@@ -55,6 +43,16 @@ public class SerializablePerson implements Person, Serializable {
this.name = name;
}
@Override
public int getAge() {
return age;
}
@Override
public void setAge(int age) {
this.age = age;
}
@Override
public Object echo(Object o) throws Throwable {
if (o instanceof Throwable) {
@@ -63,10 +61,6 @@ public class SerializablePerson implements Person, Serializable {
return o;
}
@Override
public int hashCode() {
return 0;
}
@Override
public boolean equals(Object other) {
@@ -77,4 +71,9 @@ public class SerializablePerson implements Person, Serializable {
return p.age == age && ObjectUtils.nullSafeEquals(name, p.name);
}
@Override
public int hashCode() {
return SerializablePerson.class.hashCode();
}
}
@@ -36,7 +36,9 @@ import org.springframework.util.ObjectUtils;
* @author Rod Johnson
* @author Ramnivas Laddad
* @author Sam Brannen
* @deprecated as of Spring 4.3, in favor of a custom aspect for such purposes
*/
@Deprecated
public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMethod()) {
private final Expectations expectations = new Expectations();
@@ -59,7 +59,9 @@ import org.aspectj.lang.annotation.SuppressAjWarnings;
* @author Ramnivas Laddad
* @author Sam Brannen
* @see MockStaticEntityMethods
* @deprecated as of Spring 4.3, in favor of a custom aspect for such purposes
*/
@Deprecated
@RequiredTypes("javax.persistence.Entity")
public aspect AnnotationDrivenStaticEntityMockingControl extends AbstractMethodMockingControl {
@@ -29,7 +29,9 @@ import java.lang.annotation.Target;
*
* @author Rod Johnson
* @author Sam Brannen
* @deprecated as of Spring 4.3, in favor of a custom aspect for such purposes
*/
@Deprecated
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MockStaticEntityMethods {
@@ -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.
@@ -458,7 +458,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
private GroovyBeanDefinitionWrapper invokeBeanDefiningMethod(String beanName, Object[] args) {
boolean hasClosureArgument = args[args.length - 1] instanceof Closure;
if (args[0] instanceof Class) {
Class<?> beanClass = (args[0] instanceof Class ? (Class) args[0] : args[0].getClass());
Class<?> beanClass = (args[0] instanceof Class ? (Class<?>) args[0] : args[0].getClass());
if (args.length >= 1) {
if (hasClosureArgument) {
if (args.length-1 != 1) {
@@ -94,7 +94,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
private String nestedPath = "";
private Object rootObject;
Object rootObject;
/**
* Map with cached nested Accessors: nested path -> Accessor instance.
@@ -590,7 +590,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
throw new ConversionNotSupportedException(pce, requiredType, ex);
}
catch (Throwable ex) {
catch (IllegalArgumentException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
throw new TypeMismatchException(pce, requiredType, ex);
@@ -914,11 +914,9 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
return BeanUtils.instantiate(type);
}
}
catch (Exception ex) {
// TODO: Root cause exception context is lost here; just exception message preserved.
// Should we throw another exception type that preserves context instead?
catch (Throwable ex) {
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + name,
"Could not instantiate property type [" + type.getName() + "] to auto-grow nested property path: " + ex);
"Could not instantiate property type [" + type.getName() + "] to auto-grow nested property path", ex);
}
}
@@ -148,7 +148,7 @@ public abstract class AbstractPropertyAccessor extends TypeConverterSupport impl
* @throws InvalidPropertyException if there is no such property or
* if the property isn't writable
* @throws PropertyAccessException if the property was valid but the
* accessor method failed or a type mismatch occured
* accessor method failed or a type mismatch occurred
*/
@Override
public abstract void setPropertyValue(String propertyName, Object value) throws BeansException;
@@ -63,11 +63,10 @@ public abstract class BeanUtils {
/**
* Convenience method to instantiate a class using its no-arg constructor.
* As this method doesn't try to load classes by name, it should avoid
* class-loading issues.
* @param clazz class to instantiate
* @return the new instance
* @throws BeanInstantiationException if the bean cannot be instantiated
* @see Class#newInstance()
*/
public static <T> T instantiate(Class<T> clazz) throws BeanInstantiationException {
Assert.notNull(clazz, "Class must not be null");
@@ -87,13 +86,12 @@ public abstract class BeanUtils {
/**
* Instantiate a class using its no-arg constructor.
* As this method doesn't try to load classes by name, it should avoid
* class-loading issues.
* <p>Note that this method tries to set the constructor accessible
* if given a non-accessible (that is, non-public) constructor.
* @param clazz class to instantiate
* @return the new instance
* @throws BeanInstantiationException if the bean cannot be instantiated
* @see Constructor#newInstance
*/
public static <T> T instantiateClass(Class<T> clazz) throws BeanInstantiationException {
Assert.notNull(clazz, "Class must not be null");
@@ -111,17 +109,15 @@ public abstract class BeanUtils {
/**
* Instantiate a class using its no-arg constructor and return the new instance
* as the specified assignable type.
* <p>Useful in cases where
* the type of the class to instantiate (clazz) is not available, but the type
* desired (assignableTo) is known.
* <p>As this method doesn't try to load classes by name, it should avoid
* class-loading issues.
* <p>Note that this method tries to set the constructor accessible
* if given a non-accessible (that is, non-public) constructor.
* <p>Useful in cases where the type of the class to instantiate (clazz) is not
* available, but the type desired (assignableTo) is known.
* <p>Note that this method tries to set the constructor accessible if given a
* non-accessible (that is, non-public) constructor.
* @param clazz class to instantiate
* @param assignableTo type that clazz must be assignableTo
* @return the new instance
* @throws BeanInstantiationException if the bean cannot be instantiated
* @see Constructor#newInstance
*/
@SuppressWarnings("unchecked")
public static <T> T instantiateClass(Class<?> clazz, Class<T> assignableTo) throws BeanInstantiationException {
@@ -131,14 +127,13 @@ public abstract class BeanUtils {
/**
* Convenience method to instantiate a class using the given constructor.
* As this method doesn't try to load classes by name, it should avoid
* class-loading issues.
* <p>Note that this method tries to set the constructor accessible
* if given a non-accessible (that is, non-public) constructor.
* <p>Note that this method tries to set the constructor accessible if given a
* non-accessible (that is, non-public) constructor.
* @param ctor the constructor to instantiate
* @param args the constructor arguments to apply
* @return the new instance
* @throws BeanInstantiationException if the bean cannot be instantiated
* @see Constructor#newInstance
*/
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
@@ -141,6 +141,7 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
*/
public void setBeanInstance(Object object) {
this.wrappedObject = object;
this.rootObject = object;
this.typeConverterDelegate = new TypeConverterDelegate(this, this.wrappedObject);
setIntrospectionClass(object.getClass());
}
@@ -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.
@@ -24,6 +24,7 @@ package org.springframework.beans;
* spouse property of the target object has a null value.
*
* @author Rod Johnson
* @author Juergen Hoeller
*/
@SuppressWarnings("serial")
public class NullValueInNestedPathException extends InvalidPropertyException {
@@ -47,4 +48,16 @@ public class NullValueInNestedPathException extends InvalidPropertyException {
super(beanClass, propertyName, msg);
}
/**
* Create a new NullValueInNestedPathException.
* @param beanClass the offending bean class
* @param propertyName the offending property
* @param msg the detail message
* @param cause the root cause
* @since 4.3.2
*/
public NullValueInNestedPathException(Class<?> beanClass, String propertyName, String msg, Throwable cause) {
super(beanClass, propertyName, msg, cause);
}
}
@@ -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.
@@ -120,7 +120,7 @@ public interface PropertyAccessor {
* @throws InvalidPropertyException if there is no such property or
* if the property isn't writable
* @throws PropertyAccessException if the property was valid but the
* accessor method failed or a type mismatch occured
* accessor method failed or a type mismatch occurred
*/
void setPropertyValue(String propertyName, Object value) throws BeansException;
@@ -130,7 +130,7 @@ public interface PropertyAccessor {
* @throws InvalidPropertyException if there is no such property or
* if the property isn't writable
* @throws PropertyAccessException if the property was valid but the
* accessor method failed or a type mismatch occured
* accessor method failed or a type mismatch occurred
*/
void setPropertyValue(PropertyValue pv) throws BeansException;
@@ -144,7 +144,7 @@ public interface PropertyAccessor {
* @throws InvalidPropertyException if there is no such property or
* if the property isn't writable
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
* occured for specific properties during the batch update. This exception bundles
* occurred for specific properties during the batch update. This exception bundles
* all individual PropertyAccessExceptions. All other properties will have been
* successfully updated.
*/
@@ -164,7 +164,7 @@ public interface PropertyAccessor {
* @throws InvalidPropertyException if there is no such property or
* if the property isn't writable
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
* occured for specific properties during the batch update. This exception bundles
* occurred for specific properties during the batch update. This exception bundles
* all individual PropertyAccessExceptions. All other properties will have been
* successfully updated.
* @see #setPropertyValues(PropertyValues, boolean, boolean)
@@ -185,7 +185,7 @@ public interface PropertyAccessor {
* @throws InvalidPropertyException if there is no such property or
* if the property isn't writable
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
* occured for specific properties during the batch update. This exception bundles
* occurred for specific properties during the batch update. This exception bundles
* all individual PropertyAccessExceptions. All other properties will have been
* successfully updated.
* @see #setPropertyValues(PropertyValues, boolean, boolean)
@@ -208,7 +208,7 @@ public interface PropertyAccessor {
* @throws InvalidPropertyException if there is no such property or
* if the property isn't writable
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
* occured for specific properties during the batch update. This exception bundles
* occurred for specific properties during the batch update. This exception bundles
* all individual PropertyAccessExceptions. All other properties will have been
* successfully updated.
*/
@@ -59,6 +59,7 @@ import org.springframework.beans.propertyeditors.FileEditor;
import org.springframework.beans.propertyeditors.InputSourceEditor;
import org.springframework.beans.propertyeditors.InputStreamEditor;
import org.springframework.beans.propertyeditors.LocaleEditor;
import org.springframework.beans.propertyeditors.PathEditor;
import org.springframework.beans.propertyeditors.PatternEditor;
import org.springframework.beans.propertyeditors.PropertiesEditor;
import org.springframework.beans.propertyeditors.ReaderEditor;
@@ -87,11 +88,21 @@ import org.springframework.util.ClassUtils;
*/
public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
private static Class<?> pathClass;
private static Class<?> zoneIdClass;
static {
ClassLoader cl = PropertyEditorRegistrySupport.class.getClassLoader();
try {
zoneIdClass = ClassUtils.forName("java.time.ZoneId", PropertyEditorRegistrySupport.class.getClassLoader());
pathClass = ClassUtils.forName("java.nio.file.Path", cl);
}
catch (ClassNotFoundException ex) {
// Java 7 Path class not available
pathClass = null;
}
try {
zoneIdClass = ClassUtils.forName("java.time.ZoneId", cl);
}
catch (ClassNotFoundException ex) {
// Java 8 ZoneId class not available
@@ -211,6 +222,9 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
this.defaultEditors.put(InputStream.class, new InputStreamEditor());
this.defaultEditors.put(InputSource.class, new InputSourceEditor());
this.defaultEditors.put(Locale.class, new LocaleEditor());
if (pathClass != null) {
this.defaultEditors.put(pathClass, new PathEditor());
}
this.defaultEditors.put(Pattern.class, new PatternEditor());
this.defaultEditors.put(Properties.class, new PropertiesEditor());
this.defaultEditors.put(Reader.class, new ReaderEditor());
@@ -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.
@@ -45,8 +45,6 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
private final Object value;
private Object source;
private boolean optional = false;
private boolean converted = false;
@@ -78,12 +76,12 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
Assert.notNull(original, "Original must not be null");
this.name = original.getName();
this.value = original.getValue();
this.source = original.getSource();
this.optional = original.isOptional();
this.converted = original.converted;
this.convertedValue = original.convertedValue;
this.conversionNecessary = original.conversionNecessary;
this.resolvedTokens = original.resolvedTokens;
setSource(original.getSource());
copyAttributesFrom(original);
}
@@ -97,10 +95,10 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
Assert.notNull(original, "Original must not be null");
this.name = original.getName();
this.value = newValue;
this.source = original;
this.optional = original.isOptional();
this.conversionNecessary = original.conversionNecessary;
this.resolvedTokens = original.resolvedTokens;
setSource(original);
copyAttributesFrom(original);
}
@@ -129,16 +127,28 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
*/
public PropertyValue getOriginalPropertyValue() {
PropertyValue original = this;
while (original.source instanceof PropertyValue && original.source != original) {
original = (PropertyValue) original.source;
Object source = getSource();
while (source instanceof PropertyValue && source != original) {
original = (PropertyValue) source;
source = original.getSource();
}
return original;
}
/**
* Set whether this is an optional value, that is, to be ignored
* when no corresponding property exists on the target class.
* @since 3.0
*/
public void setOptional(boolean optional) {
this.optional = optional;
}
/**
* Return whether this is an optional value, that is, to be ignored
* when no corresponding property exists on the target class.
* @since 3.0
*/
public boolean isOptional() {
return this.optional;
}
@@ -180,7 +190,7 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
PropertyValue otherPv = (PropertyValue) other;
return (this.name.equals(otherPv.name) &&
ObjectUtils.nullSafeEquals(this.value, otherPv.value) &&
ObjectUtils.nullSafeEquals(this.source, otherPv.source));
ObjectUtils.nullSafeEquals(getSource(), otherPv.getSource()));
}
@Override
@@ -269,7 +269,7 @@ class TypeConverterDelegate {
}
else {
// convertedValue == null
if (javaUtilOptionalEmpty != null && requiredType.equals(javaUtilOptionalEmpty.getClass())) {
if (javaUtilOptionalEmpty != null && requiredType == javaUtilOptionalEmpty.getClass()) {
convertedValue = javaUtilOptionalEmpty;
}
}
@@ -290,15 +290,15 @@ class TypeConverterDelegate {
// Definitely doesn't match: throw IllegalArgumentException/IllegalStateException
StringBuilder msg = new StringBuilder();
msg.append("Cannot convert value of type [").append(ClassUtils.getDescriptiveType(newValue));
msg.append("] to required type [").append(ClassUtils.getQualifiedName(requiredType)).append("]");
msg.append("Cannot convert value of type '").append(ClassUtils.getDescriptiveType(newValue));
msg.append("' to required type '").append(ClassUtils.getQualifiedName(requiredType)).append("'");
if (propertyName != null) {
msg.append(" for property '").append(propertyName).append("'");
}
if (editor != null) {
msg.append(": PropertyEditor [").append(editor.getClass().getName()).append(
"] returned inappropriate value of type [").append(
ClassUtils.getDescriptiveType(convertedValue)).append("]");
"] returned inappropriate value of type '").append(
ClassUtils.getDescriptiveType(convertedValue)).append("'");
throw new IllegalArgumentException(msg.toString());
}
else {
@@ -73,7 +73,7 @@ public abstract class TypeConverterSupport extends PropertyEditorRegistrySupport
catch (IllegalStateException ex) {
throw new ConversionNotSupportedException(value, requiredType, ex);
}
catch (Throwable ex) {
catch (IllegalArgumentException ex) {
throw new TypeMismatchException(value, requiredType, 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.
@@ -57,10 +57,10 @@ public class TypeMismatchException extends PropertyAccessException {
*/
public TypeMismatchException(PropertyChangeEvent propertyChangeEvent, Class<?> requiredType, Throwable cause) {
super(propertyChangeEvent,
"Failed to convert property value of type [" +
ClassUtils.getDescriptiveType(propertyChangeEvent.getNewValue()) + "]" +
"Failed to convert property value of type '" +
ClassUtils.getDescriptiveType(propertyChangeEvent.getNewValue()) + "'" +
(requiredType != null ?
" to required type [" + ClassUtils.getQualifiedName(requiredType) + "]" : "") +
" to required type '" + ClassUtils.getQualifiedName(requiredType) + "'" : "") +
(propertyChangeEvent.getPropertyName() != null ?
" for property '" + propertyChangeEvent.getPropertyName() + "'" : ""),
cause);
@@ -84,8 +84,8 @@ public class TypeMismatchException extends PropertyAccessException {
* @param cause the root cause (may be {@code null})
*/
public TypeMismatchException(Object value, Class<?> requiredType, Throwable cause) {
super("Failed to convert value of type [" + ClassUtils.getDescriptiveType(value) + "]" +
(requiredType != null ? " to required type [" + ClassUtils.getQualifiedName(requiredType) + "]" : ""),
super("Failed to convert value of type '" + ClassUtils.getDescriptiveType(value) + "'" +
(requiredType != null ? " to required type '" + ClassUtils.getQualifiedName(requiredType) + "'" : ""),
cause);
this.value = value;
this.requiredType = requiredType;
@@ -123,7 +123,7 @@ public class BeanCreationException extends FatalBeanException {
/**
* Add a related cause to this bean creation exception,
* not being a direct cause of the failure but having occured
* not being a direct cause of the failure but having occurred
* earlier in the creation of the same bean instance.
* @param ex the related cause to add
*/
@@ -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.
@@ -63,28 +63,35 @@ import org.springframework.core.ResolvableType;
* are supposed to override beans of the same name in any parent factory.
*
* <p>Bean factory implementations should support the standard bean lifecycle interfaces
* as far as possible. The full set of initialization methods and their standard order is:<br>
* 1. BeanNameAware's {@code setBeanName}<br>
* 2. BeanClassLoaderAware's {@code setBeanClassLoader}<br>
* 3. BeanFactoryAware's {@code setBeanFactory}<br>
* 4. ResourceLoaderAware's {@code setResourceLoader}
* (only applicable when running in an application context)<br>
* 5. ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
* (only applicable when running in an application context)<br>
* 6. MessageSourceAware's {@code setMessageSource}
* (only applicable when running in an application context)<br>
* 7. ApplicationContextAware's {@code setApplicationContext}
* (only applicable when running in an application context)<br>
* 8. ServletContextAware's {@code setServletContext}
* (only applicable when running in a web application context)<br>
* 9. {@code postProcessBeforeInitialization} methods of BeanPostProcessors<br>
* 10. InitializingBean's {@code afterPropertiesSet}<br>
* 11. a custom init-method definition<br>
* 12. {@code postProcessAfterInitialization} methods of BeanPostProcessors
* as far as possible. The full set of initialization methods and their standard order is:
* <ol>
* <li>BeanNameAware's {@code setBeanName}
* <li>BeanClassLoaderAware's {@code setBeanClassLoader}
* <li>BeanFactoryAware's {@code setBeanFactory}
* <li>EnvironmentAware's {@code setEnvironment}
* <li>EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
* <li>ResourceLoaderAware's {@code setResourceLoader}
* (only applicable when running in an application context)
* <li>ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
* (only applicable when running in an application context)
* <li>MessageSourceAware's {@code setMessageSource}
* (only applicable when running in an application context)
* <li>ApplicationContextAware's {@code setApplicationContext}
* (only applicable when running in an application context)
* <li>ServletContextAware's {@code setServletContext}
* (only applicable when running in a web application context)
* <li>{@code postProcessBeforeInitialization} methods of BeanPostProcessors
* <li>InitializingBean's {@code afterPropertiesSet}
* <li>a custom init-method definition
* <li>{@code postProcessAfterInitialization} methods of BeanPostProcessors
* </ol>
*
* <p>On shutdown of a bean factory, the following lifecycle methods apply:<br>
* 1. DisposableBean's {@code destroy}<br>
* 2. a custom destroy-method definition
* <p>On shutdown of a bean factory, the following lifecycle methods apply:
* <ol>
* <li>{@code postProcessBeforeDestruction} methods of DestructionAwareBeanPostProcessors
* <li>DisposableBean's {@code destroy}
* <li>a custom destroy-method definition
* </ol>
*
* @author Rod Johnson
* @author Juergen Hoeller
@@ -153,12 +160,12 @@ public interface BeanFactory {
/**
* Return the bean instance that uniquely matches the given object type, if any.
* @param requiredType type the bean must match; can be an interface or superclass.
* {@code null} is disallowed.
* <p>This method goes into {@link ListableBeanFactory} by-type lookup territory
* but may also be translated into a conventional by-name lookup based on the name
* of the given type. For more extensive retrieval operations across sets of beans,
* use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}.
* @param requiredType type the bean must match; can be an interface or superclass.
* {@code null} is disallowed.
* @return an instance of the single bean matching the required type
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
@@ -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.
@@ -17,6 +17,7 @@
package org.springframework.beans.factory;
import org.springframework.beans.BeansException;
import org.springframework.util.ClassUtils;
/**
* Thrown when a bean doesn't match the expected type.
@@ -45,8 +46,8 @@ public class BeanNotOfRequiredTypeException extends BeansException {
* the expected type
*/
public BeanNotOfRequiredTypeException(String beanName, Class<?> requiredType, Class<?> actualType) {
super("Bean named '" + beanName + "' must be of type [" + requiredType.getName() +
"], but was actually of type [" + actualType.getName() + "]");
super("Bean named '" + beanName + "' is expected to be of type '" + ClassUtils.getQualifiedName(requiredType) +
"' but was actually of type '" + ClassUtils.getQualifiedName(actualType) + "'");
this.beanName = beanName;
this.requiredType = requiredType;
this.actualType = actualType;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 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,10 +17,10 @@
package org.springframework.beans.factory;
/**
* Counterpart of BeanNameAware. Returns the bean name of an object.
* Counterpart of {@link BeanNameAware}. Returns the bean name of an object.
*
* <p>This interface can be introduced to avoid a brittle dependence
* on bean name in objects used with Spring IoC and Spring AOP.
* <p>This interface can be introduced to avoid a brittle dependence on
* bean name in objects used with Spring IoC and Spring AOP.
*
* @author Rod Johnson
* @since 2.0
@@ -29,7 +29,7 @@ package org.springframework.beans.factory;
public interface NamedBean {
/**
* Return the name of this bean in a Spring bean factory.
* Return the name of this bean in a Spring bean factory, if known.
*/
String getBeanName();
@@ -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.
@@ -17,6 +17,8 @@
package org.springframework.beans.factory;
import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
@@ -26,6 +28,7 @@ import org.springframework.util.StringUtils;
*
* @author Rod Johnson
* @author Juergen Hoeller
* @author Stephane Nicoll
* @see BeanFactory#getBean(String)
* @see BeanFactory#getBean(Class)
* @see NoUniqueBeanDefinitionException
@@ -33,11 +36,9 @@ import org.springframework.util.StringUtils;
@SuppressWarnings("serial")
public class NoSuchBeanDefinitionException extends BeansException {
/** Name of the missing bean */
private String beanName;
/** Required type of the missing bean */
private Class<?> beanType;
private ResolvableType resolvableType;
/**
@@ -45,7 +46,7 @@ public class NoSuchBeanDefinitionException extends BeansException {
* @param name the name of the missing bean
*/
public NoSuchBeanDefinitionException(String name) {
super("No bean named '" + name + "' is defined");
super("No bean named '" + name + "' available");
this.beanName = name;
}
@@ -55,7 +56,7 @@ public class NoSuchBeanDefinitionException extends BeansException {
* @param message detailed message describing the problem
*/
public NoSuchBeanDefinitionException(String name, String message) {
super("No bean named '" + name + "' is defined: " + message);
super("No bean named '" + name + "' available: " + message);
this.beanName = name;
}
@@ -64,8 +65,7 @@ public class NoSuchBeanDefinitionException extends BeansException {
* @param type required type of the missing bean
*/
public NoSuchBeanDefinitionException(Class<?> type) {
super("No qualifying bean of type [" + type.getName() + "] is defined");
this.beanType = type;
this(ResolvableType.forClass(type));
}
/**
@@ -74,8 +74,28 @@ public class NoSuchBeanDefinitionException extends BeansException {
* @param message detailed message describing the problem
*/
public NoSuchBeanDefinitionException(Class<?> type, String message) {
super("No qualifying bean of type [" + type.getName() + "] is defined: " + message);
this.beanType = type;
this(ResolvableType.forClass(type), message);
}
/**
* Create a new {@code NoSuchBeanDefinitionException}.
* @param type full type declaration of the missing bean
* @since 4.3.4
*/
public NoSuchBeanDefinitionException(ResolvableType type) {
super("No qualifying bean of type '" + type + "' available");
this.resolvableType = type;
}
/**
* Create a new {@code NoSuchBeanDefinitionException}.
* @param type full type declaration of the missing bean
* @param message detailed message describing the problem
* @since 4.3.4
*/
public NoSuchBeanDefinitionException(ResolvableType type, String message) {
super("No qualifying bean of type '" + type + "' available: " + message);
this.resolvableType = type;
}
/**
@@ -83,12 +103,15 @@ public class NoSuchBeanDefinitionException extends BeansException {
* @param type required type of the missing bean
* @param dependencyDescription a description of the originating dependency
* @param message detailed message describing the problem
* @deprecated as of 4.3.4, in favor of {@link #NoSuchBeanDefinitionException(ResolvableType, String)}
*/
@Deprecated
public NoSuchBeanDefinitionException(Class<?> type, String dependencyDescription, String message) {
super("No qualifying bean of type [" + type.getName() + "] found for dependency" +
super("No qualifying bean" + (!StringUtils.hasLength(dependencyDescription) ?
" of type '" + ClassUtils.getQualifiedName(type) + "'" : "") + " found for dependency" +
(StringUtils.hasLength(dependencyDescription) ? " [" + dependencyDescription + "]" : "") +
": " + message);
this.beanType = type;
this.resolvableType = ResolvableType.forClass(type);
}
@@ -100,10 +123,20 @@ public class NoSuchBeanDefinitionException extends BeansException {
}
/**
* Return the required type of the missing bean, if it was a lookup <em>by type</em> that failed.
* Return the required type of the missing bean, if it was a lookup <em>by type</em>
* that failed.
*/
public Class<?> getBeanType() {
return this.beanType;
return (this.resolvableType != null ? this.resolvableType.getRawClass() : null);
}
/**
* Return the required {@link ResolvableType} of the missing bean, if it was a lookup
* <em>by type</em> that failed.
* @since 4.3.4
*/
public ResolvableType getResolvableType() {
return this.resolvableType;
}
/**
@@ -18,6 +18,7 @@ package org.springframework.beans.factory;
import org.springframework.beans.BeansException;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* Exception thrown when a bean depends on other beans or simple properties
@@ -46,7 +47,7 @@ public class UnsatisfiedDependencyException extends BeanCreationException {
super(resourceDescription, beanName,
"Unsatisfied dependency expressed through bean property '" + propertyName + "'" +
(msg != null ? ": " + msg : ""));
(StringUtils.hasLength(msg) ? ": " + msg : ""));
}
/**
@@ -59,7 +60,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, "");
initCause(ex);
}
@@ -74,7 +75,9 @@ public class UnsatisfiedDependencyException extends BeanCreationException {
public UnsatisfiedDependencyException(
String resourceDescription, String beanName, InjectionPoint injectionPoint, String msg) {
super(resourceDescription, beanName, "Unsatisfied dependency expressed through " + injectionPoint + ": " + msg);
super(resourceDescription, beanName,
"Unsatisfied dependency expressed through " + injectionPoint +
(StringUtils.hasLength(msg) ? ": " + msg : ""));
this.injectionPoint = injectionPoint;
}
@@ -89,7 +92,7 @@ public class UnsatisfiedDependencyException extends BeanCreationException {
public UnsatisfiedDependencyException(
String resourceDescription, String beanName, InjectionPoint injectionPoint, BeansException ex) {
this(resourceDescription, beanName, injectionPoint, (ex != null ? ex.getMessage() : ""));
this(resourceDescription, beanName, injectionPoint, "");
initCause(ex);
}
@@ -220,7 +220,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
public void setBeanFactory(BeanFactory beanFactory) {
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
throw new IllegalArgumentException(
"AutowiredAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory");
@@ -238,35 +238,56 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
}
@Override
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName) throws BeansException {
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
// Let's check for lookup methods here..
if (!this.lookupMethodsChecked.contains(beanName)) {
ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() {
@Override
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
Lookup lookup = method.getAnnotation(Lookup.class);
if (lookup != null) {
LookupOverride override = new LookupOverride(method, lookup.value());
try {
RootBeanDefinition mbd = (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName);
mbd.getMethodOverrides().addOverride(override);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(beanName,
"Cannot apply @Lookup to beans without corresponding bean definition");
try {
ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() {
@Override
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
Lookup lookup = method.getAnnotation(Lookup.class);
if (lookup != null) {
LookupOverride override = new LookupOverride(method, lookup.value());
try {
RootBeanDefinition mbd = (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName);
mbd.getMethodOverrides().addOverride(override);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(beanName,
"Cannot apply @Lookup to beans without corresponding bean definition");
}
}
}
}
});
});
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
}
catch (NoClassDefFoundError err) {
throw new BeanCreationException(beanName, "Failed to introspect bean class [" + beanClass.getName() +
"] for lookup method metadata: could not find class that it depends on", err);
}
this.lookupMethodsChecked.add(beanName);
}
// Quick check on the concurrent map first, with minimal locking.
Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
if (candidateConstructors == null) {
// Fully synchronized resolution now...
synchronized (this.candidateConstructorsCache) {
candidateConstructors = this.candidateConstructorsCache.get(beanClass);
if (candidateConstructors == null) {
Constructor<?>[] rawCandidates = beanClass.getDeclaredConstructors();
Constructor<?>[] rawCandidates;
try {
rawCandidates = beanClass.getDeclaredConstructors();
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
List<Constructor<?>> candidates = new ArrayList<Constructor<?>>(rawCandidates.length);
Constructor<?> requiredConstructor = null;
Constructor<?> defaultConstructor = null;
@@ -320,9 +341,9 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
}
else if (candidates.size() == 1 && logger.isWarnEnabled()) {
logger.warn("Inconsistent constructor declaration on bean with name '" + beanName +
"': single autowire-marked constructor flagged as optional - this constructor " +
"is effectively required since there is no default constructor to fall back to: " +
candidates.get(0));
"': single autowire-marked constructor flagged as optional - " +
"this constructor is effectively required since there is no " +
"default constructor to fall back to: " + candidates.get(0));
}
}
candidateConstructors = candidates.toArray(new Constructor<?>[candidates.size()]);
@@ -342,7 +363,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
@@ -361,9 +382,9 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
* 'Native' processing method for direct calls with an arbitrary target instance,
* resolving all of its fields and methods which are annotated with {@code @Autowired}.
* @param bean the target instance to process
* @throws BeansException if autowiring failed
* @throws BeanCreationException if autowiring failed
*/
public void processInjection(Object bean) throws BeansException {
public void processInjection(Object bean) throws BeanCreationException {
Class<?> clazz = bean.getClass();
InjectionMetadata metadata = findAutowiringMetadata(clazz.getName(), clazz, null);
try {
@@ -373,7 +394,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException("Injection of autowired dependencies failed for class [" + clazz + "]", ex);
throw new BeanCreationException(
"Injection of autowired dependencies failed for class [" + clazz + "]", ex);
}
}
@@ -446,7 +468,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
}
if (method.getParameterTypes().length == 0) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation should be used on methods with parameters: " + method);
logger.warn("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
boolean required = determineRequiredStatus(ann);
@@ -577,7 +600,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName)) {
if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName);
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
@@ -628,7 +652,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
Class<?>[] paramTypes = method.getParameterTypes();
arguments = new Object[paramTypes.length];
DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
Set<String> autowiredBeanNames = new LinkedHashSet<String>(paramTypes.length);
Set<String> autowiredBeans = new LinkedHashSet<String>(paramTypes.length);
TypeConverter typeConverter = beanFactory.getTypeConverter();
for (int i = 0; i < arguments.length; i++) {
MethodParameter methodParam = new MethodParameter(method, i);
@@ -636,7 +660,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
currDesc.setContainingClass(bean.getClass());
descriptors[i] = currDesc;
try {
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeanNames, typeConverter);
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
if (arg == null && !this.required) {
arguments = null;
break;
@@ -654,15 +678,15 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
for (int i = 0; i < arguments.length; i++) {
this.cachedMethodArguments[i] = descriptors[i];
}
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == paramTypes.length) {
Iterator<String> it = autowiredBeanNames.iterator();
registerDependentBeans(beanName, autowiredBeans);
if (autowiredBeans.size() == paramTypes.length) {
Iterator<String> it = autowiredBeans.iterator();
for (int i = 0; i < paramTypes.length; i++) {
String autowiredBeanName = it.next();
if (beanFactory.containsBean(autowiredBeanName)) {
if (beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
this.cachedMethodArguments[i] =
new ShortcutDependencyDescriptor(descriptors[i], autowiredBeanName);
this.cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
descriptors[i], autowiredBeanName, paramTypes[i]);
}
}
}
@@ -705,16 +729,19 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
@SuppressWarnings("serial")
private static class ShortcutDependencyDescriptor extends DependencyDescriptor {
private final String shortcutBeanName;
private final String shortcut;
public ShortcutDependencyDescriptor(DependencyDescriptor original, String shortcutBeanName) {
private final Class<?> requiredType;
public ShortcutDependencyDescriptor(DependencyDescriptor original, String shortcut, Class<?> requiredType) {
super(original);
this.shortcutBeanName = shortcutBeanName;
this.shortcut = shortcut;
this.requiredType = requiredType;
}
@Override
public Object resolveShortcut(BeanFactory beanFactory) {
return resolveCandidate(this.shortcutBeanName, beanFactory);
return resolveCandidate(this.shortcut, this.requiredType, beanFactory);
}
}
@@ -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,27 +18,30 @@ package org.springframework.beans.factory.annotation;
import java.lang.reflect.Method;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* Convenience methods performing bean lookups related to annotations, for example
* Spring's {@link Qualifier @Qualifier} annotation.
*
* @author Chris Beams
* @author Juergen Hoeller
* @author Chris Beams
* @since 3.1.2
* @see BeanFactoryUtils
*/
public class BeanFactoryAnnotationUtils {
public abstract class BeanFactoryAnnotationUtils {
/**
* Obtain a bean of type {@code T} from the given {@code BeanFactory} declaring a
@@ -48,9 +51,16 @@ public class BeanFactoryAnnotationUtils {
* @param beanType the type of bean to retrieve
* @param qualifier the qualifier for selecting between multiple bean matches
* @return the matching bean of type {@code T} (never {@code null})
* @throws NoUniqueBeanDefinitionException if multiple matching beans of type {@code T} found
* @throws NoSuchBeanDefinitionException if no matching bean of type {@code T} found
* @throws BeansException if the bean could not be created
* @see BeanFactory#getBean(Class)
*/
public static <T> T qualifiedBeanOfType(BeanFactory beanFactory, Class<T> beanType, String qualifier) {
public static <T> T qualifiedBeanOfType(BeanFactory beanFactory, Class<T> beanType, String qualifier)
throws BeansException {
Assert.notNull(beanFactory, "BeanFactory must not be null");
if (beanFactory instanceof ConfigurableListableBeanFactory) {
// Full qualifier matching supported.
return qualifiedBeanOfType((ConfigurableListableBeanFactory) beanFactory, beanType, qualifier);
@@ -74,7 +84,6 @@ public class BeanFactoryAnnotationUtils {
* @param beanType the type of bean to retrieve
* @param qualifier the qualifier for selecting between multiple bean matches
* @return the matching bean of type {@code T} (never {@code null})
* @throws NoSuchBeanDefinitionException if no matching bean of type {@code T} found
*/
private static <T> T qualifiedBeanOfType(ConfigurableListableBeanFactory bf, Class<T> beanType, String qualifier) {
String[] candidateBeans = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(bf, beanType);
@@ -82,8 +91,7 @@ public class BeanFactoryAnnotationUtils {
for (String beanName : candidateBeans) {
if (isQualifierMatch(qualifier, beanName, bf)) {
if (matchingBean != null) {
throw new NoSuchBeanDefinitionException(qualifier, "No unique " + beanType.getSimpleName() +
" bean found for qualifier '" + qualifier + "'");
throw new NoUniqueBeanDefinitionException(beanType, matchingBean, beanName);
}
matchingBean = beanName;
}
@@ -40,6 +40,7 @@ import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcess
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
/**
@@ -349,7 +350,7 @@ public class InitDestroyAnnotationBeanPostProcessor
}
this.method = method;
this.identifier = (Modifier.isPrivate(method.getModifiers()) ?
method.getDeclaringClass() + "." + method.getName() : method.getName());
ClassUtils.getQualifiedMethodName(method) : method.getName());
}
public Method getMethod() {
@@ -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,6 +17,7 @@
package org.springframework.beans.factory.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.LinkedHashSet;
import java.util.Map;
@@ -49,6 +50,7 @@ import org.springframework.util.StringUtils;
*
* @author Mark Fisher
* @author Juergen Hoeller
* @author Stephane Nicoll
* @since 2.5
* @see AutowireCandidateQualifier
* @see Qualifier
@@ -225,8 +227,12 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
qualifier = bd.getQualifier(ClassUtils.getShortName(type));
}
if (qualifier == null) {
// First, check annotation on factory method, if applicable
Annotation targetAnnotation = getFactoryMethodAnnotation(bd, type);
// First, check annotation on qualified element, if any
Annotation targetAnnotation = getQualifiedElementAnnotation(bd, type);
// Then, check annotation on factory method, if applicable
if (targetAnnotation == null) {
targetAnnotation = getFactoryMethodAnnotation(bd, type);
}
if (targetAnnotation == null) {
RootBeanDefinition dbd = getResolvedDecoratedDefinition(bd);
if (dbd != null) {
@@ -291,6 +297,11 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
return true;
}
protected Annotation getQualifiedElementAnnotation(RootBeanDefinition bd, Class<? extends Annotation> type) {
AnnotatedElement qualifiedElement = bd.getQualifiedElement();
return (qualifiedElement != null ? AnnotationUtils.getAnnotation(qualifiedElement, type) : null);
}
protected Annotation getFactoryMethodAnnotation(RootBeanDefinition bd, Class<? extends Annotation> type) {
Method resolvedFactoryMethod = bd.getResolvedFactoryMethod();
return (resolvedFactoryMethod != null ? AnnotationUtils.getAnnotation(resolvedFactoryMethod, type) : null);
@@ -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.
@@ -141,8 +141,7 @@ public class RequiredAnnotationBeanPostProcessor extends InstantiationAwareBeanP
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
throws BeansException {
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
if (!this.validatedBeanNames.contains(beanName)) {
if (!shouldSkip(this.beanFactory, beanName)) {
@@ -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.
@@ -208,7 +208,7 @@ public abstract class AbstractFactoryBean<T>
* <p>Invoked on initialization of this FactoryBean in case of
* a singleton; else, on each {@link #getObject()} call.
* @return the object returned by this factory
* @throws Exception if an exception occured during object creation
* @throws Exception if an exception occurred during object creation
* @see #getObject()
*/
protected abstract T createInstance() throws Exception;
@@ -21,6 +21,8 @@ import java.util.Set;
import org.springframework.beans.BeansException;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
/**
* Extension of the {@link org.springframework.beans.factory.BeanFactory}
@@ -154,15 +156,6 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
*/
Object configureBean(Object existingBean, String beanName) throws BeansException;
/**
* Resolve the specified dependency against the beans defined in this factory.
* @param descriptor the descriptor for the dependency
* @param beanName the name of the bean which declares the present dependency
* @return the resolved object, or {@code null} if none found
* @throws BeansException if dependency resolution failed
*/
Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansException;
//-------------------------------------------------------------------------
// Specialized methods for fine-grained control over the bean lifecycle
@@ -312,18 +305,55 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
*/
void destroyBean(Object existingBean);
//-------------------------------------------------------------------------
// Delegate methods for resolving injection points
//-------------------------------------------------------------------------
/**
* Resolve the bean instance that uniquely matches the given object type, if any,
* including its bean name.
* <p>This is effectively a variant of {@link #getBean(Class)} which preserves the
* bean name of the matching instance.
* @param requiredType type the bean must match; can be an interface or superclass.
* {@code null} is disallowed.
* @return the bean name plus bean instance
* @throws NoSuchBeanDefinitionException if no matching bean was found
* @throws NoUniqueBeanDefinitionException if more than one matching bean was found
* @throws BeansException if the bean could not be created
* @since 4.3.3
* @see #getBean(Class)
*/
<T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException;
/**
* Resolve the specified dependency against the beans defined in this factory.
* @param descriptor the descriptor for the dependency
* @param beanName the name of the bean which declares the present dependency
* @param autowiredBeanNames a Set that all names of autowired beans (used for
* resolving the present dependency) are supposed to be added to
* @param typeConverter the TypeConverter to use for populating arrays and
* collections
* @param descriptor the descriptor for the dependency (field/method/constructor)
* @param requestingBeanName the name of the bean which declares the given dependency
* @return the resolved object, or {@code null} if none found
* @throws BeansException if dependency resolution failed
* @throws NoSuchBeanDefinitionException if no matching bean was found
* @throws NoUniqueBeanDefinitionException if more than one matching bean was found
* @throws BeansException if dependency resolution failed for any other reason
* @since 2.5
* @see #resolveDependency(DependencyDescriptor, String, Set, TypeConverter)
*/
Object resolveDependency(DependencyDescriptor descriptor, String beanName,
Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName) throws BeansException;
/**
* Resolve the specified dependency against the beans defined in this factory.
* @param descriptor the descriptor for the dependency (field/method/constructor)
* @param requestingBeanName the name of the bean which declares the given dependency
* @param autowiredBeanNames a Set that all names of autowired beans (used for
* resolving the given dependency) are supposed to be added to
* @param typeConverter the TypeConverter to use for populating arrays and collections
* @return the resolved object, or {@code null} if none found
* @throws NoSuchBeanDefinitionException if no matching bean was found
* @throws NoUniqueBeanDefinitionException if more than one matching bean was found
* @throws BeansException if dependency resolution failed for any other reason
* @since 2.5
* @see DependencyDescriptor
*/
Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException;
}
@@ -172,21 +172,6 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
}
/**
* Resolve the specified bean name, as a candidate result of the matching
* algorithm for this dependency, to a bean instance from the given factory.
* <p>The default implementation calls {@link BeanFactory#getBean(String)}.
* Subclasses may provide additional arguments or other customizations.
* @param beanName the bean name, as a candidate result for this dependency
* @param beanFactory the associated factory
* @return the bean instance (never {@code null})
* @since 4.3
* @see BeanFactory#getBean(String)
*/
public Object resolveCandidate(String beanName, BeanFactory beanFactory) {
return beanFactory.getBean(beanName);
}
/**
* Resolve a shortcut for this dependency against the given factory, for example
* taking some pre-resolved information into account.
@@ -196,12 +181,32 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
* pre-cached information while still receiving {@link InjectionPoint} exposure etc.
* @param beanFactory the associated factory
* @return the shortcut result if any, or {@code null} if none
* @throws BeansException if the shortcut could not be obtained
* @since 4.3.1
*/
public Object resolveShortcut(BeanFactory beanFactory) {
public Object resolveShortcut(BeanFactory beanFactory) throws BeansException {
return null;
}
/**
* Resolve the specified bean name, as a candidate result of the matching
* algorithm for this dependency, to a bean instance from the given factory.
* <p>The default implementation calls {@link BeanFactory#getBean(String)}.
* Subclasses may provide additional arguments or other customizations.
* @param beanName the bean name, as a candidate result for this dependency
* @param requiredType the expected type of the bean (as an assertion)
* @param beanFactory the associated factory
* @return the bean instance (never {@code null})
* @throws BeansException if the bean could not be obtained
* @since 4.3.2
* @see BeanFactory#getBean(String)
*/
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
throws BeansException {
return beanFactory.getBean(beanName, requiredType);
}
/**
* Increase this descriptor's nesting level.
@@ -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.
@@ -103,7 +103,6 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
* @see org.springframework.beans.MutablePropertyValues
*/
PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
throws BeansException;
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
}
@@ -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.
@@ -66,8 +66,7 @@ public abstract class InstantiationAwareBeanPostProcessorAdapter implements Smar
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
throws BeansException {
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
@@ -0,0 +1,63 @@
/*
* 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.beans.factory.config;
import org.springframework.beans.factory.NamedBean;
import org.springframework.util.Assert;
/**
* A simple holder for a given bean name plus bean instance.
*
* @author Juergen Hoeller
* @since 4.3.3
* @see AutowireCapableBeanFactory#resolveNamedBean(Class)
*/
public class NamedBeanHolder<T> implements NamedBean {
private final String beanName;
private final T beanInstance;
/**
* Create a new holder for the given bean name plus instance.
* @param beanName the name of the bean
* @param beanInstance the corresponding bean instance
*/
public NamedBeanHolder(String beanName, T beanInstance) {
Assert.notNull(beanName, "Bean name must not be null");
this.beanName = beanName;
this.beanInstance = beanInstance;
}
/**
* Return the name of the bean (never {@code null}).
*/
@Override
public String getBeanName() {
return this.beanName;
}
/**
* Return the corresponding bean instance (can be {@code null}).
*/
public T getBeanInstance() {
return this.beanInstance;
}
}
@@ -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.
@@ -95,7 +95,7 @@ public class PropertiesFactoryBean extends PropertiesLoaderSupport
* <p>Invoked on initialization of this FactoryBean in case of a
* shared singleton; else, on each {@link #getObject()} call.
* @return the object returned by this factory
* @throws IOException if an exception occured during properties loading
* @throws IOException if an exception occurred during properties loading
* @see #mergeProperties()
*/
protected Properties createProperties() throws IOException {
@@ -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.
@@ -68,6 +68,7 @@ public interface Scope {
* @param objectFactory the {@link ObjectFactory} to use to create the scoped
* object if it is not present in the underlying storage mechanism
* @return the desired object (never {@code null})
* @throws IllegalStateException if the underlying scope is not currently active
*/
Object get(String name, ObjectFactory<?> objectFactory);
@@ -84,6 +85,7 @@ public interface Scope {
* removing an object.
* @param name the name of the object to remove
* @return the removed object, or {@code null} if no object was present
* @throws IllegalStateException if the underlying scope is not currently active
* @see #registerDestructionCallback
*/
Object remove(String name);
@@ -112,6 +114,7 @@ public interface Scope {
* so it can safely be executed without an enclosing try-catch block.
* Furthermore, the Runnable will usually be serializable, provided
* that its target object is serializable as well.
* @throws IllegalStateException if the underlying scope is not currently active
* @see org.springframework.beans.factory.DisposableBean
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#getDestroyMethodName()
* @see DestructionAwareBeanPostProcessor
@@ -123,6 +126,7 @@ public interface Scope {
* E.g. the HttpServletRequest object for key "request".
* @param key the contextual key
* @return the corresponding object, or {@code null} if none found
* @throws IllegalStateException if the underlying scope is not currently active
*/
Object resolveContextualObject(String key);
@@ -139,6 +143,7 @@ public interface Scope {
* underlying storage mechanism has no obvious candidate for such an ID.
* @return the conversation ID, or {@code null} if there is no
* conversation ID for the current scope
* @throws IllegalStateException if the underlying scope is not currently active
*/
String getConversationId();
@@ -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.
@@ -25,12 +25,16 @@ import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
/**
* Factory for a Map that reads from a YAML source. YAML is a nice human-readable
* format for configuration, and it has some useful hierarchical properties. It's
* more or less a superset of JSON, so it has a lot of similar features. If
* multiple resources are provided the later ones will override entries in the
* earlier ones hierarchically - that is all entries with the same nested key of
* type Map at any depth are merged. For example:
* Factory for a {@code Map} that reads from a YAML source, preserving the
* YAML-declared value types and their structure.
*
* <p>YAML is a nice human-readable format for configuration, and it has some
* useful hierarchical properties. It's more or less a superset of JSON, so it
* has a lot of similar features.
*
* <p>If multiple resources are provided the later ones will override entries in
* the earlier ones hierarchically; that is, all entries with the same nested key
* of type {@code Map} at any depth are merged. For example:
*
* <pre class="code">
* foo:
@@ -62,6 +66,7 @@ import org.springframework.beans.factory.InitializingBean;
* with the value in the second, but its nested values are merged.
*
* @author Dave Syer
* @author Juergen Hoeller
* @since 4.1
*/
public class YamlMapFactoryBean extends YamlProcessor implements FactoryBean<Map<String, Object>>, InitializingBean {
@@ -104,10 +109,10 @@ public class YamlMapFactoryBean extends YamlProcessor implements FactoryBean<Map
/**
* Template method that subclasses may override to construct the object
* returned by this factory. The default implementation returns the
* merged Map instance.
* returned by this factory.
* <p>Invoked lazily the first time {@link #getObject()} is invoked in
* case of a shared singleton; else, on each {@link #getObject()} call.
* <p>The default implementation returns the merged {@code Map} instance.
* @return the object returned by this factory
* @see #process(java.util.Map, MatchCallback)
*/
@@ -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.
@@ -37,6 +37,7 @@ import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.parser.ParserException;
import org.yaml.snakeyaml.reader.UnicodeReader;
import org.springframework.core.CollectionFactory;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -45,6 +46,7 @@ import org.springframework.util.StringUtils;
* Base class for YAML factories.
*
* @author Dave Syer
* @author Juergen Hoeller
* @since 4.1
*/
public abstract class YamlProcessor {
@@ -217,7 +219,7 @@ public abstract class YamlProcessor {
}
private boolean process(Map<String, Object> map, MatchCallback callback) {
Properties properties = new Properties();
Properties properties = CollectionFactory.createStringAdaptingProperties();
properties.putAll(getFlattenedMap(map));
if (this.documentMatchers.isEmpty()) {
@@ -278,7 +280,7 @@ public abstract class YamlProcessor {
key = path + key;
}
else {
key = path + "." + key;
key = path + '.' + key;
}
}
Object value = entry.getValue();
@@ -302,21 +304,23 @@ public abstract class YamlProcessor {
}
}
else {
result.put(key, value != null ? value : "");
result.put(key, (value != null ? value : ""));
}
}
}
/**
* Callback interface used to process properties in a resulting map.
* Callback interface used to process the YAML parsing results.
*/
public interface MatchCallback {
/**
* Process the properties.
* @param properties the properties to process
* @param map a mutable result map
* Process the given representation of the parsing results.
* @param properties the properties to process (as a flattened
* representation with indexed keys in case of a collection or map)
* @param map the result map (preserving the original value structure
* in the YAML document)
*/
void process(Properties properties, Map<String, Object> map);
}
@@ -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.
@@ -21,13 +21,23 @@ import java.util.Properties;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.CollectionFactory;
/**
* Factory for Java Properties that reads from a YAML source. YAML is a nice
* human-readable format for configuration, and it has some useful hierarchical
* properties. It's more or less a superset of JSON, so it has a lot of similar
* features. The Properties created by this factory have nested paths for
* hierarchical objects, so for instance this YAML
* Factory for {@link java.util.Properties} that reads from a YAML source,
* exposing a flat structure of String property values.
*
* <p>YAML is a nice human-readable format for configuration, and it has some
* useful hierarchical properties. It's more or less a superset of JSON, so it
* has a lot of similar features.
*
* <p><b>Note: All exposed values are of type {@code String}</b> for access through
* the common {@link Properties#getProperty} method (e.g. in configuration property
* resolution through {@link PropertyResourceConfigurer#setProperties(Properties)}).
* If this is not desirable, use {@link YamlMapFactoryBean} instead.
*
* <p>The Properties created by this factory have nested paths for hierarchical
* objects, so for instance this YAML
*
* <pre class="code">
* environments:
@@ -39,7 +49,7 @@ import org.springframework.beans.factory.InitializingBean;
* name: My Cool App
* </pre>
*
* is transformed into these Properties:
* is transformed into these properties:
*
* <pre class="code">
* environments.dev.url=http://dev.bar.com
@@ -57,7 +67,7 @@ import org.springframework.beans.factory.InitializingBean;
* - foo.bar.com
* </pre>
*
* becomes Java Properties like this:
* becomes properties like this:
*
* <pre class="code">
* servers[0]=dev.bar.com
@@ -66,6 +76,7 @@ import org.springframework.beans.factory.InitializingBean;
*
* @author Dave Syer
* @author Stephane Nicoll
* @author Juergen Hoeller
* @since 4.1
*/
public class YamlPropertiesFactoryBean extends YamlProcessor implements FactoryBean<Properties>, InitializingBean {
@@ -116,7 +127,7 @@ public class YamlPropertiesFactoryBean extends YamlProcessor implements FactoryB
* @see #process(MatchCallback) ()
*/
protected Properties createProperties() {
final Properties result = new Properties();
final Properties result = CollectionFactory.createStringAdaptingProperties();
process(new MatchCallback() {
@Override
public void process(Properties properties, Map<String, Object> map) {
@@ -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.
@@ -325,8 +325,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
}
@Override
public Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansException {
return resolveDependency(descriptor, beanName, null, null);
public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName) throws BeansException {
return resolveDependency(descriptor, requestingBeanName, null, null);
}
@@ -500,7 +500,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
*/
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
@@ -515,7 +517,13 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
@@ -550,7 +558,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
@@ -586,7 +595,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
@@ -624,10 +634,11 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
protected Class<?> determineTargetType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
Class<?> targetType = mbd.getTargetType();
if (targetType == null) {
targetType = (mbd.getFactoryMethodName() != null ? getTypeForFactoryMethod(beanName, mbd, typesToMatch) :
targetType = (mbd.getFactoryMethodName() != null ?
getTypeForFactoryMethod(beanName, mbd, typesToMatch) :
resolveBeanClass(mbd, beanName, typesToMatch));
if (ObjectUtils.isEmpty(typesToMatch) || getTempClassLoader() == null) {
mbd.setTargetType(targetType);
mbd.resolvedTargetType = targetType;
}
}
return targetType;
@@ -772,10 +783,11 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
ReflectionUtils.doWithMethods(fbClass,
new ReflectionUtils.MethodCallback() {
@Override
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
public void doWith(Method method) {
if (method.getName().equals(factoryMethodName) &&
FactoryBean.class.isAssignableFrom(method.getReturnType())) {
objectType.value = GenericTypeResolver.resolveReturnTypeArgument(method, FactoryBean.class);
objectType.value = GenericTypeResolver.resolveReturnTypeArgument(
method, FactoryBean.class);
}
}
});
@@ -802,10 +814,14 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
if (objectType.value != null) {
return objectType.value;
}
else {
// No type found for shortcut FactoryBean instance:
// fall back to full creation of the FactoryBean instance.
return super.getTypeForFactoryBean(beanName, mbd);
}
}
// No type found - fall back to full creation of the FactoryBean instance.
return super.getTypeForFactoryBean(beanName, mbd);
return null;
}
/**
@@ -824,7 +840,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
if (exposedObject == null) {
return exposedObject;
return null;
}
}
}
@@ -922,24 +938,15 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
* @param mbd the merged bean definition for the bean
* @param beanType the actual type of the managed bean instance
* @param beanName the name of the bean
* @throws BeansException if any post-processing failed
* @see MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
*/
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName)
throws BeansException {
try {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
catch (Exception ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing failed of bean type [" + beanType + "] failed", ex);
}
}
/**
@@ -976,12 +983,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
* @param beanClass the class of the bean to be instantiated
* @param beanName the name of the bean
* @return the bean object to use instead of a default instance of the target bean, or {@code null}
* @throws BeansException if any post-processing failed
* @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
*/
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName)
throws BeansException {
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
@@ -1102,7 +1106,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
@@ -1654,7 +1659,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
* methods with arguments.
* @see #invokeInitMethods
*/
protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
String initMethodName = mbd.getInitMethodName();
final Method initMethod = (mbd.isNonPublicAccessAllowed() ?
BeanUtils.findMethod(bean.getClass(), initMethodName) :
@@ -287,13 +287,13 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
if (isDependent(beanName, dependsOnBean)) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dependsOnBean, beanName);
getBean(dependsOnBean);
registerDependentBean(dep, beanName);
getBean(dep);
}
}
@@ -372,8 +372,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type [" +
ClassUtils.getQualifiedName(requiredType) + "]", ex);
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
@@ -460,19 +460,19 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
return false;
}
if (isFactoryBean(beanName, mbd)) {
final FactoryBean<?> factoryBean = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
final FactoryBean<?> fb = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((factoryBean instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factoryBean).isPrototype()) ||
!factoryBean.isSingleton());
return ((fb instanceof SmartFactoryBean && ((SmartFactoryBean<?>) fb).isPrototype()) ||
!fb.isSingleton());
}
}, getAccessControlContext());
}
else {
return ((factoryBean instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factoryBean).isPrototype()) ||
!factoryBean.isSingleton());
return ((fb instanceof SmartFactoryBean && ((SmartFactoryBean<?>) fb).isPrototype()) ||
!fb.isSingleton());
}
}
else {
@@ -805,12 +805,15 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
@Override
public String resolveEmbeddedValue(String value) {
if (value == null) {
return null;
}
String result = value;
for (StringValueResolver resolver : this.embeddedValueResolvers) {
result = resolver.resolveStringValue(result);
if (result == null) {
return null;
}
result = resolver.resolveStringValue(result);
}
return result;
}
@@ -1050,11 +1053,11 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
* Destroy the given bean instance (usually a prototype instance
* obtained from this factory) according to the given bean definition.
* @param beanName the name of the bean definition
* @param beanInstance the bean instance to destroy
* @param bean the bean instance to destroy
* @param mbd the merged bean definition
*/
protected void destroyBean(String beanName, Object beanInstance, RootBeanDefinition mbd) {
new DisposableBeanAdapter(beanInstance, beanName, mbd, getBeanPostProcessors(), getAccessControlContext()).destroy();
protected void destroyBean(String beanName, Object bean, RootBeanDefinition mbd) {
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), getAccessControlContext()).destroy();
}
@Override
@@ -1235,12 +1238,13 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
if (getParentBeanFactory() instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(parentBeanName);
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(bd.getParentName(),
"Parent name '" + bd.getParentName() + "' is equal to bean name '" + beanName +
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without an AbstractBeanFactory parent");
}
}
@@ -1356,12 +1360,14 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
catch (ClassNotFoundException ex) {
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
}
catch (LinkageError err) {
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
catch (LinkageError ex) {
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
}
}
private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch) throws ClassNotFoundException {
private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
throws ClassNotFoundException {
ClassLoader beanClassLoader = getBeanClassLoader();
ClassLoader classLoaderToUse = beanClassLoader;
if (!ObjectUtils.isEmpty(typesToMatch)) {
@@ -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.
@@ -115,7 +115,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
Object instance;
if (ctor == null) {
instance = BeanUtils.instantiate(subclass);
instance = BeanUtils.instantiateClass(subclass);
}
else {
try {
@@ -609,8 +609,8 @@ class ConstructorResolver {
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
this.beanFactory.getCustomTypeConverter() : bw);
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
BeanDefinitionValueResolver valueResolver =
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
@@ -665,8 +665,8 @@ class ConstructorResolver {
BeanWrapper bw, Class<?>[] paramTypes, String[] paramNames, Object methodOrCtor,
boolean autowiring) throws UnsatisfiedDependencyException {
TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
this.beanFactory.getCustomTypeConverter() : bw);
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders =
@@ -769,12 +769,13 @@ class ConstructorResolver {
private Object[] resolvePreparedArguments(
String beanName, RootBeanDefinition mbd, BeanWrapper bw, Member methodOrCtor, Object[] argsToResolve) {
Class<?>[] paramTypes = (methodOrCtor instanceof Method ?
((Method) methodOrCtor).getParameterTypes() : ((Constructor<?>) methodOrCtor).getParameterTypes());
TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
this.beanFactory.getCustomTypeConverter() : bw);
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
BeanDefinitionValueResolver valueResolver =
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
Class<?>[] paramTypes = (methodOrCtor instanceof Method ?
((Method) methodOrCtor).getParameterTypes() : ((Constructor<?>) methodOrCtor).getParameterTypes());
Object[] resolvedArgs = new Object[argsToResolve.length];
for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) {
Object argValue = argsToResolve[argIndex];
@@ -32,7 +32,6 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -52,6 +51,7 @@ import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
import org.springframework.beans.factory.CannotLoadBeanClassException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InjectionPoint;
@@ -61,11 +61,13 @@ import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.SmartFactoryBean;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.config.NamedBeanHolder;
import org.springframework.core.OrderComparator;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationUtils;
@@ -335,43 +337,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@Override
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
Assert.notNull(requiredType, "Required type must not be null");
String[] beanNames = getBeanNamesForType(requiredType);
if (beanNames.length > 1) {
ArrayList<String> autowireCandidates = new ArrayList<String>();
for (String beanName : beanNames) {
if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
autowireCandidates.add(beanName);
}
}
if (autowireCandidates.size() > 0) {
beanNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
}
NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args);
if (namedBean != null) {
return namedBean.getBeanInstance();
}
if (beanNames.length == 1) {
return getBean(beanNames[0], requiredType, args);
}
else if (beanNames.length > 1) {
Map<String, Object> candidates = new HashMap<String, Object>();
for (String beanName : beanNames) {
candidates.put(beanName, getBean(beanName, requiredType, args));
}
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return getBean(primaryCandidate, requiredType, args);
}
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return getBean(priorityCandidate, requiredType, args);
}
throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
}
else if (getParentBeanFactory() != null) {
return getParentBeanFactory().getBean(requiredType, args);
}
else {
throw new NoSuchBeanDefinitionException(requiredType);
BeanFactory parent = getParentBeanFactory();
if (parent != null) {
return parent.getBean(requiredType, args);
}
throw new NoSuchBeanDefinitionException(requiredType);
}
@@ -444,8 +418,11 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
// In case of FactoryBean, match object created by FactoryBean.
boolean isFactoryBean = isFactoryBean(beanName, mbd);
boolean matchFound = (allowEagerInit || !isFactoryBean || containsSingleton(beanName)) &&
(includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type);
boolean matchFound = (allowEagerInit || !isFactoryBean ||
(mbd.getDecoratedDefinition() != null && !mbd.isLazyInit()) ||
containsSingleton(beanName)) &&
(includeNonSingletons || isSingleton(beanName)) &&
isTypeMatch(beanName, type);
if (!matchFound && isFactoryBean) {
// In case of FactoryBean, try to match FactoryBean instance itself next.
beanName = FACTORY_BEAN_PREFIX + beanName;
@@ -651,13 +628,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
else if (containsSingleton(beanName)) {
return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor, resolver);
}
else if (getParentBeanFactory() instanceof DefaultListableBeanFactory) {
BeanFactory parent = getParentBeanFactory();
if (parent instanceof DefaultListableBeanFactory) {
// No bean definition found in this factory -> delegate to parent.
return ((DefaultListableBeanFactory) getParentBeanFactory()).isAutowireCandidate(beanName, descriptor, resolver);
return ((DefaultListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor, resolver);
}
else if (getParentBeanFactory() instanceof ConfigurableListableBeanFactory) {
else if (parent instanceof ConfigurableListableBeanFactory) {
// If no DefaultListableBeanFactory, can't pass the resolver along.
return ((ConfigurableListableBeanFactory) getParentBeanFactory()).isAutowireCandidate(beanName, descriptor);
return ((ConfigurableListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor);
}
else {
return true;
@@ -998,24 +977,86 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
//---------------------------------------------------------------------
@Override
public Object resolveDependency(DependencyDescriptor descriptor, String beanName,
public <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException {
NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, (Object[]) null);
if (namedBean != null) {
return namedBean;
}
BeanFactory parent = getParentBeanFactory();
if (parent instanceof AutowireCapableBeanFactory) {
return ((AutowireCapableBeanFactory) parent).resolveNamedBean(requiredType);
}
return null;
}
@SuppressWarnings("unchecked")
private <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType, Object... args) throws BeansException {
Assert.notNull(requiredType, "Required type must not be null");
String[] candidateNames = getBeanNamesForType(requiredType);
if (candidateNames.length > 1) {
List<String> autowireCandidates = new ArrayList<String>(candidateNames.length);
for (String beanName : candidateNames) {
if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
autowireCandidates.add(beanName);
}
}
if (!autowireCandidates.isEmpty()) {
candidateNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
}
}
if (candidateNames.length == 1) {
String beanName = candidateNames[0];
return new NamedBeanHolder<T>(beanName, getBean(beanName, requiredType, args));
}
else if (candidateNames.length > 1) {
Map<String, Object> candidates = new LinkedHashMap<String, Object>(candidateNames.length);
for (String beanName : candidateNames) {
if (containsSingleton(beanName)) {
candidates.put(beanName, getBean(beanName, requiredType, args));
}
else {
candidates.put(beanName, getType(beanName));
}
}
String candidateName = determinePrimaryCandidate(candidates, requiredType);
if (candidateName == null) {
candidateName = determineHighestPriorityCandidate(candidates, requiredType);
}
if (candidateName != null) {
Object beanInstance = candidates.get(candidateName);
if (beanInstance instanceof Class) {
beanInstance = getBean(candidateName, requiredType, args);
}
return new NamedBeanHolder<T>(candidateName, (T) beanInstance);
}
throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
}
return null;
}
@Override
public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (descriptor.getDependencyType().equals(javaUtilOptionalClass)) {
return new OptionalDependencyFactory().createOptionalDependency(descriptor, beanName);
if (javaUtilOptionalClass == descriptor.getDependencyType()) {
return new OptionalDependencyFactory().createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, beanName);
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330ProviderFactory().createDependencyProvider(descriptor, beanName);
return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, beanName);
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, beanName, autowiredBeanNames, typeConverter);
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
@@ -1053,13 +1094,17 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {
raiseNoSuchBeanDefinitionException(type, descriptor.getResolvableType().toString(), descriptor);
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) {
String primaryBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (primaryBeanName == null) {
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (descriptor.isRequired() || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(type, matchingBeans);
}
@@ -1070,17 +1115,20 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
return null;
}
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(primaryBeanName);
}
return matchingBeans.get(primaryBeanName);
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(entry.getKey());
autowiredBeanNames.add(autowiredBeanName);
}
return entry.getValue();
return (instanceCandidate instanceof Class ?
descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
@@ -1093,9 +1141,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
Class<?> type = descriptor.getDependencyType();
if (type.isArray()) {
Class<?> componentType = type.getComponentType();
DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);
targetDesc.increaseNestingLevel();
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, targetDesc);
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
new MultiElementDependencyDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
@@ -1114,9 +1161,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (elementType == null) {
return null;
}
DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);
targetDesc.increaseNestingLevel();
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, targetDesc);
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
new MultiElementDependencyDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
@@ -1139,9 +1185,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (valueType == null) {
return null;
}
DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);
targetDesc.increaseNestingLevel();
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, targetDesc);
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
new MultiElementDependencyDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
@@ -1210,7 +1255,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
for (String candidateName : candidateNames) {
if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, descriptor)) {
result.put(candidateName, descriptor.resolveCandidate(candidateName, this));
addCandidateEntry(result, candidateName, descriptor, requiredType);
}
}
if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {
@@ -1218,14 +1263,14 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidateName : candidateNames) {
if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
result.put(candidateName, descriptor.resolveCandidate(candidateName, this));
addCandidateEntry(result, candidateName, descriptor, requiredType);
}
}
if (result.isEmpty()) {
// Consider self references before as a final pass
for (String candidateName : candidateNames) {
if (isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
result.put(candidateName, descriptor.resolveCandidate(candidateName, this));
addCandidateEntry(result, candidateName, descriptor, requiredType);
}
}
}
@@ -1233,31 +1278,46 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
return result;
}
/**
* Add an entry to the candidate map: a bean instance if available or just the resolved
* type, preventing early bean initialization ahead of primary candidate selection.
*/
private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
DependencyDescriptor descriptor, Class<?> requiredType) {
if (descriptor instanceof MultiElementDependencyDescriptor || containsSingleton(candidateName)) {
candidates.put(candidateName, descriptor.resolveCandidate(candidateName, requiredType, this));
}
else {
candidates.put(candidateName, getType(candidateName));
}
}
/**
* Determine the autowire candidate in the given set of beans.
* <p>Looks for {@code @Primary} and {@code @Priority} (in that order).
* @param candidateBeans a Map of candidate names and candidate instances
* @param candidates a Map of candidate names and candidate instances
* that match the required type, as returned by {@link #findAutowireCandidates}
* @param descriptor the target dependency to match against
* @return the name of the autowire candidate, or {@code null} if none found
*/
protected String determineAutowireCandidate(Map<String, Object> candidateBeans, DependencyDescriptor descriptor) {
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
String primaryCandidate = determinePrimaryCandidate(candidateBeans, requiredType);
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
String priorityCandidate = determineHighestPriorityCandidate(candidateBeans, requiredType);
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// Fallback
for (Map.Entry<String, Object> entry : candidateBeans.entrySet()) {
String candidateBeanName = entry.getKey();
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateBeanName, descriptor.getDependencyName())) {
return candidateBeanName;
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
@@ -1265,15 +1325,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
/**
* Determine the primary candidate in the given set of beans.
* @param candidateBeans a Map of candidate names and candidate instances
* that match the required type
* @param candidates a Map of candidate names and candidate instances
* (or candidate classes if not created yet) that match the required type
* @param requiredType the target dependency type to match against
* @return the name of the primary candidate, or {@code null} if none found
* @see #isPrimary(String, Object)
*/
protected String determinePrimaryCandidate(Map<String, Object> candidateBeans, Class<?> requiredType) {
protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
String primaryBeanName = null;
for (Map.Entry<String, Object> entry : candidateBeans.entrySet()) {
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
if (isPrimary(candidateBeanName, beanInstance)) {
@@ -1281,8 +1341,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
boolean candidateLocal = containsBeanDefinition(candidateBeanName);
boolean primaryLocal = containsBeanDefinition(primaryBeanName);
if (candidateLocal && primaryLocal) {
throw new NoUniqueBeanDefinitionException(requiredType, candidateBeans.size(),
"more than one 'primary' bean found among candidates: " + candidateBeans.keySet());
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"more than one 'primary' bean found among candidates: " + candidates.keySet());
}
else if (candidateLocal) {
primaryBeanName = candidateBeanName;
@@ -1297,29 +1357,30 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
/**
* Determine the candidate with the highest priority in the given set of beans. As
* defined by the {@link org.springframework.core.Ordered} interface, the lowest
* value has the highest priority.
* @param candidateBeans a Map of candidate names and candidate instances
* that match the required type
* Determine the candidate with the highest priority in the given set of beans.
* <p>Based on {@code @javax.annotation.Priority}. As defined by the related
* {@link org.springframework.core.Ordered} interface, the lowest value has
* the highest priority.
* @param candidates a Map of candidate names and candidate instances
* (or candidate classes if not created yet) that match the required type
* @param requiredType the target dependency type to match against
* @return the name of the candidate with the highest priority,
* or {@code null} if none found
* @see #getPriority(Object)
*/
protected String determineHighestPriorityCandidate(Map<String, Object> candidateBeans, Class<?> requiredType) {
protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
String highestPriorityBeanName = null;
Integer highestPriority = null;
for (Map.Entry<String, Object> entry : candidateBeans.entrySet()) {
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
Integer candidatePriority = getPriority(beanInstance);
if (candidatePriority != null) {
if (highestPriorityBeanName != null) {
if (candidatePriority.equals(highestPriority)) {
throw new NoUniqueBeanDefinitionException(requiredType, candidateBeans.size(),
"Multiple beans found with the same priority ('" + highestPriority + "') " +
"among candidates: " + candidateBeans.keySet());
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"Multiple beans found with the same priority ('" + highestPriority +
"') among candidates: " + candidates.keySet());
}
else if (candidatePriority < highestPriority) {
highestPriorityBeanName = candidateBeanName;
@@ -1346,9 +1407,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (containsBeanDefinition(beanName)) {
return getMergedLocalBeanDefinition(beanName).isPrimary();
}
BeanFactory parentFactory = getParentBeanFactory();
return (parentFactory instanceof DefaultListableBeanFactory &&
((DefaultListableBeanFactory) parentFactory).isPrimary(beanName, beanInstance));
BeanFactory parent = getParentBeanFactory();
return (parent instanceof DefaultListableBeanFactory &&
((DefaultListableBeanFactory) parent).isPrimary(beanName, beanInstance));
}
/**
@@ -1392,17 +1453,44 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
/**
* Raise a NoSuchBeanDefinitionException for an unresolvable dependency.
* Raise a NoSuchBeanDefinitionException or BeanNotOfRequiredTypeException
* for an unresolvable dependency.
*/
private void raiseNoSuchBeanDefinitionException(
Class<?> type, String dependencyDescription, DependencyDescriptor descriptor)
throws NoSuchBeanDefinitionException {
private void raiseNoMatchingBeanFound(
Class<?> type, ResolvableType resolvableType, DependencyDescriptor descriptor) throws BeansException {
throw new NoSuchBeanDefinitionException(type, dependencyDescription,
"expected at least 1 bean which qualifies as autowire candidate for this dependency. " +
checkBeanNotOfRequiredType(type, descriptor);
throw new NoSuchBeanDefinitionException(resolvableType,
"expected at least 1 bean which qualifies as autowire candidate. " +
"Dependency annotations: " + ObjectUtils.nullSafeToString(descriptor.getAnnotations()));
}
/**
* Raise a BeanNotOfRequiredTypeException for an unresolvable dependency, if applicable,
* i.e. if the target type of the bean would match but an exposed proxy doesn't.
*/
private void checkBeanNotOfRequiredType(Class<?> type, DependencyDescriptor descriptor) {
for (String beanName : this.beanDefinitionNames) {
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
Class<?> targetType = mbd.getTargetType();
if (targetType != null && type.isAssignableFrom(targetType) &&
isAutowireCandidate(beanName, mbd, descriptor, getAutowireCandidateResolver())) {
// Probably a poxy interfering with target type match -> throw meaningful exception.
Object beanInstance = getSingleton(beanName, false);
Class<?> beanType = (beanInstance != null ? beanInstance.getClass() : predictBeanType(beanName, mbd));
if (type != beanType) {
throw new BeanNotOfRequiredTypeException(beanName, type, beanType);
}
}
}
BeanFactory parent = getParentBeanFactory();
if (parent instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) parent).checkBeanNotOfRequiredType(type, descriptor);
}
}
@Override
public String toString() {
@@ -1473,18 +1561,17 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
private class OptionalDependencyFactory {
public Object createOptionalDependency(DependencyDescriptor descriptor, String beanName, final Object... args) {
DependencyDescriptor descriptorToUse = new DependencyDescriptor(descriptor) {
DependencyDescriptor descriptorToUse = new NestedDependencyDescriptor(descriptor) {
@Override
public boolean isRequired() {
return false;
}
@Override
public Object resolveCandidate(String beanName, BeanFactory beanFactory) {
return (!ObjectUtils.isEmpty(args) ? beanFactory.getBean(beanName, args) :
super.resolveCandidate(beanName, beanFactory));
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) {
return (!ObjectUtils.isEmpty(args) ? beanFactory.getBean(beanName, requiredType, args) :
super.resolveCandidate(beanName, requiredType, beanFactory));
}
};
descriptorToUse.increaseNestingLevel();
return Optional.ofNullable(doResolveDependency(descriptorToUse, beanName, null, null));
}
}
@@ -1502,9 +1589,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
private final String beanName;
public DependencyObjectProvider(DependencyDescriptor descriptor, String beanName) {
this.descriptor = new DependencyDescriptor(descriptor);
this.descriptor.increaseNestingLevel();
this.optional = this.descriptor.getDependencyType().equals(javaUtilOptionalClass);
this.descriptor = new NestedDependencyDescriptor(descriptor);
this.optional = (this.descriptor.getDependencyType() == javaUtilOptionalClass);
this.beanName = beanName;
}
@@ -1526,8 +1612,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
else {
DependencyDescriptor descriptorToUse = new DependencyDescriptor(descriptor) {
@Override
public Object resolveCandidate(String beanName, BeanFactory beanFactory) {
return beanFactory.getBean(beanName, args);
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) {
return ((AbstractBeanFactory) beanFactory).getBean(beanName, requiredType, args);
}
};
return doResolveDependency(descriptorToUse, this.beanName, null, null);
@@ -1620,13 +1706,13 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (beanDefinition == null) {
return null;
}
List<Object> sources = new ArrayList<Object>();
List<Object> sources = new ArrayList<Object>(2);
Method factoryMethod = beanDefinition.getResolvedFactoryMethod();
if (factoryMethod != null) {
sources.add(factoryMethod);
}
Class<?> targetType = beanDefinition.getTargetType();
if (targetType != null && !targetType.equals(obj.getClass())) {
if (targetType != null && targetType != obj.getClass()) {
sources.add(targetType);
}
return sources.toArray(new Object[sources.size()]);
@@ -1643,4 +1729,21 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
}
private static class NestedDependencyDescriptor extends DependencyDescriptor {
public NestedDependencyDescriptor(DependencyDescriptor original) {
super(original);
increaseNestingLevel();
}
}
private static class MultiElementDependencyDescriptor extends NestedDependencyDescriptor {
public MultiElementDependencyDescriptor(DependencyDescriptor original) {
super(original);
}
}
}
@@ -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.
@@ -214,7 +214,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while the singletons of this factory are in destruction " +
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
@@ -449,10 +449,10 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
}
private boolean isDependent(String beanName, String dependentBeanName, Set<String> alreadySeen) {
String canonicalName = canonicalName(beanName);
if (alreadySeen != null && alreadySeen.contains(beanName)) {
return false;
}
String canonicalName = canonicalName(beanName);
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
return false;
@@ -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.
@@ -74,21 +74,31 @@ public class GenericTypeAwareAutowireCandidateResolver implements AutowireCandid
// No generic type -> we know it's a Class type-match, so no need to check again.
return true;
}
ResolvableType targetType = null;
boolean cacheType = false;
RootBeanDefinition rbd = null;
if (bdHolder.getBeanDefinition() instanceof RootBeanDefinition) {
rbd = (RootBeanDefinition) bdHolder.getBeanDefinition();
}
if (rbd != null) {
// First, check factory method return type, if applicable
targetType = getReturnTypeForFactoryMethod(rbd, descriptor);
targetType = rbd.targetType;
if (targetType == null) {
RootBeanDefinition dbd = getResolvedDecoratedDefinition(rbd);
if (dbd != null) {
targetType = getReturnTypeForFactoryMethod(dbd, descriptor);
cacheType = true;
// First, check factory method return type, if applicable
targetType = getReturnTypeForFactoryMethod(rbd, descriptor);
if (targetType == null) {
RootBeanDefinition dbd = getResolvedDecoratedDefinition(rbd);
if (dbd != null) {
targetType = dbd.targetType;
if (targetType == null) {
targetType = getReturnTypeForFactoryMethod(dbd, descriptor);
}
}
}
}
}
if (targetType == null) {
// Regular case: straight bean instance, with BeanFactory available.
if (this.beanFactory != null) {
@@ -106,7 +116,14 @@ public class GenericTypeAwareAutowireCandidateResolver implements AutowireCandid
}
}
}
if (targetType == null || (descriptor.fallbackMatchAllowed() && targetType.hasUnresolvableGenerics())) {
if (targetType == null) {
return true;
}
if (cacheType) {
rbd.targetType = targetType;
}
if (descriptor.fallbackMatchAllowed() && targetType.hasUnresolvableGenerics()) {
return true;
}
// Full check for complex generic type match...
@@ -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.
@@ -16,6 +16,7 @@
package org.springframework.beans.factory.support;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.HashSet;
@@ -25,6 +26,7 @@ import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.core.ResolvableType;
import org.springframework.util.Assert;
/**
@@ -48,22 +50,28 @@ import org.springframework.util.Assert;
@SuppressWarnings("serial")
public class RootBeanDefinition extends AbstractBeanDefinition {
boolean allowCaching = true;
private BeanDefinitionHolder decoratedDefinition;
private volatile Class<?> targetType;
private AnnotatedElement qualifiedElement;
boolean allowCaching = true;
boolean isFactoryMethodUnique = false;
volatile ResolvableType targetType;
/** Package-visible field for caching the determined Class of a given bean definition */
volatile Class<?> resolvedTargetType;
/** Package-visible field for caching the return type of a generically typed factory method */
volatile Class<?> resolvedFactoryMethodReturnType;
/** Common lock for the four constructor fields below */
final Object constructorArgumentLock = new Object();
/** Package-visible field for caching the resolved constructor or factory method */
Object resolvedConstructorOrFactoryMethod;
/** Package-visible field for caching the return type of a generically typed factory method */
volatile Class<?> resolvedFactoryMethodReturnType;
/** Package-visible field that marks the constructor arguments as resolved */
boolean constructorArgumentsResolved = false;
@@ -73,6 +81,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
/** Package-visible field for caching partly prepared constructor arguments */
Object[] preparedConstructorArguments;
/** Common lock for the two post-processing fields below */
final Object postProcessingLock = new Object();
/** Package-visible field that indicates MergedBeanDefinitionPostProcessor having been applied */
@@ -125,7 +134,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
setBeanClass(beanClass);
setAutowireMode(autowireMode);
if (dependencyCheck && getResolvedAutowireMode() != AUTOWIRE_CONSTRUCTOR) {
setDependencyCheck(RootBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
setDependencyCheck(DEPENDENCY_CHECK_OBJECTS);
}
}
@@ -171,10 +180,11 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
*/
public RootBeanDefinition(RootBeanDefinition original) {
super(original);
this.allowCaching = original.allowCaching;
this.decoratedDefinition = original.decoratedDefinition;
this.targetType = original.targetType;
this.qualifiedElement = original.qualifiedElement;
this.allowCaching = original.allowCaching;
this.isFactoryMethodUnique = original.isFactoryMethodUnique;
this.targetType = original.targetType;
}
/**
@@ -213,19 +223,52 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
return this.decoratedDefinition;
}
/**
* Specify the {@link AnnotatedElement} defining qualifiers,
* to be used instead of the target class or factory method.
* @since 4.3.3
* @see #setTargetType(ResolvableType)
* @see #getResolvedFactoryMethod()
*/
public void setQualifiedElement(AnnotatedElement qualifiedElement) {
this.qualifiedElement = qualifiedElement;
}
/**
* Return the {@link AnnotatedElement} defining qualifiers, if any.
* Otherwise, the factory method and target class will be checked.
* @since 4.3.3
*/
public AnnotatedElement getQualifiedElement() {
return this.qualifiedElement;
}
/**
* Specify a generics-containing target type of this bean definition, if known in advance.
* @since 4.3.3
*/
public void setTargetType(ResolvableType targetType) {
this.targetType = targetType;
}
/**
* Specify the target type of this bean definition, if known in advance.
* @since 3.2.2
*/
public void setTargetType(Class<?> targetType) {
this.targetType = targetType;
this.targetType = (targetType != null ? ResolvableType.forClass(targetType) : null);
}
/**
* Return the target type of this bean definition, if known
* (either specified in advance or resolved on first instantiation).
* @since 3.2.2
*/
public Class<?> getTargetType() {
return this.targetType;
if (this.resolvedTargetType != null) {
return this.resolvedTargetType;
}
return (this.targetType != null ? this.targetType.resolve() : null);
}
/**
@@ -81,7 +81,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Exception ex) {
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", 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.
@@ -200,6 +200,7 @@ public class UtilNamespaceHandler extends NamespaceHandlerSupport {
String location = element.getAttribute("location");
if (StringUtils.hasLength(location)) {
location = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(location);
String[] locations = StringUtils.commaDelimitedListToStringArray(location);
builder.addPropertyValue("locations", locations);
}
@@ -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.
@@ -154,9 +154,9 @@ public class CustomCollectionEditor extends PropertyEditorSupport {
try {
return collectionType.newInstance();
}
catch (Exception ex) {
catch (Throwable ex) {
throw new IllegalArgumentException(
"Could not instantiate collection class [" + collectionType.getName() + "]: " + ex.getMessage());
"Could not instantiate collection class: " + collectionType.getName(), ex);
}
}
else if (List.class == collectionType) {
@@ -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.
@@ -132,9 +132,9 @@ public class CustomMapEditor extends PropertyEditorSupport {
try {
return mapType.newInstance();
}
catch (Exception ex) {
catch (Throwable ex) {
throw new IllegalArgumentException(
"Could not instantiate map class [" + mapType.getName() + "]: " + ex.getMessage());
"Could not instantiate map class: " + mapType.getName(), ex);
}
}
else if (SortedMap.class == mapType) {
@@ -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.
@@ -59,16 +59,14 @@ public class FileEditor extends PropertyEditorSupport {
/**
* Create a new FileEditor,
* using the default ResourceEditor underneath.
* Create a new FileEditor, using a default ResourceEditor underneath.
*/
public FileEditor() {
this.resourceEditor = new ResourceEditor();
}
/**
* Create a new FileEditor,
* using the given ResourceEditor underneath.
* Create a new FileEditor, using the given ResourceEditor underneath.
* @param resourceEditor the ResourceEditor to use
*/
public FileEditor(ResourceEditor resourceEditor) {
@@ -86,8 +84,9 @@ public class FileEditor extends PropertyEditorSupport {
// Check whether we got an absolute file path without "file:" prefix.
// For backwards compatibility, we'll consider those as straight file path.
File file = null;
if (!ResourceUtils.isUrl(text)) {
File file = new File(text);
file = new File(text);
if (file.isAbsolute()) {
setValue(file);
return;
@@ -99,18 +98,18 @@ public class FileEditor extends PropertyEditorSupport {
Resource resource = (Resource) this.resourceEditor.getValue();
// If it's a URL or a path pointing to an existing resource, use it as-is.
if (ResourceUtils.isUrl(text) || resource.exists()) {
if (file == null || resource.exists()) {
try {
setValue(resource.getFile());
}
catch (IOException ex) {
throw new IllegalArgumentException(
"Could not retrieve File for " + resource + ": " + ex.getMessage());
"Could not retrieve file for " + resource + ": " + ex.getMessage());
}
}
else {
// Create a relative File reference and hope for the best.
setValue(new File(text));
// Set a relative File reference and hope for the best.
setValue(file);
}
}
@@ -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.
@@ -47,16 +47,14 @@ public class InputStreamEditor extends PropertyEditorSupport {
/**
* Create a new InputStreamEditor,
* using the default ResourceEditor underneath.
* Create a new InputStreamEditor, using the default ResourceEditor underneath.
*/
public InputStreamEditor() {
this.resourceEditor = new ResourceEditor();
}
/**
* Create a new InputStreamEditor,
* using the given ResourceEditor underneath.
* Create a new InputStreamEditor, using the given ResourceEditor underneath.
* @param resourceEditor the ResourceEditor to use
*/
public InputStreamEditor(ResourceEditor resourceEditor) {
@@ -0,0 +1,123 @@
/*
* 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.beans.propertyeditors;
import java.beans.PropertyEditorSupport;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.FileSystemNotFoundException;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceEditor;
import org.springframework.core.io.ResourceLoader;
import org.springframework.lang.UsesJava7;
import org.springframework.util.Assert;
/**
* Editor for {@code java.nio.file.Path}, to directly populate a Path
* property instead of using a String property as bridge.
*
* <p>Based on {@link Paths#get(URI)}'s resolution algorithm, checking
* registered NIO file system providers, including the default file system
* for "file:..." paths. Also supports Spring-style URL notation: any fully
* qualified standard URL and Spring's special "classpath:" pseudo-URL, as
* well as Spring's context-specific relative file paths. As a fallback, a
* path will be resolved in the file system via {@code Paths#get(String)}
* if no existing context-relative resource could be found.
*
* @author Juergen Hoeller
* @since 4.3.2
* @see java.nio.file.Path
* @see Paths#get(URI)
* @see ResourceEditor
* @see org.springframework.core.io.ResourceLoader
* @see FileEditor
* @see URLEditor
*/
@UsesJava7
public class PathEditor extends PropertyEditorSupport {
private final ResourceEditor resourceEditor;
/**
* Create a new PathEditor, using the default ResourceEditor underneath.
*/
public PathEditor() {
this.resourceEditor = new ResourceEditor();
}
/**
* Create a new PathEditor, using the given ResourceEditor underneath.
* @param resourceEditor the ResourceEditor to use
*/
public PathEditor(ResourceEditor resourceEditor) {
Assert.notNull(resourceEditor, "ResourceEditor must not be null");
this.resourceEditor = resourceEditor;
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
boolean nioPathCandidate = !text.startsWith(ResourceLoader.CLASSPATH_URL_PREFIX);
if (nioPathCandidate && !text.startsWith("/")) {
try {
URI uri = new URI(text);
if (uri.getScheme() != null) {
nioPathCandidate = false;
// Let's try NIO file system providers via Paths.get(URI)
setValue(Paths.get(uri).normalize());
return;
}
}
catch (URISyntaxException ex) {
// Not a valid URI: Let's try as Spring resource location.
}
catch (FileSystemNotFoundException ex) {
// URI scheme not registered for NIO:
// Let's try URL protocol handlers via Spring's resource mechanism.
}
}
this.resourceEditor.setAsText(text);
Resource resource = (Resource) this.resourceEditor.getValue();
if (resource == null) {
setValue(null);
}
else if (!resource.exists() && nioPathCandidate) {
setValue(Paths.get(text).normalize());
}
else {
try {
setValue(resource.getFile().toPath());
}
catch (IOException ex) {
throw new IllegalArgumentException("Failed to retrieve file for " + resource, ex);
}
}
}
@Override
public String getAsText() {
Path value = (Path) getValue();
return (value != null ? value.toString() : "");
}
}
@@ -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.
@@ -47,16 +47,14 @@ public class ReaderEditor extends PropertyEditorSupport {
/**
* Create a new ReaderEditor,
* using the default ResourceEditor underneath.
* Create a new ReaderEditor, using the default ResourceEditor underneath.
*/
public ReaderEditor() {
this.resourceEditor = new ResourceEditor();
}
/**
* Create a new ReaderEditor,
* using the given ResourceEditor underneath.
* Create a new ReaderEditor, using the given ResourceEditor underneath.
* @param resourceEditor the ResourceEditor to use
*/
public ReaderEditor(ResourceEditor resourceEditor) {
@@ -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.
@@ -60,8 +60,7 @@ public class URIEditor extends PropertyEditorSupport {
* standard URIs (not trying to resolve them into physical resources).
*/
public URIEditor() {
this.classLoader = null;
this.encode = true;
this(true);
}
/**
@@ -74,7 +73,6 @@ public class URIEditor extends PropertyEditorSupport {
this.encode = encode;
}
/**
* Create a new URIEditor, using the given ClassLoader to resolve
* "classpath:" locations into physical resource URLs.
@@ -82,8 +80,7 @@ public class URIEditor extends PropertyEditorSupport {
* (may be {@code null} to indicate the default ClassLoader)
*/
public URIEditor(ClassLoader classLoader) {
this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
this.encode = true;
this(classLoader, true);
}
/**
@@ -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.
@@ -50,7 +50,7 @@ public class URLEditor extends PropertyEditorSupport {
/**
* Create a new URLEditor, using the default ResourceEditor underneath.
* Create a new URLEditor, using a default ResourceEditor underneath.
*/
public URLEditor() {
this.resourceEditor = new ResourceEditor();
@@ -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,6 +33,7 @@ import org.springframework.beans.propertyeditors.ClassEditor;
import org.springframework.beans.propertyeditors.FileEditor;
import org.springframework.beans.propertyeditors.InputSourceEditor;
import org.springframework.beans.propertyeditors.InputStreamEditor;
import org.springframework.beans.propertyeditors.PathEditor;
import org.springframework.beans.propertyeditors.ReaderEditor;
import org.springframework.beans.propertyeditors.URIEditor;
import org.springframework.beans.propertyeditors.URLEditor;
@@ -43,6 +44,7 @@ import org.springframework.core.io.ResourceEditor;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourceArrayPropertyEditor;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.ClassUtils;
/**
* PropertyEditorRegistrar implementation that populates a given
@@ -58,6 +60,19 @@ import org.springframework.core.io.support.ResourcePatternResolver;
*/
public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
private static Class<?> pathClass;
static {
try {
pathClass = ClassUtils.forName("java.nio.file.Path", ResourceEditorRegistrar.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
// Java 7 Path class not available
pathClass = null;
}
}
private final PropertyResolver propertyResolver;
private final ResourceLoader resourceLoader;
@@ -103,6 +118,9 @@ public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
if (pathClass != null) {
doRegisterEditor(registry, pathClass, new PathEditor(baseEditor));
}
doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor));
doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));
@@ -1435,12 +1435,14 @@ public class DefaultListableBeanFactoryTests {
public void testGetBeanByTypeWithPrimary() throws Exception {
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
bd1.setLazyInit(true);
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
bd2.setPrimary(true);
lbf.registerBeanDefinition("bd1", bd1);
lbf.registerBeanDefinition("bd2", bd2);
TestBean bean = lbf.getBean(TestBean.class);
assertThat(bean.getBeanName(), equalTo("bd2"));
assertFalse(lbf.containsSingleton("bd1"));
}
@Test
@@ -1760,24 +1762,6 @@ public class DefaultListableBeanFactoryTests {
}
}
@Test
public void testAutowireBeanByTypeWithTwoMatchesAndParameterNameDiscovery() {
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
lbf.registerBeanDefinition("test", bd);
lbf.registerBeanDefinition("spouse", bd2);
try {
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
fail("Should have thrown UnsatisfiedDependencyException");
}
catch (UnsatisfiedDependencyException ex) {
// expected
assertTrue(ex.getMessage().contains("test"));
assertTrue(ex.getMessage().contains("spouse"));
}
}
@Test
public void testAutowireBeanByTypeWithDependencyCheck() {
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
@@ -2216,7 +2200,7 @@ public class DefaultListableBeanFactoryTests {
@Test
public void testPrototypeWithArrayConversionForConstructor() {
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
List<String> list = new ManagedList<String>();
List<String> list = new ManagedList<>();
list.add("myName");
list.add("myBeanName");
RootBeanDefinition bd = new RootBeanDefinition(DerivedTestBean.class);
@@ -2235,7 +2219,7 @@ public class DefaultListableBeanFactoryTests {
@Test
public void testPrototypeWithArrayConversionForFactoryMethod() {
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
List<String> list = new ManagedList<String>();
List<String> list = new ManagedList<>();
list.add("myName");
list.add("myBeanName");
RootBeanDefinition bd = new RootBeanDefinition(DerivedTestBean.class);
@@ -41,6 +41,7 @@ import org.mockito.Mockito;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
@@ -62,6 +63,7 @@ import org.springframework.tests.sample.beans.ITestBean;
import org.springframework.tests.sample.beans.IndexedTestBean;
import org.springframework.tests.sample.beans.NestedTestBean;
import org.springframework.tests.sample.beans.TestBean;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.SerializationTestUtils;
import static org.junit.Assert.*;
@@ -1025,14 +1027,35 @@ public class AutowiredAnnotationBeanPostProcessorTests {
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryQualifierInjectionBean.class));
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
bd.addQualifier(new AutowireCandidateQualifier(Qualifier.class, "testBean"));
bf.registerBeanDefinition("testBean", bd);
bf.registerBeanDefinition("testBean2", new RootBeanDefinition(TestBean.class));
bf.registerBeanDefinition("dependencyBean", bd);
bf.registerBeanDefinition("dependencyBean2", new RootBeanDefinition(TestBean.class));
ObjectFactoryQualifierInjectionBean bean = (ObjectFactoryQualifierInjectionBean) bf.getBean("annotatedBean");
assertSame(bf.getBean("testBean"), bean.getTestBean());
assertSame(bf.getBean("dependencyBean"), bean.getTestBean());
bf.destroySingletons();
}
@Test
public void testObjectFactoryQualifierProviderInjection() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
bpp.setBeanFactory(bf);
bf.addBeanPostProcessor(bpp);
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryQualifierInjectionBean.class));
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
bd.setQualifiedElement(ReflectionUtils.findMethod(getClass(), "testBeanQualifierProvider"));
bf.registerBeanDefinition("dependencyBean", bd);
bf.registerBeanDefinition("dependencyBean2", new RootBeanDefinition(TestBean.class));
ObjectFactoryQualifierInjectionBean bean = (ObjectFactoryQualifierInjectionBean) bf.getBean("annotatedBean");
assertSame(bf.getBean("dependencyBean"), bean.getTestBean());
bf.destroySingletons();
}
@Qualifier("testBean")
private void testBeanQualifierProvider() {}
@Test
public void testObjectFactorySerialization() throws Exception {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
@@ -1145,12 +1168,15 @@ public class AutowiredAnnotationBeanPostProcessorTests {
RootBeanDefinition tb1 = new RootBeanDefinition(TestBean.class);
tb1.setPrimary(true);
bf.registerBeanDefinition("testBean1", tb1);
bf.registerBeanDefinition("testBean2", new RootBeanDefinition(TestBean.class));
RootBeanDefinition tb2 = new RootBeanDefinition(TestBean.class);
tb2.setLazyInit(true);
bf.registerBeanDefinition("testBean2", tb2);
SmartObjectFactoryInjectionBean bean = (SmartObjectFactoryInjectionBean) bf.getBean("annotatedBean");
assertSame(bf.getBean("testBean1"), bean.getTestBean());
assertSame(bf.getBean("testBean1"), bean.getOptionalTestBean());
assertSame(bf.getBean("testBean1"), bean.getUniqueTestBean());
assertFalse(bf.containsSingleton("testBean2"));
bf.destroySingletons();
}
@@ -1584,11 +1610,12 @@ public class AutowiredAnnotationBeanPostProcessorTests {
rbd.setFactoryBeanName("mocksControl");
rbd.setFactoryMethodName("createMock");
rbd.getConstructorArgumentValues().addGenericArgumentValue(Repository.class);
bf.registerBeanDefinition("integerRepo", rbd);
rbd.setQualifiedElement(ReflectionUtils.findField(getClass(), "integerRepositoryQualifierProvider"));
bf.registerBeanDefinition("integerRepository", rbd); // Bean name not matching qualifier
RepositoryFieldInjectionBeanWithQualifiers bean = (RepositoryFieldInjectionBeanWithQualifiers) bf.getBean("annotatedBean");
Repository<?> sr = bf.getBean("stringRepo", Repository.class);
Repository<?> ir = bf.getBean("integerRepo", Repository.class);
Repository<?> ir = bf.getBean("integerRepository", Repository.class);
assertSame(sr, bean.stringRepository);
assertSame(ir, bean.integerRepository);
assertSame(1, bean.stringRepositoryArray.length);
@@ -1602,9 +1629,12 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertSame(1, bean.stringRepositoryMap.size());
assertSame(1, bean.integerRepositoryMap.size());
assertSame(sr, bean.stringRepositoryMap.get("stringRepo"));
assertSame(ir, bean.integerRepositoryMap.get("integerRepo"));
assertSame(ir, bean.integerRepositoryMap.get("integerRepository"));
}
@Qualifier("integerRepo")
private Repository<?> integerRepositoryQualifierProvider;
@Test
public void testGenericsBasedFieldInjectionWithSimpleMatch() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
@@ -2047,6 +2077,24 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertSame(bean2, bean1.gi2);
}
@Test
public void testGenericsBasedInjectionWithBeanDefinitionTargetResolvableType() throws Exception {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
bpp.setBeanFactory(bf);
bf.addBeanPostProcessor(bpp);
RootBeanDefinition bd1 = new RootBeanDefinition(GenericInterface2Bean.class);
bd1.setTargetType(ResolvableType.forClassWithGenerics(GenericInterface2Bean.class, String.class));
bf.registerBeanDefinition("bean1", bd1);
RootBeanDefinition bd2 = new RootBeanDefinition(GenericInterface2Bean.class);
bd2.setTargetType(ResolvableType.forClassWithGenerics(GenericInterface2Bean.class, Integer.class));
bf.registerBeanDefinition("bean2", bd2);
bf.registerBeanDefinition("bean3", new RootBeanDefinition(MultiGenericFieldInjection.class));
assertEquals("bean1 a bean2 123", bf.getBean("bean3").toString());
}
@Test
public void testCircularTypeReference() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
@@ -3139,6 +3187,37 @@ public class AutowiredAnnotationBeanPostProcessorTests {
}
public static class GenericInterface2Bean<K> implements GenericInterface2<K>, BeanNameAware {
private String name;
@Override
public void setBeanName(String name) {
this.name = name;
}
@Override
public String doSomethingMoreGeneric(K o) {
return this.name + " " + o;
}
}
public static class MultiGenericFieldInjection {
@Autowired
private GenericInterface2<String> stringBean;
@Autowired
private GenericInterface2<Integer> integerBean;
@Override
public String toString() {
return this.stringBean.doSomethingMoreGeneric("a") + " " + this.integerBean.doSomethingMoreGeneric(123);
}
}
@SuppressWarnings("rawtypes")
public static class PlainGenericInterface2Impl implements GenericInterface2 {
@@ -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.
@@ -41,6 +41,7 @@ public class LookupAnnotationTests {
aabpp.setBeanFactory(beanFactory);
beanFactory.addBeanPostProcessor(aabpp);
beanFactory.registerBeanDefinition("abstractBean", new RootBeanDefinition(AbstractBean.class));
beanFactory.registerBeanDefinition("beanConsumer", new RootBeanDefinition(BeanConsumer.class));
RootBeanDefinition tbd = new RootBeanDefinition(TestBean.class);
tbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
beanFactory.registerBeanDefinition("testBean", tbd);
@@ -53,6 +54,7 @@ public class LookupAnnotationTests {
assertNotNull(bean);
Object expected = bean.get();
assertEquals(TestBean.class, expected.getClass());
assertSame(bean, beanFactory.getBean(BeanConsumer.class).abstractBean);
}
@Test
@@ -62,6 +64,7 @@ public class LookupAnnotationTests {
TestBean expected = bean.get("haha");
assertEquals(TestBean.class, expected.getClass());
assertEquals("haha", expected.getName());
assertSame(bean, beanFactory.getBean(BeanConsumer.class).abstractBean);
}
@Test
@@ -71,6 +74,7 @@ public class LookupAnnotationTests {
TestBean expected = bean.getOneArgument("haha");
assertEquals(TestBean.class, expected.getClass());
assertEquals("haha", expected.getName());
assertSame(bean, beanFactory.getBean(BeanConsumer.class).abstractBean);
}
@Test
@@ -81,6 +85,7 @@ public class LookupAnnotationTests {
assertEquals(TestBean.class, expected.getClass());
assertEquals("haha", expected.getName());
assertEquals(72, expected.getAge());
assertSame(bean, beanFactory.getBean(BeanConsumer.class).abstractBean);
}
@Test
@@ -93,6 +98,16 @@ public class LookupAnnotationTests {
}
catch (AbstractMethodError ex) {
}
assertSame(bean, beanFactory.getBean(BeanConsumer.class).abstractBean);
}
@Test
public void testWithEarlyInjection() {
AbstractBean bean = beanFactory.getBean("beanConsumer", BeanConsumer.class).abstractBean;
assertNotNull(bean);
Object expected = bean.get();
assertEquals(TestBean.class, expected.getClass());
assertSame(bean, beanFactory.getBean(BeanConsumer.class).abstractBean);
}
@@ -113,4 +128,11 @@ public class LookupAnnotationTests {
public abstract TestBean getThreeArguments(String name, int age, int anotherArg);
}
public static class BeanConsumer {
@Autowired
AbstractBean abstractBean;
}
}
@@ -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.
@@ -34,43 +34,40 @@ import static org.junit.Assert.*;
* Tests for {@link YamlMapFactoryBean}.
*
* @author Dave Syer
* @author Juergen Hoeller
*/
public class YamlMapFactoryBeanTests {
private final YamlMapFactoryBean factory = new YamlMapFactoryBean();
@Test
public void testSetIgnoreResourceNotFound() throws Exception {
this.factory
.setResolutionMethod(YamlMapFactoryBean.ResolutionMethod.OVERRIDE_AND_IGNORE);
this.factory.setResources(new FileSystemResource[] {new FileSystemResource(
"non-exsitent-file.yml")});
this.factory.setResolutionMethod(YamlMapFactoryBean.ResolutionMethod.OVERRIDE_AND_IGNORE);
this.factory.setResources(new FileSystemResource("non-exsitent-file.yml"));
assertEquals(0, this.factory.getObject().size());
}
@Test(expected = IllegalStateException.class)
public void testSetBarfOnResourceNotFound() throws Exception {
this.factory.setResources(new FileSystemResource[] {new FileSystemResource(
"non-exsitent-file.yml")});
this.factory.setResources(new FileSystemResource("non-exsitent-file.yml"));
assertEquals(0, this.factory.getObject().size());
}
@Test
public void testGetObject() throws Exception {
this.factory.setResources(new ByteArrayResource[] {new ByteArrayResource(
"foo: bar".getBytes())});
this.factory.setResources(new ByteArrayResource("foo: bar".getBytes()));
assertEquals(1, this.factory.getObject().size());
}
@SuppressWarnings("unchecked")
@Test
public void testOverrideAndremoveDefaults() throws Exception {
this.factory.setResources(new ByteArrayResource[] {
new ByteArrayResource("foo:\n bar: spam".getBytes()),
new ByteArrayResource("foo:\n spam: bar".getBytes())});
public void testOverrideAndRemoveDefaults() throws Exception {
this.factory.setResources(new ByteArrayResource("foo:\n bar: spam".getBytes()),
new ByteArrayResource("foo:\n spam: bar".getBytes()));
assertEquals(1, this.factory.getObject().size());
assertEquals(2,
((Map<String, Object>) this.factory.getObject().get("foo")).size());
assertEquals(2, ((Map<String, Object>) this.factory.getObject().get("foo")).size());
}
@Test
@@ -81,20 +78,20 @@ public class YamlMapFactoryBeanTests {
public String getDescription() {
return "non-existent";
}
@Override
public InputStream getInputStream() throws IOException {
throw new IOException("planned");
}
}, new ByteArrayResource("foo:\n spam: bar".getBytes()));
assertEquals(1, this.factory.getObject().size());
}
@Test
public void testMapWithPeriodsInKey() throws Exception {
this.factory.setResources(new ByteArrayResource[] {new ByteArrayResource(
"foo:\n ? key1.key2\n : value".getBytes())});
this.factory.setResources(new ByteArrayResource("foo:\n ? key1.key2\n : value".getBytes()));
Map<String, Object> map = this.factory.getObject();
assertEquals(1, map.size());
assertTrue(map.containsKey("foo"));
Object object = map.get("foo");
@@ -105,10 +102,24 @@ public class YamlMapFactoryBeanTests {
assertEquals("value", sub.get("key1.key2"));
}
@Test
public void testMapWithIntegerValue() throws Exception {
this.factory.setResources(new ByteArrayResource("foo:\n ? key1.key2\n : 3".getBytes()));
Map<String, Object> map = this.factory.getObject();
assertEquals(1, map.size());
assertTrue(map.containsKey("foo"));
Object object = map.get("foo");
assertTrue(object instanceof LinkedHashMap);
@SuppressWarnings("unchecked")
Map<String, Object> sub = (Map<String, Object>) object;
assertTrue(sub.containsKey("key1.key2"));
assertEquals(Integer.valueOf(3), sub.get("key1.key2"));
}
@Test(expected = ParserException.class)
public void testDuplicateKey() throws Exception {
this.factory.setResources(new ByteArrayResource[] {new ByteArrayResource(
"mymap:\n foo: bar\nmymap:\n bar: foo".getBytes())});
this.factory.setResources(new ByteArrayResource("mymap:\n foo: bar\nmymap:\n bar: foo".getBytes()));
this.factory.getObject().get("mymap");
}
@@ -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.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.config;
import java.util.LinkedHashMap;
@@ -24,6 +25,7 @@ import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.yaml.snakeyaml.parser.ParserException;
import org.yaml.snakeyaml.scanner.ScannerException;
import org.springframework.core.io.ByteArrayResource;
import static org.junit.Assert.*;
@@ -33,34 +35,38 @@ import static org.springframework.beans.factory.config.YamlProcessor.*;
* Tests for {@link YamlProcessor}.
*
* @author Dave Syer
* @author Juergen Hoeller
*/
public class YamlProcessorTests {
private final YamlProcessor processor = new YamlProcessor() {
};
private final YamlProcessor processor = new YamlProcessor() {};
@Rule
public ExpectedException exception = ExpectedException.none();
@Test
public void arrayConvertedToIndexedBeanReference() {
this.processor.setResources(new ByteArrayResource(
"foo: bar\nbar: [1,2,3]".getBytes()));
this.processor.setResources(new ByteArrayResource("foo: bar\nbar: [1,2,3]".getBytes()));
this.processor.process(new MatchCallback() {
@Override
public void process(Properties properties, Map<String, Object> map) {
assertEquals(1, properties.get("bar[0]"));
assertEquals(2, properties.get("bar[1]"));
assertEquals(3, properties.get("bar[2]"));
assertEquals(4, properties.size());
assertEquals("bar", properties.get("foo"));
assertEquals("bar", properties.getProperty("foo"));
assertEquals(1, properties.get("bar[0]"));
assertEquals("1", properties.getProperty("bar[0]"));
assertEquals(2, properties.get("bar[1]"));
assertEquals("2", properties.getProperty("bar[1]"));
assertEquals(3, properties.get("bar[2]"));
assertEquals("3", properties.getProperty("bar[2]"));
}
});
}
@Test
public void testStringResource() throws Exception {
this.processor.setResources(new ByteArrayResource(
"foo # a document that is a literal".getBytes()));
this.processor.setResources(new ByteArrayResource("foo # a document that is a literal".getBytes()));
this.processor.process(new MatchCallback() {
@Override
public void process(Properties properties, Map<String, Object> map) {
@@ -71,8 +77,7 @@ public class YamlProcessorTests {
@Test
public void testBadDocumentStart() throws Exception {
this.processor.setResources(new ByteArrayResource(
"foo # a document\nbar: baz".getBytes()));
this.processor.setResources(new ByteArrayResource("foo # a document\nbar: baz".getBytes()));
this.exception.expect(ParserException.class);
this.exception.expectMessage("line 2, column 1");
this.processor.process(new MatchCallback() {
@@ -84,8 +89,7 @@ public class YamlProcessorTests {
@Test
public void testBadResource() throws Exception {
this.processor.setResources(new ByteArrayResource(
"foo: bar\ncd\nspam:\n foo: baz".getBytes()));
this.processor.setResources(new ByteArrayResource("foo: bar\ncd\nspam:\n foo: baz".getBytes()));
this.exception.expect(ScannerException.class);
this.exception.expectMessage("line 3, column 1");
this.processor.process(new MatchCallback() {
@@ -97,8 +101,7 @@ public class YamlProcessorTests {
@Test
public void mapConvertedToIndexedBeanReference() {
this.processor.setResources(new ByteArrayResource(
"foo: bar\nbar:\n spam: bucket".getBytes()));
this.processor.setResources(new ByteArrayResource("foo: bar\nbar:\n spam: bucket".getBytes()));
this.processor.process(new MatchCallback() {
@Override
public void process(Properties properties, Map<String, Object> map) {
@@ -111,8 +114,7 @@ public class YamlProcessorTests {
@Test
public void integerKeyBehaves() {
this.processor.setResources(new ByteArrayResource(
"foo: bar\n1: bar".getBytes()));
this.processor.setResources(new ByteArrayResource("foo: bar\n1: bar".getBytes()));
this.processor.process(new MatchCallback() {
@Override
public void process(Properties properties, Map<String, Object> map) {
@@ -124,10 +126,8 @@ public class YamlProcessorTests {
@Test
public void integerDeepKeyBehaves() {
this.processor.setResources(new ByteArrayResource(
"foo:\n 1: bar".getBytes()));
this.processor.setResources(new ByteArrayResource("foo:\n 1: bar".getBytes()));
this.processor.process(new MatchCallback() {
@Override
public void process(Properties properties, Map<String, Object> map) {
assertEquals("bar", properties.get("foo[1]"));
@@ -139,8 +139,7 @@ public class YamlProcessorTests {
@Test
@SuppressWarnings("unchecked")
public void flattenedMapIsSameAsPropertiesButOrdered() {
this.processor.setResources(new ByteArrayResource(
"foo: bar\nbar:\n spam: bucket".getBytes()));
this.processor.setResources(new ByteArrayResource("foo: bar\nbar:\n spam: bucket".getBytes()));
this.processor.process(new MatchCallback() {
@Override
public void process(Properties properties, Map<String, Object> map) {
@@ -155,4 +154,5 @@ public class YamlProcessorTests {
}
});
}
}
@@ -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.
@@ -38,12 +38,14 @@ import static org.springframework.beans.factory.config.YamlProcessor.*;
* Tests for {@link YamlPropertiesFactoryBean}.
*
* @author Dave Syer
* @author Juergen Hoeller
*/
public class YamlPropertiesFactoryBeanTests {
@Rule
public ExpectedException exception = ExpectedException.none();
@Test
public void testLoadResource() throws Exception {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
@@ -113,8 +115,8 @@ public class YamlPropertiesFactoryBeanTests {
factory.setDocumentMatchers(new DocumentMatcher() {
@Override
public MatchStatus matches(Properties properties) {
return "bag".equals(properties.getProperty("foo")) ? MatchStatus.FOUND
: MatchStatus.NOT_FOUND;
return ("bag".equals(properties.getProperty("foo")) ?
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
}
});
Properties properties = factory.getObject();
@@ -134,8 +136,8 @@ public class YamlPropertiesFactoryBeanTests {
if (!properties.containsKey("foo")) {
return MatchStatus.ABSTAIN;
}
return "bag".equals(properties.getProperty("foo")) ? MatchStatus.FOUND
: MatchStatus.NOT_FOUND;
return ("bag".equals(properties.getProperty("foo")) ?
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
}
});
Properties properties = factory.getObject();
@@ -156,8 +158,8 @@ public class YamlPropertiesFactoryBeanTests {
if (!properties.containsKey("foo")) {
return MatchStatus.ABSTAIN;
}
return "bag".equals(properties.getProperty("foo")) ? MatchStatus.FOUND
: MatchStatus.NOT_FOUND;
return ("bag".equals(properties.getProperty("foo")) ?
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
}
});
Properties properties = factory.getObject();
@@ -178,8 +180,8 @@ public class YamlPropertiesFactoryBeanTests {
if (!properties.containsKey("foo")) {
return MatchStatus.ABSTAIN;
}
return "bag".equals(properties.getProperty("foo")) ? MatchStatus.FOUND
: MatchStatus.NOT_FOUND;
return ("bag".equals(properties.getProperty("foo")) ?
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
}
});
Properties properties = factory.getObject();
@@ -200,8 +202,7 @@ public class YamlPropertiesFactoryBeanTests {
@Test
public void testLoadNull() throws Exception {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(new ByteArrayResource("foo: bar\nspam:"
.getBytes()));
factory.setResources(new ByteArrayResource("foo: bar\nspam:".getBytes()));
Properties properties = factory.getObject();
assertThat(properties.getProperty("foo"), equalTo("bar"));
assertThat(properties.getProperty("spam"), equalTo(""));
@@ -210,20 +211,28 @@ public class YamlPropertiesFactoryBeanTests {
@Test
public void testLoadArrayOfString() throws Exception {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(new ByteArrayResource("foo:\n- bar\n- baz"
.getBytes()));
factory.setResources(new ByteArrayResource("foo:\n- bar\n- baz".getBytes()));
Properties properties = factory.getObject();
assertThat(properties.getProperty("foo[0]"), equalTo("bar"));
assertThat(properties.getProperty("foo[1]"), equalTo("baz"));
assertThat(properties.get("foo"), is(nullValue()));
}
@Test
public void testLoadArrayOfInteger() throws Exception {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(new ByteArrayResource("foo:\n- 1\n- 2".getBytes()));
Properties properties = factory.getObject();
assertThat(properties.getProperty("foo[0]"), equalTo("1"));
assertThat(properties.getProperty("foo[1]"), equalTo("2"));
assertThat(properties.get("foo"), is(nullValue()));
}
@Test
public void testLoadArrayOfObject() throws Exception {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(new ByteArrayResource(
"foo:\n- bar:\n spam: crap\n- baz\n- one: two\n three: four"
.getBytes()
"foo:\n- bar:\n spam: crap\n- baz\n- one: two\n three: four".getBytes()
));
Properties properties = factory.getObject();
assertThat(properties.getProperty("foo[0].bar.spam"), equalTo("crap"));
@@ -239,8 +248,7 @@ public class YamlPropertiesFactoryBeanTests {
Yaml yaml = new Yaml();
Map<String, ?> map = yaml.loadAs("foo: bar\nspam:\n foo: baz", Map.class);
assertThat(map.get("foo"), equalTo((Object) "bar"));
assertThat(((Map<String, Object>) map.get("spam")).get("foo"),
equalTo((Object) "baz"));
assertThat(((Map<String, Object>) map.get("spam")).get("foo"), equalTo((Object) "baz"));
}
}
@@ -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.
@@ -126,6 +126,7 @@ public class BeanDefinitionTests {
bd.getConstructorArgumentValues().addIndexedArgumentValue(1, new Integer(5));
bd.getPropertyValues().add("name", "myName");
bd.getPropertyValues().add("age", "99");
bd.setQualifiedElement(getClass());
GenericBeanDefinition childBd = new GenericBeanDefinition();
childBd.setParentName("bd");
@@ -138,6 +139,7 @@ public class BeanDefinitionTests {
mergedBd.getConstructorArgumentValues().getArgumentValue(1, null).setValue(new Integer(9));
assertEquals(new Integer(5), bd.getConstructorArgumentValues().getArgumentValue(1, null).getValue());
assertEquals(getClass(), bd.getQualifiedElement());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 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,21 +28,22 @@ import static org.junit.Assert.*;
/**
* @author Thomas Risberg
* @author Chris Beams
* @author Juergen Hoeller
*/
public final class FileEditorTests {
public class FileEditorTests {
@Test
public void testClasspathFileName() throws Exception {
PropertyEditor fileEditor = new FileEditor();
fileEditor.setAsText("classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/"
+ ClassUtils.getShortName(getClass()) + ".class");
fileEditor.setAsText("classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
ClassUtils.getShortName(getClass()) + ".class");
Object value = fileEditor.getValue();
assertTrue(value instanceof File);
File file = (File) value;
assertTrue(file.exists());
}
@Test(expected=IllegalArgumentException.class)
@Test(expected = IllegalArgumentException.class)
public void testWithNonExistentResource() throws Exception {
PropertyEditor propertyEditor = new FileEditor();
propertyEditor.setAsText("classpath:no_way_this_file_is_found.doc");
@@ -71,34 +72,29 @@ public final class FileEditorTests {
@Test
public void testUnqualifiedFileNameFound() throws Exception {
PropertyEditor fileEditor = new FileEditor();
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" + ClassUtils.getShortName(getClass())
+ ".class";
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
ClassUtils.getShortName(getClass()) + ".class";
fileEditor.setAsText(fileName);
Object value = fileEditor.getValue();
assertTrue(value instanceof File);
File file = (File) value;
assertTrue(file.exists());
String absolutePath = file.getAbsolutePath();
if (File.separatorChar == '\\') {
absolutePath = absolutePath.replace('\\', '/');
}
String absolutePath = file.getAbsolutePath().replace('\\', '/');
assertTrue(absolutePath.endsWith(fileName));
}
@Test
public void testUnqualifiedFileNameNotFound() throws Exception {
PropertyEditor fileEditor = new FileEditor();
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" + ClassUtils.getShortName(getClass())
+ ".clazz";
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
ClassUtils.getShortName(getClass()) + ".clazz";
fileEditor.setAsText(fileName);
Object value = fileEditor.getValue();
assertTrue(value instanceof File);
File file = (File) value;
assertFalse(file.exists());
String absolutePath = file.getAbsolutePath();
if (File.separatorChar == '\\') {
absolutePath = absolutePath.replace('\\', '/');
}
String absolutePath = file.getAbsolutePath().replace('\\', '/');
assertTrue(absolutePath.endsWith(fileName));
}
}
@@ -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.
@@ -60,9 +60,8 @@ public class InputStreamEditorTests {
@Test(expected = IllegalArgumentException.class)
public void testWhenResourceDoesNotExist() throws Exception {
String resource = "classpath:bingo!";
InputStreamEditor editor = new InputStreamEditor();
editor.setAsText(resource);
editor.setAsText("classpath:bingo!");
}
@Test
@@ -0,0 +1,108 @@
/*
* 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.beans.propertyeditors;
import java.beans.PropertyEditor;
import java.io.File;
import java.nio.file.Path;
import org.junit.Test;
import org.springframework.util.ClassUtils;
import static org.junit.Assert.*;
/**
* @author Juergen Hoeller
* @since 4.3.2
*/
public class PathEditorTests {
@Test
public void testClasspathPathName() throws Exception {
PropertyEditor pathEditor = new PathEditor();
pathEditor.setAsText("classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
ClassUtils.getShortName(getClass()) + ".class");
Object value = pathEditor.getValue();
assertTrue(value instanceof Path);
Path path = (Path) value;
assertTrue(path.toFile().exists());
}
@Test(expected = IllegalArgumentException.class)
public void testWithNonExistentResource() throws Exception {
PropertyEditor propertyEditor = new PathEditor();
propertyEditor.setAsText("classpath:/no_way_this_file_is_found.doc");
}
@Test
public void testWithNonExistentPath() throws Exception {
PropertyEditor pathEditor = new PathEditor();
pathEditor.setAsText("file:/no_way_this_file_is_found.doc");
Object value = pathEditor.getValue();
assertTrue(value instanceof Path);
Path path = (Path) value;
assertTrue(!path.toFile().exists());
}
@Test
public void testAbsolutePath() throws Exception {
PropertyEditor pathEditor = new PathEditor();
pathEditor.setAsText("/no_way_this_file_is_found.doc");
Object value = pathEditor.getValue();
assertTrue(value instanceof Path);
Path path = (Path) value;
assertTrue(!path.toFile().exists());
}
@Test
public void testUnqualifiedPathNameFound() throws Exception {
PropertyEditor pathEditor = new PathEditor();
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
ClassUtils.getShortName(getClass()) + ".class";
pathEditor.setAsText(fileName);
Object value = pathEditor.getValue();
assertTrue(value instanceof Path);
Path path = (Path) value;
File file = path.toFile();
assertTrue(file.exists());
String absolutePath = file.getAbsolutePath();
if (File.separatorChar == '\\') {
absolutePath = absolutePath.replace('\\', '/');
}
assertTrue(absolutePath.endsWith(fileName));
}
@Test
public void testUnqualifiedPathNameNotFound() throws Exception {
PropertyEditor pathEditor = new PathEditor();
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
ClassUtils.getShortName(getClass()) + ".clazz";
pathEditor.setAsText(fileName);
Object value = pathEditor.getValue();
assertTrue(value instanceof Path);
Path path = (Path) value;
File file = path.toFile();
assertFalse(file.exists());
String absolutePath = file.getAbsolutePath();
if (File.separatorChar == '\\') {
absolutePath = absolutePath.replace('\\', '/');
}
assertTrue(absolutePath.endsWith(fileName));
}
}
@@ -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.
@@ -34,7 +34,7 @@ public class ReaderEditorTests {
@Test(expected = IllegalArgumentException.class)
public void testCtorWithNullResourceEditor() throws Exception {
new InputStreamEditor(null);
new ReaderEditor(null);
}
@Test
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 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,15 +31,6 @@ import static org.junit.Assert.*;
*/
public class URIEditorTests {
private void doTestURI(String uriSpec) {
PropertyEditor uriEditor = new URIEditor();
uriEditor.setAsText(uriSpec);
Object value = uriEditor.getValue();
assertTrue(value instanceof URI);
URI uri = (URI) value;
assertEquals(uriSpec, uri.toString());
}
@Test
public void standardURI() throws Exception {
doTestURI("mailto:juergen.hoeller@interface21.com");
@@ -141,4 +132,14 @@ public class URIEditorTests {
assertEquals("http://example.com/spaces%20and%20%E2%82%AC", uri.toASCIIString());
}
private void doTestURI(String uriSpec) {
PropertyEditor uriEditor = new URIEditor();
uriEditor.setAsText(uriSpec);
Object value = uriEditor.getValue();
assertTrue(value instanceof URI);
URI uri = (URI) value;
assertEquals(uriSpec, uri.toString());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 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,7 +29,12 @@ import static org.junit.Assert.*;
* @author Rick Evans
* @author Chris Beams
*/
public final class URLEditorTests {
public class URLEditorTests {
@Test(expected = IllegalArgumentException.class)
public void testCtorWithNullResourceEditor() throws Exception {
new URLEditor(null);
}
@Test
public void testStandardURI() throws Exception {
@@ -63,7 +68,7 @@ public final class URLEditorTests {
assertTrue(!url.getProtocol().startsWith("classpath"));
}
@Test(expected=IllegalArgumentException.class)
@Test(expected = IllegalArgumentException.class)
public void testWithNonExistentResource() throws Exception {
PropertyEditor urlEditor = new URLEditor();
urlEditor.setAsText("gonna:/freak/in/the/morning/freak/in/the.evening");
@@ -83,9 +88,4 @@ public final class URLEditorTests {
assertEquals("", urlEditor.getAsText());
}
@Test(expected=IllegalArgumentException.class)
public void testCtorWithNullResourceEditor() throws Exception {
new URLEditor(null);
}
}
@@ -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.
@@ -223,7 +223,7 @@ public class TestBean implements BeanNameAware, BeanFactoryAware, ITestBean, IOt
@Override
public ITestBean[] getSpouses() {
return (spouse != null ? new ITestBean[]{spouse} : null);
return (spouse != null ? new ITestBean[] {spouse} : null);
}
public String getTouchy() {
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
@@ -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.
@@ -98,7 +98,7 @@ public class EhCacheCache implements Cache {
try {
value = valueLoader.call();
}
catch (Exception ex) {
catch (Throwable ex) {
throw new ValueRetrievalException(key, valueLoader, ex);
}
put(key, value);
@@ -7,6 +7,6 @@
* <p>Note: EhCache 3.x lives in a different package namespace
* and is not covered by the traditional support classes here.
* Instead, consider using it through JCache (JSR-107), with
* Spring's support in {@link org.springframework.cache.jcache}.
* Spring's support in {@code org.springframework.cache.jcache}.
*/
package org.springframework.cache.ehcache;
@@ -69,7 +69,7 @@ abstract class AbstractCacheInterceptor<O extends AbstractJCacheOperation<A>, A
/**
* Convert the collection of caches in a single expected element.
* <p>Throw an {@link IllegalStateException} if the collection holds more than one element
* @return the singe element or {@code null} if the collection is empty
* @return the single element or {@code null} if the collection is empty
*/
static Cache extractFrom(Collection<? extends Cache> caches) {
if (CollectionUtils.isEmpty(caches)) {
@@ -652,6 +652,8 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe
logger.info("Will start Quartz Scheduler [" + scheduler.getSchedulerName() +
"] in " + startupDelay + " seconds");
}
// Not using the Quartz startDelayed method since we explicitly want a daemon
// thread here, not keeping the JVM alive in case of all other threads ending.
Thread schedulerThread = new Thread() {
@Override
public void run() {
@@ -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.
@@ -43,8 +43,7 @@ import org.springframework.util.Assert;
* @since 3.1
*/
@SuppressWarnings("serial")
public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperationSource
implements Serializable {
public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperationSource implements Serializable {
private final boolean publicMethodsOnly;
@@ -177,6 +176,7 @@ public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperati
return this.annotationParsers.hashCode();
}
/**
* Callback interface providing {@link CacheOperation} instance(s) based on
* a given {@link CacheAnnotationParser}.
@@ -184,10 +184,9 @@ public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperati
protected interface CacheOperationProvider {
/**
* Returns the {@link CacheOperation} instance(s) provided by the specified parser.
*
* Return the {@link CacheOperation} instance(s) provided by the specified parser.
* @param parser the parser to use
* @return the cache operations or {@code null} if none is found
* @return the cache operations, or {@code null} if none found
*/
Collection<CacheOperation> getCacheOperations(CacheAnnotationParser parser);
}
@@ -69,7 +69,9 @@ public @interface CacheEvict {
* following meta-data:
* <ul>
* <li>{@code #result} for a reference to the result of the method invocation, which
* can only be used if {@link #beforeInvocation()} is {@code false}.</li>
* can only be used if {@link #beforeInvocation()} is {@code false}. For supported
* wrappers such as {@code Optional}, {@code #result} refers to the actual object,
* not the wrapper</li>
* <li>{@code #root.method}, {@code #root.target}, and {@code #root.caches} for
* references to the {@link java.lang.reflect.Method method}, target object, and
* affected cache(s) respectively.</li>
@@ -31,7 +31,9 @@ import org.springframework.core.annotation.AliasFor;
*
* <p>In contrast to the {@link Cacheable @Cacheable} annotation, this annotation
* does not cause the advised method to be skipped. Rather, it always causes the
* method to be invoked and its result to be stored in the associated cache.
* method to be invoked and its result to be stored in the associated cache. Note
* that Java8's {@code Optional} return types are automatically handled and its
* content is stored in the cache if present.
*
* <p>This annotation may be used as a <em>meta-annotation</em> to create custom
* <em>composed annotations</em> with attribute overrides.
@@ -73,7 +75,9 @@ public @interface CachePut {
* <p>The SpEL expression evaluates against a dedicated context that provides the
* following meta-data:
* <ul>
* <li>{@code #result} for a reference to the result of the method invocation.</li>
* <li>{@code #result} for a reference to the result of the method invocation. For
* supported wrappers such as {@code Optional}, {@code #result} refers to the actual
* object, not the wrapper</li>
* <li>{@code #root.method}, {@code #root.target}, and {@code #root.caches} for
* references to the {@link java.lang.reflect.Method method}, target object, and
* affected cache(s) respectively.</li>
@@ -138,7 +142,9 @@ public @interface CachePut {
* <p>The SpEL expression evaluates against a dedicated context that provides the
* following meta-data:
* <ul>
* <li>{@code #result} for a reference to the result of the method invocation.</li>
* <li>{@code #result} for a reference to the result of the method invocation. For
* supported wrappers such as {@code Optional}, {@code #result} refers to the actual
* object, not the wrapper</li>
* <li>{@code #root.method}, {@code #root.target}, and {@code #root.caches} for
* references to the {@link java.lang.reflect.Method method}, target object, and
* affected cache(s) respectively.</li>
@@ -38,7 +38,9 @@ import org.springframework.core.annotation.AliasFor;
* replace the default one (see {@link #keyGenerator}).
*
* <p>If no value is found in the cache for the computed key, the target method
* will be invoked and the returned value stored in the associated cache.
* will be invoked and the returned value stored in the associated cache. Note
* that Java8's {@code Optional} return types are automatically handled and its
* content is stored in the cache if present.
*
* <p>This annotation may be used as a <em>meta-annotation</em> to create custom
* <em>composed annotations</em> with attribute overrides.
@@ -144,7 +146,9 @@ public @interface Cacheable {
* <p>The SpEL expression evaluates against a dedicated context that provides the
* following meta-data:
* <ul>
* <li>{@code #result} for a reference to the result of the method invocation.</li>
* <li>{@code #result} for a reference to the result of the method invocation. For
* supported wrappers such as {@code Optional}, {@code #result} refers to the actual
* object, not the wrapper</li>
* <li>{@code #root.method}, {@code #root.target}, and {@code #root.caches} for
* references to the {@link java.lang.reflect.Method method}, target object, and
* affected cache(s) respectively.</li>
@@ -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.
@@ -52,7 +52,7 @@ public class CachingConfigurationSelector extends AdviceModeImportSelector<Enabl
private static final boolean jsr107Present = ClassUtils.isPresent(
"javax.cache.Cache", CachingConfigurationSelector.class.getClassLoader());
private static final boolean jCacheImplPresent = ClassUtils.isPresent(
private static final boolean jcacheImplPresent = ClassUtils.isPresent(
PROXY_JCACHE_CONFIGURATION_CLASS, CachingConfigurationSelector.class.getClassLoader());
@@ -81,7 +81,7 @@ public class CachingConfigurationSelector extends AdviceModeImportSelector<Enabl
List<String> result = new ArrayList<String>();
result.add(AutoProxyRegistrar.class.getName());
result.add(ProxyCachingConfiguration.class.getName());
if (jsr107Present && jCacheImplPresent) {
if (jsr107Present && jcacheImplPresent) {
result.add(PROXY_JCACHE_CONFIGURATION_CLASS);
}
return result.toArray(new String[result.size()]);
@@ -94,7 +94,7 @@ public class CachingConfigurationSelector extends AdviceModeImportSelector<Enabl
private String[] getAspectJImports() {
List<String> result = new ArrayList<String>();
result.add(CACHE_ASPECT_CONFIGURATION_CLASS_NAME);
if (jsr107Present && jCacheImplPresent) {
if (jsr107Present && jcacheImplPresent) {
result.add(JCACHE_ASPECT_CONFIGURATION_CLASS_NAME);
}
return result.toArray(new String[result.size()]);
@@ -62,28 +62,28 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria
protected Collection<CacheOperation> parseCacheAnnotations(DefaultCacheConfig cachingConfig, AnnotatedElement ae) {
Collection<CacheOperation> ops = null;
Collection<Cacheable> cacheables = AnnotatedElementUtils.findAllMergedAnnotations(ae, Cacheable.class);
Collection<Cacheable> cacheables = AnnotatedElementUtils.getAllMergedAnnotations(ae, Cacheable.class);
if (!cacheables.isEmpty()) {
ops = lazyInit(ops);
for (Cacheable cacheable : cacheables) {
ops.add(parseCacheableAnnotation(ae, cachingConfig, cacheable));
}
}
Collection<CacheEvict> evicts = AnnotatedElementUtils.findAllMergedAnnotations(ae, CacheEvict.class);
Collection<CacheEvict> evicts = AnnotatedElementUtils.getAllMergedAnnotations(ae, CacheEvict.class);
if (!evicts.isEmpty()) {
ops = lazyInit(ops);
for (CacheEvict evict : evicts) {
ops.add(parseEvictAnnotation(ae, cachingConfig, evict));
}
}
Collection<CachePut> puts = AnnotatedElementUtils.findAllMergedAnnotations(ae, CachePut.class);
Collection<CachePut> puts = AnnotatedElementUtils.getAllMergedAnnotations(ae, CachePut.class);
if (!puts.isEmpty()) {
ops = lazyInit(ops);
for (CachePut put : puts) {
ops.add(parsePutAnnotation(ae, cachingConfig, put));
}
}
Collection<Caching> cachings = AnnotatedElementUtils.findAllMergedAnnotations(ae, Caching.class);
Collection<Caching> cachings = AnnotatedElementUtils.getAllMergedAnnotations(ae, Caching.class);
if (!cachings.isEmpty()) {
ops = lazyInit(ops);
for (Caching caching : cachings) {

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