mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
386 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1c31c7aa6b | |||
| 7b189d1124 | |||
| bd88bbab4a | |||
| 420f8237c0 | |||
| 897aab9f59 | |||
| a383633630 | |||
| 4a0c2f8879 | |||
| 0e59fc4a15 | |||
| 96b1dc9db4 | |||
| 902938e95f | |||
| 379bc5a8a6 | |||
| cbb90236dc | |||
| 53ed9b282b | |||
| 3d3f8f3219 | |||
| 28a765f32b | |||
| 65655b949f | |||
| c8984d2e30 | |||
| 11330baf77 | |||
| 433b4eff8f | |||
| 2f4453a99c | |||
| 65885d1dfd | |||
| 723f94fd0e | |||
| 2a140addfd | |||
| eb3a3a6de2 | |||
| e12fbd3e2b | |||
| 928f5423af | |||
| 65622bd546 | |||
| 882289b06e | |||
| 12cffc68c8 | |||
| c58f46f056 | |||
| 632c0e7c5e | |||
| 392accd910 | |||
| 8446fd1b26 | |||
| 5f9b2db90b | |||
| 4cef52a86f | |||
| de866a0ff6 | |||
| d684e49462 | |||
| fe1e7f0d6c | |||
| 857faec1f3 | |||
| 5b420e20c7 | |||
| 78c906caaa | |||
| 2ef3a86c4f | |||
| 53cdb9dfeb | |||
| cc238207f9 | |||
| 5330dc48aa | |||
| 4764fa53f0 | |||
| f72c431e8a | |||
| 0dc29cb2d3 | |||
| 5801af9ef5 | |||
| d0393ea109 | |||
| 75c5405d6f | |||
| 3a5af35d37 | |||
| dea5918d66 | |||
| 2136b04b65 | |||
| b4af04ba9d | |||
| f0777d130f | |||
| 1532119787 | |||
| 6c6004a93b | |||
| b90fa49ebc | |||
| bca067abb2 | |||
| 0c6b38b0b5 | |||
| 8800bab8a6 | |||
| ed3cb4217d | |||
| 66aca1e8b3 | |||
| d7f72fbbd4 | |||
| 2676771255 | |||
| 3cf303cabd | |||
| a6d9c90841 | |||
| 0390c2b9fe | |||
| f9736ec3f6 | |||
| 6fe5871e91 | |||
| ecf2d8c5de | |||
| 469e30b507 | |||
| 8a3c56b6d5 | |||
| 680bfbe718 | |||
| d600e35157 | |||
| 101d8381ef | |||
| ae56f3a361 | |||
| de326e5e95 | |||
| 2c2df7f555 | |||
| 2ad2022058 | |||
| 57a503b274 | |||
| 0b8140b50d | |||
| a8ed98255f | |||
| 738d84f75c | |||
| 7f24edc3d5 | |||
| ff4f749adb | |||
| 578e80c1cf | |||
| d9a664a588 | |||
| e9ecf5d716 | |||
| 27be8434f1 | |||
| 3f885d0302 | |||
| 9f9a27a1d8 | |||
| d22a6f9da9 | |||
| 8ccd74b6c8 | |||
| ceb668ac6c | |||
| 68055ba4c9 | |||
| ad5c7aeb31 | |||
| 59d2d35f4a | |||
| 103c1aa82f | |||
| a1e4f4f406 | |||
| fa7472c057 | |||
| bd1b559d47 | |||
| 15df7b11d0 | |||
| 4955a73047 | |||
| 11bb7264a2 | |||
| 853eab8b4c | |||
| 15fe75b1a1 | |||
| dad714710f | |||
| 365737b515 | |||
| 026523d24b | |||
| 2b0655b459 | |||
| f53621a86f | |||
| 42cdfbcd89 | |||
| 9919cc976b | |||
| a45d33a158 | |||
| c0aac20081 | |||
| b0afa0c472 | |||
| 17a1362ed8 | |||
| dd8c18188f | |||
| 159f98728e | |||
| c1f18582e7 | |||
| f8a05da1c9 | |||
| a910ce68ff | |||
| aa216672ae | |||
| 4ddcd35d13 | |||
| 02cc37cc16 | |||
| 03415960ff | |||
| c2707150b1 | |||
| 8ce4037af2 | |||
| 101a5cd8ff | |||
| 8df0403e99 | |||
| 07920fc3df | |||
| 87e327773e | |||
| b28310b051 | |||
| 20d3085dc8 | |||
| 218ee6d24c | |||
| 3f06a92b6b | |||
| 5057c4a69c | |||
| 4cab4a7545 | |||
| 3dbe38e418 | |||
| c5f83686d2 | |||
| 77074c6c87 | |||
| 1e34e2725a | |||
| 7790dedff2 | |||
| 399b388ea5 | |||
| 5af6d917e9 | |||
| ea9eb853fa | |||
| 05360c095c | |||
| 1ed05eceb9 | |||
| 69c4cdf975 | |||
| 3f6cc3f552 | |||
| e21a1c5a61 | |||
| 86906d1b4d | |||
| 6e13cc9eaa | |||
| b25462ddf9 | |||
| e60389283d | |||
| 066b4d542b | |||
| 594596f361 | |||
| bf03d0d56f | |||
| 33252495cf | |||
| a71514222a | |||
| 8464ac90c7 | |||
| ebbf63f4e0 | |||
| e6018afe8b | |||
| b9aeba23ef | |||
| d98da7d240 | |||
| e7c99b2b62 | |||
| 64d6a42dfd | |||
| bf1a95c771 | |||
| f6b56a591c | |||
| 2a19148eed | |||
| 7048f32666 | |||
| b3b5b356d2 | |||
| 7355dff967 | |||
| eb7f8309e2 | |||
| 67ba18f956 | |||
| 12ce250c6c | |||
| e6b0a1d4d7 | |||
| 385298b808 | |||
| 03120b70d0 | |||
| 4d2a398cbc | |||
| 353781021d | |||
| 688dd1a018 | |||
| d34d8764b0 | |||
| 28da6e0d98 | |||
| 4ee6735376 | |||
| ff6abbd369 | |||
| ecda2aee4a | |||
| e2a9bc9c66 | |||
| b5b60cafb7 | |||
| 270fab4fd0 | |||
| f7f0d18e41 | |||
| 386b7507c6 | |||
| 8a1a23af83 | |||
| 580dc8e72a | |||
| 66d2c6698b | |||
| 7f90e3bcf7 | |||
| bc1abe6070 | |||
| 6aa0e62597 | |||
| 52179d8bfb | |||
| ee686188b7 | |||
| 4a98fcb3f7 | |||
| 29ab58c4d8 | |||
| f6d05eaad4 | |||
| 5105793228 | |||
| 689e7b7af2 | |||
| 636e2f0f4c | |||
| 461b488eee | |||
| 6b93f41f3a | |||
| 092241a632 | |||
| 20f4e9023b | |||
| c24bafd644 | |||
| 21b4526063 | |||
| b2ff0b1df0 | |||
| 87d0da2d4c | |||
| ad78b5cdb5 | |||
| de84703c02 | |||
| b67b5ec408 | |||
| 65e88449aa | |||
| 20de98362a | |||
| ea7ff5241d | |||
| ae877e92c7 | |||
| 16305530f2 | |||
| 282de41f06 | |||
| 16eb915c95 | |||
| 0eabef0720 | |||
| 2c9753ad25 | |||
| 81e81ce77c | |||
| 9cecaa769e | |||
| 8c8eca7e05 | |||
| fba8bcc7dc | |||
| fa719ad4c5 | |||
| 63dc53a5ea | |||
| bc7679f9fc | |||
| a6d5d7c8e2 | |||
| 122e4346bb | |||
| c18137d40a | |||
| a827ab88b1 | |||
| 351e72b6e2 | |||
| cbed1c1b4b | |||
| 124837e2c3 | |||
| 753a54096f | |||
| d50881d82b | |||
| f836601e0f | |||
| fbda55f141 | |||
| 10c358718e | |||
| 6f2062fb3a | |||
| f42d4241b4 | |||
| 3576bc4585 | |||
| 47389a0edd | |||
| ab139dffd0 | |||
| a5f3d00977 | |||
| 53b6e1c1b0 | |||
| 65b0a8fcb2 | |||
| 461c200ce6 | |||
| a614430899 | |||
| bc2440ea16 | |||
| 6fb49f1de7 | |||
| 6118d67321 | |||
| cbca6e1acb | |||
| 2c2cf32b8a | |||
| 89755542da | |||
| 051b5f4f4f | |||
| b370969690 | |||
| a1f6eabbce | |||
| 247c46e6ea | |||
| 915ca47cad | |||
| 0d8a020684 | |||
| 1e388a894e | |||
| 4e7752c9ba | |||
| c13e5f9f5b | |||
| 706a09c49e | |||
| c38c09bc35 | |||
| 77bb68b967 | |||
| 212daa1995 | |||
| f7ac7a395c | |||
| 465e84eda4 | |||
| ec577f8e24 | |||
| 26470cc23a | |||
| 296aa96d71 | |||
| a2c3274b8e | |||
| 5e19f2959e | |||
| 5dc59aaa7b | |||
| c9289a4dcf | |||
| 19b4618fb5 | |||
| 4c0744ee54 | |||
| b07d02f1bf | |||
| 69cbadf7e9 | |||
| 0543036ec9 | |||
| 2ff2f0205d | |||
| e22431188b | |||
| b8c0e153e3 | |||
| ff09482653 | |||
| d932c043da | |||
| 0cb7e4dcb3 | |||
| 2e5f1c22f6 | |||
| cf93e7c69e | |||
| 9da980d325 | |||
| 7da13e7ad1 | |||
| a0e40a5610 | |||
| ac5c75690a | |||
| 795a5e02cd | |||
| bb75662a7e | |||
| 23cb161fb3 | |||
| eb1c039a6e | |||
| 4c39f90466 | |||
| d4de1ac346 | |||
| 4880d1d461 | |||
| 5a8aa53232 | |||
| 85b8befbd1 | |||
| 4c4f19ec94 | |||
| 145dcfd0c2 | |||
| 991c982e5b | |||
| 1d6f374970 | |||
| eee72c52da | |||
| b0e3081636 | |||
| 886eb665bf | |||
| 70ee2ee7b1 | |||
| f3f535623f | |||
| 63076d0865 | |||
| fc0a6ce40c | |||
| 88773ae7f1 | |||
| 81b10be1d0 | |||
| 50c5593740 | |||
| af4b22e5b9 | |||
| 6e55c8cd2f | |||
| def90d1016 | |||
| f30b0a86f7 | |||
| 95ad7168bf | |||
| ccb312a974 | |||
| f588ab05fa | |||
| 2dd1134303 | |||
| 0efb9d8023 | |||
| 21fd150894 | |||
| ac9a625ccc | |||
| c31213e5cb | |||
| f82cc6458b | |||
| 8d7df01d73 | |||
| 5303ab68aa | |||
| c91ff130d5 | |||
| 54d0346084 | |||
| 4f926c82bf | |||
| b07b146965 | |||
| cfbc5224e3 | |||
| a0c41a0e03 | |||
| 8fe5151f84 | |||
| 77f8b070cd | |||
| 4f4f3fab7d | |||
| 0444ab236a | |||
| 9ede9fe697 | |||
| 3e98b26b77 | |||
| 0aee6e9f5b | |||
| eddc5b8898 | |||
| 57993d871e | |||
| 3c8a47bd06 | |||
| 7f8c91a52d | |||
| 62f9f477f5 | |||
| 894875ce8d | |||
| 9d1c3fa9ac | |||
| d207c2294d | |||
| e653a9cd03 | |||
| 5675046cb7 | |||
| 20a8039642 | |||
| 4bda92fd8a | |||
| 97adfdd398 | |||
| a5b5df450e | |||
| 80b8fb8b83 | |||
| ef227c5d01 | |||
| 9e5b129ba5 | |||
| 12b30843c5 | |||
| 09f02bc620 | |||
| 3d2611484a | |||
| 6af91773ee | |||
| 9e71af86f8 | |||
| 60ff93e5ac | |||
| f25d2a9416 | |||
| fd4b9cf6a3 | |||
| 1a351db6e0 | |||
| 5b537e9604 | |||
| 6c69f47acf | |||
| 44ef114981 | |||
| 67b342d923 | |||
| 5063c6dd00 | |||
| 8d0bb00188 | |||
| fe59d4a787 |
@@ -0,0 +1,5 @@
|
||||
target
|
||||
integration-repo
|
||||
ivy-cache
|
||||
spring-build
|
||||
jmx.log
|
||||
@@ -3,6 +3,106 @@ SPRING FRAMEWORK CHANGELOG
|
||||
http://www.springsource.org
|
||||
|
||||
|
||||
Changes in version 3.0.3 (2010-06-15)
|
||||
-------------------------------------
|
||||
|
||||
* Spring autodetects JodaTime 1.3 or higher (as required), ignoring older JodaTime versions
|
||||
* clarified that Spring's Jackson support requires Jackson 1.3 or higher
|
||||
* JPA 2.0 support tested and supported with Hibernate 3.5.2 and OpenJPA 2.0.0 GA as well
|
||||
* revised VFS support for Spring's component scanning to work on JBoss AS 6.0.0 M3 as well
|
||||
* fixed URIEditor's URI construction to consider fragment as well
|
||||
* added default InputSourceEditor for SAX InputSource construction with a URL String as system id
|
||||
* CachedIntrospectionResults only caches GenericTypeAwarePropertyDescriptors if fully safe
|
||||
* revised BeanWrapper's exception wrapping to consistently handle ConversionExceptions
|
||||
* DefaultListableBeanFactory checks for alias circle on registerAlias (avoiding endless loop)
|
||||
* ConversionService is able to apply Converters to interface-based array elements
|
||||
* ConversionService fully supports conversion from String to MediaType now (through 'valueOf')
|
||||
* revised exception handling in ObjectToObjectConverter, avoiding InvocationTargetExceptions
|
||||
* a context ConversionService is able to override an ApplicationContext's resource editors
|
||||
* refined LifecycleProcessor exception handling, properly wrapping a start exception from a bean
|
||||
* revised DefaultLifecycleProcessor's handling of circular dependencies to avoid stack overflow
|
||||
* fixed constructor argument caching for prototypes with multiple constructor matches
|
||||
* specific detection of CGLIB subclasses in order to properly handle CGLIB interfaces
|
||||
* registerDependentBean resolves to the canonical bean name in order to handle alias references
|
||||
* fixed registerResolvableDependency mechanism to correctly handle non-serializable factory objects
|
||||
* added "expose-proxy" attribute to aop namespace (enforcing AopContext proxy exposure with CGLIB)
|
||||
* revised AbstractInterceptorDrivenBeanDefinitionDecorator for further alignment with auto-proxying
|
||||
* BeanDefinitionVisitor/PropertyPlaceholderConfigurer finds and resolves values in arrays as well
|
||||
* property placeholders can deal with nested expressions which happen to use the same suffix
|
||||
* SpEL's Elvis operator is able to deal with #{${myProp}?:defaultValue} case if myProp is empty
|
||||
* introduced EmbeddedValueResolverAware callback interface for convenient placeholder resolution
|
||||
* @Transactional qualifier value matches against @Qualifier annotations on @Bean methods as well
|
||||
* setTransactionIsolation on JDBC Connection only called when actually necessary (for PostgreSQL)
|
||||
* added limit for parsed SQL cache to NamedParameterJdbcTemplate (default is 256; configurable)
|
||||
* CachingConnectionFactory detects destination equality for WebSphere MQ as well (using toString)
|
||||
* DefaultPersistenceUnitManager's getPersistenceUnitInfo method has 2.5 compatible signature again
|
||||
* DefaultMessageListenerContainer reacts to maxConcurrentConsumers reduction for long-lived tasks
|
||||
* added "idleConsumerLimit" bean property to DefaultMessageListenerContainer (default is 1)
|
||||
* AsyncAnnotationBeanPostProcessor consistently adds @Async processing as first Advisor in the chain
|
||||
* ScheduledTaskRegistrar (as used for @Scheduled processing) properly shuts down its default executor
|
||||
* CronTrigger defensively protects itself against accidental re-fires if a task runs too early
|
||||
* MailSendException includes all messages as failed messages in case of a connect failure
|
||||
* added support for JAX-WS 2.1 WebServiceFeatures to JaxWsPortClientInterceptor/PortProxyFactoryBean
|
||||
* added XmlAwareFormHttpMessageConverter, taking over the 3.0.2-introduced XML multipart support
|
||||
* ServletContextResourcePatternResolver handles "/WEB-INF/lib/*.jar!/**/context.xml" style patterns
|
||||
* fixed MVC mapping regression for servlet url-pattern "/" case on servers other than WebSphere
|
||||
* MVC mappings properly apply even to welcome file entries that forward to a DispatcherServlet
|
||||
* fixed @ExceptionHandler resolution in case of multiple matches at different inheritance levels
|
||||
* revised Portlet SessionStatus.setComplete() to avoid re-exposure of attributes in render phase
|
||||
* shortened Portlet MVC's implicit model render parameter name to "implicitModel"
|
||||
* added convenient "checkRefresh" bean property to TilesConfigurer
|
||||
* TilesConfigurer's "definitionsFactoryClass" property applies common Tiles DefinitionsFactory setup
|
||||
* JSP FormTag calculates proper default form action even when using a rewrite filter on WebSphere
|
||||
* JSP HiddenInputTag allows for using common HTML attributes (equivalent to LabelTag)
|
||||
* fixed JSP ErrorsTag to avoid invalid "*.errors" id, using form object name as id prefix instead
|
||||
* fixed JSP SelectTag's support for rendering enum constants
|
||||
* JSP Radiobutton/CheckboxesTag utilizes PropertyEditor/ConversionService for label rendering
|
||||
* MockHttpServletResponse supports multiple includes
|
||||
|
||||
|
||||
Changes in version 3.0.2 (2010-04-02)
|
||||
-------------------------------------
|
||||
|
||||
* fixed cross-module version ranges in OSGi manifests
|
||||
* fixed contents of org.springframework.web.struts jar
|
||||
* upgraded to Hibernate Validator 4.0.2 and Jackson 1.4.2
|
||||
* compatibility with Hibernate 3.5 final (native and also as a JPA 2.0 provider)
|
||||
* compatibility with OpenJPA 2.0 (support for JPA 2.0 persistence.xml versioning)
|
||||
* compatibility with Hessian 4.0 (in terms of exception propagation)
|
||||
* compatibility with JasperReports 3.x (in terms of resource management)
|
||||
* restored full compatibility with Servlet 2.4 containers on all VMs
|
||||
* PropertyEditor lookup fallback works on Google App Engine as well
|
||||
* fixed TypeDescriptor/MethodParameter toString for all cases in debug log messages
|
||||
* widened AbstractFactoryBean's "getObjectType" signature to return any Class as well
|
||||
* BeanPostProcessors are allowed to return a null bean value in the middle of the chain
|
||||
* autowire="byType" ignores parameter name when choosing a primary bean, as defined
|
||||
* ObjectFactoryCreatingFactoryBean creates a serializable ObjectFactory reference
|
||||
* added ProviderCreatingFactoryBean, exposing a serializable JSR-330 Provider reference
|
||||
* "conversionService" bean will be ignored if it is not of type ConversionService
|
||||
* revised AbstractInterceptorDrivenBeanDefinitionDecorator for alignment with auto-proxying
|
||||
* SimpleJdbcCall's "returningResultSet" accepts any plain RowMapper now
|
||||
* added public "validateDatabaseSchema" method to Hibernate LocalSessionFactoryBean
|
||||
* HibernateJpaDialect borrows JDBC Connection on demand (supporting aggressive release)
|
||||
* JCA listener containers delegate to wrapped Transaction handle (for Geronimo compatibility)
|
||||
* @Transactional qualifiers work in unit tests as well (TransactionalTestExecutionListener)
|
||||
* @Value processing works in test instances (using the test context framework) as well now
|
||||
* @DirtiesContext is now inherited for class-level usage
|
||||
* NativeWebRequest detects native MultipartRequest when decorated by HiddenHttpMethodFilter
|
||||
* WebRequestInterceptor exposes HttpServletResponse through NativeWebRequest (after downcast)
|
||||
* WebContentInterceptor does not restrict HTTP methods by default anymore
|
||||
* WebApplicationObjectSupport's initServletContext will be called only once in any scenario
|
||||
* DispatcherPortlet passes handler instance into HandlerExceptionResolver for action exception
|
||||
* DispatcherPortlet applies preHandleRender callbacks in case of action exception as well
|
||||
* UrlPathHelper cuts off trailing servlet-path slashes for root mappings (on WebSphere)
|
||||
* introduced support for HttpEntity and ResponseEntity wrappers, adding context to body values
|
||||
* fixed DataBinder's conversion error handling for direct field access with ConversionService
|
||||
* @InitBinder methods support all applicable Spring 3.0 parameter annotations as well
|
||||
* fixed @RequestParam(required=false) regression for @InitBinder methods
|
||||
* @ExceptionHandler methods consistently receive original exception
|
||||
* fixed indexed property binding regression in form tag library
|
||||
* fixed @Configurable issue with null bean name
|
||||
|
||||
|
||||
Changes in version 3.0.1 (2010-02-18)
|
||||
-------------------------------------
|
||||
|
||||
@@ -12,7 +112,7 @@ Changes in version 3.0.1 (2010-02-18)
|
||||
* support for Hibernate 3.5 (as native Hibernate API and as JPA 2.0 provider)
|
||||
* support for Tiles 2.2.1 (preserving compatibility with Tiles 2.1.2 and above)
|
||||
* consistent treatment of unresolvable placeholders for Resource and Resource array properties
|
||||
* ConversionFailedException exposes offending value through public "getValue()" method
|
||||
* ConversionFailedException exDLBFposes offending value through public "getValue()" method
|
||||
* fixed BeanFactory's "getBeansWithAnnotation" to ignore beans with non-determinable type
|
||||
* widened FactoryBean's "getObjectType" signature to return any Class (Class<?>)
|
||||
* do not ever consider Object as a candidate type for autowiring by type (autowire="byType")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
SPRING FRAMEWORK 3.0 (December 2009)
|
||||
------------------------------------
|
||||
SPRING FRAMEWORK 3.0.3 (June 2010)
|
||||
----------------------------------
|
||||
http://www.springframework.org
|
||||
|
||||
1. INTRODUCTION
|
||||
|
||||
+9
-2
@@ -1,5 +1,12 @@
|
||||
version=3.0.1
|
||||
release.type=integration
|
||||
version=3.0.3
|
||||
# osgi ranges
|
||||
spring.osgi.range.nq=${version:[=.=.=, =.=.+1)}
|
||||
spring.osgi.range="${spring.osgi.range.nq}"
|
||||
aj.osgi.range="[1.5.4, 2.0.0)"
|
||||
|
||||
#
|
||||
release.type=release
|
||||
build.stamp=RELEASE
|
||||
natural.name=spring-framework
|
||||
project.name=Spring Framework
|
||||
project.key=SPR
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src/main/java"/>
|
||||
<classpathentry kind="src" path="src/main/resources"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-1.0.0.jar" sourcepath="/IVY_CACHE/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-sources-1.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-sources-1.1.1.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.easymock/com.springsource.org.easymock/2.5.1/com.springsource.org.easymock-2.5.1.jar" sourcepath="/IVY_CACHE/org.easymock/com.springsource.org.easymock/2.5.1/com.springsource.org.easymock-sources-2.5.1.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/com.jamonapi/com.springsource.com.jamonapi/2.4.0/com.springsource.com.jamonapi-2.4.0.jar" sourcepath="/IVY_CACHE/com.jamonapi/com.springsource.com.jamonapi/2.4.0/com.springsource.com.jamonapi-sources-2.4.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.2.0/com.springsource.net.sf.cglib-2.2.0.jar" sourcepath="/IVY_CACHE/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.1.3/com.springsource.net.sf.cglib-sources-2.1.3.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.jar" sourcepath="/IVY_CACHE/org.apache.log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-sources-1.2.15.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-4.7.0.jar" sourcepath="/IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-sources-4.7.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.pool/1.3.0/com.springsource.org.apache.commons.pool-1.3.0.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.pool/1.3.0/com.springsource.org.apache.commons.pool-sources-1.3.0.jar"/>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src/main/java"/>
|
||||
<classpathentry kind="src" path="src/main/resources"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-1.0.0.jar" sourcepath="/IVY_CACHE/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-sources-1.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-sources-1.1.1.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.easymock/com.springsource.org.easymock/2.5.1/com.springsource.org.easymock-2.5.1.jar" sourcepath="/IVY_CACHE/org.easymock/com.springsource.org.easymock/2.5.1/com.springsource.org.easymock-sources-2.5.1.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/com.jamonapi/com.springsource.com.jamonapi/2.4.0/com.springsource.com.jamonapi-2.4.0.jar" sourcepath="/IVY_CACHE/com.jamonapi/com.springsource.com.jamonapi/2.4.0/com.springsource.com.jamonapi-sources-2.4.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.2.0/com.springsource.net.sf.cglib-2.2.0.jar" sourcepath="/IVY_CACHE/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.1.3/com.springsource.net.sf.cglib-sources-2.1.3.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.jar" sourcepath="/IVY_CACHE/org.apache.log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-sources-1.2.15.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-4.7.0.jar" sourcepath="/IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-sources-4.7.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.pool/1.3.0/com.springsource.org.apache.commons.pool-1.3.0.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.pool/1.3.0/com.springsource.org.apache.commons.pool-sources-1.3.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.aspectj/com.springsource.org.aspectj.weaver/1.6.8.RELEASE/com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar" sourcepath="IVY_CACHE/org.aspectj/com.springsource.org.aspectj.weaver/1.6.8.RELEASE/com.springsource.org.aspectj.weaver-sources-1.6.8.RELEASE.jar"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.beans"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.core"/>
|
||||
<classpathentry kind="lib" path="/org.springframework.asm/target/artifacts/org.springframework.asm.jar" sourcepath="/org.springframework.asm/target/artifacts/org.springframework.asm-sources.jar"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.beans"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.core"/>
|
||||
<classpathentry kind="lib" path="/org.springframework.asm/target/artifacts/org.springframework.asm.jar" sourcepath="/org.springframework.asm/target/artifacts/org.springframework.asm-sources.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.1.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.3.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.1.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.3.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -34,6 +34,6 @@ public interface TargetClassAware {
|
||||
* (typically a proxy configuration or an actual proxy).
|
||||
* @return the target Class, or <code>null</code> if not known
|
||||
*/
|
||||
Class getTargetClass();
|
||||
Class<?> getTargetClass();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*<
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2010 the original author 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 @@ public interface TargetSource extends TargetClassAware {
|
||||
* target class.
|
||||
* @return the type of targets returned by this {@link TargetSource}
|
||||
*/
|
||||
Class getTargetClass();
|
||||
Class<?> getTargetClass();
|
||||
|
||||
/**
|
||||
* Will all calls to {@link #getTarget()} return the same object?
|
||||
|
||||
+4
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.aop.aspectj;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -139,9 +140,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
|
||||
private boolean argumentsIntrospected = false;
|
||||
|
||||
// The actual type is java.lang.reflect.Type,
|
||||
// but for JDK 1.4 compatibility we use Object as the static type.
|
||||
private Object discoveredReturningGenericType;
|
||||
private Type discoveredReturningGenericType;
|
||||
// Note: Unlike return type, no such generic information is needed for the throwing type,
|
||||
// since Java doesn't allow exception types to be parameterized.
|
||||
|
||||
@@ -295,7 +294,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
return this.discoveredReturningType;
|
||||
}
|
||||
|
||||
protected Object getDiscoveredReturningGenericType() {
|
||||
protected Type getDiscoveredReturningGenericType() {
|
||||
return this.discoveredReturningGenericType;
|
||||
}
|
||||
|
||||
|
||||
+4
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -69,21 +69,11 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice implement
|
||||
*/
|
||||
private boolean shouldInvokeOnReturnValueOf(Method method, Object returnValue) {
|
||||
Class type = getDiscoveredReturningType();
|
||||
Object genericType = getDiscoveredReturningGenericType();
|
||||
Type genericType = getDiscoveredReturningGenericType();
|
||||
// If we aren't dealing with a raw type, check if generic parameters are assignable.
|
||||
return (ClassUtils.isAssignableValue(type, returnValue) &&
|
||||
(genericType == null || genericType == type || GenericTypeMatcher.isAssignable(genericType, method)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner class to avoid a static JDK 1.5 dependency for generic type matching.
|
||||
*/
|
||||
private static class GenericTypeMatcher {
|
||||
|
||||
public static boolean isAssignable(Object genericType, Method method) {
|
||||
return TypeUtils.isAssignable((Type) genericType, method.getGenericReturnType());
|
||||
}
|
||||
(genericType == null || genericType == type ||
|
||||
TypeUtils.isAssignable(genericType, method.getGenericReturnType())));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -73,7 +73,7 @@ class RuntimeTestWalker {
|
||||
catch (IllegalAccessException illegalAccessEx) {
|
||||
// Famous last words... but I don't see how this can happen given the
|
||||
// makeAccessible call above
|
||||
throw new IllegalStateException("Unable to access ShadowMatchImpl.runtimeTest field.");
|
||||
throw new IllegalStateException("Unable to access ShadowMatchImpl.residualTest field");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,15 +83,18 @@ class RuntimeTestWalker {
|
||||
* then it tests subtype sensitive vars.
|
||||
*/
|
||||
public boolean testsSubtypeSensitiveVars() {
|
||||
return new SubtypeSensitiveVarTypeTestVisitor().testsSubtypeSensitiveVars(this.runtimeTest);
|
||||
return (this.runtimeTest != null &&
|
||||
new SubtypeSensitiveVarTypeTestVisitor().testsSubtypeSensitiveVars(this.runtimeTest));
|
||||
}
|
||||
|
||||
public boolean testThisInstanceOfResidue(Class thisClass) {
|
||||
return new ThisInstanceOfResidueTestVisitor(thisClass).thisInstanceOfMatches(this.runtimeTest);
|
||||
return (this.runtimeTest != null &&
|
||||
new ThisInstanceOfResidueTestVisitor(thisClass).thisInstanceOfMatches(this.runtimeTest));
|
||||
}
|
||||
|
||||
public boolean testTargetInstanceOfResidue(Class targetClass) {
|
||||
return new TargetInstanceOfResidueTestVisitor(targetClass).targetInstanceOfMatches(this.runtimeTest);
|
||||
return (this.runtimeTest != null &&
|
||||
new TargetInstanceOfResidueTestVisitor(targetClass).targetInstanceOfMatches(this.runtimeTest));
|
||||
}
|
||||
|
||||
|
||||
@@ -139,8 +142,7 @@ class RuntimeTestWalker {
|
||||
try {
|
||||
Field varTypeField = ReflectionVar.class.getDeclaredField("varType");
|
||||
ReflectionUtils.makeAccessible(varTypeField);
|
||||
Integer varTypeValue = (Integer) varTypeField.get(v);
|
||||
return varTypeValue.intValue();
|
||||
return (Integer) varTypeField.get(v);
|
||||
}
|
||||
catch (NoSuchFieldException noSuchFieldEx) {
|
||||
throw new IllegalStateException("the version of aspectjtools.jar / aspectjweaver.jar " +
|
||||
@@ -150,7 +152,7 @@ class RuntimeTestWalker {
|
||||
catch (IllegalAccessException illegalAccessEx) {
|
||||
// Famous last words... but I don't see how this can happen given the
|
||||
// makeAccessible call above
|
||||
throw new IllegalStateException("Unable to access ReflectionVar.varType field.");
|
||||
throw new IllegalStateException("Unable to access ReflectionVar.varType field");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+31
-28
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -215,9 +215,10 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
*/
|
||||
protected static class AspectJAnnotation<A extends Annotation> {
|
||||
|
||||
private static Map<Class,AspectJAnnotationType> annotationTypes = new HashMap<Class,AspectJAnnotationType>();
|
||||
private static final String[] EXPRESSION_PROPERTIES = new String[] {"value", "pointcut"};
|
||||
|
||||
private static final String[] EXPRESSION_PROPERTIES = new String[]{"value", "pointcut"};
|
||||
private static Map<Class, AspectJAnnotationType> annotationTypes =
|
||||
new HashMap<Class, AspectJAnnotationType>();
|
||||
|
||||
static {
|
||||
annotationTypes.put(Pointcut.class,AspectJAnnotationType.AtPointcut);
|
||||
@@ -229,46 +230,48 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
}
|
||||
|
||||
private final A annotation;
|
||||
private AspectJAnnotationType annotationType;
|
||||
private final String expression;
|
||||
private final String argNames;
|
||||
|
||||
public AspectJAnnotation(A aspectjAnnotation) {
|
||||
this.annotation = aspectjAnnotation;
|
||||
for (Class type : annotationTypes.keySet()) {
|
||||
if (type.isInstance(this.annotation)) {
|
||||
this.annotationType = annotationTypes.get(type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (this.annotationType == null) {
|
||||
throw new IllegalStateException("Unknown annotation type: " + this.annotation.toString());
|
||||
}
|
||||
private final AspectJAnnotationType annotationType;
|
||||
|
||||
private final String pointcutExpression;
|
||||
|
||||
private final String argumentNames;
|
||||
|
||||
public AspectJAnnotation(A annotation) {
|
||||
this.annotation = annotation;
|
||||
this.annotationType = determineAnnotationType(annotation);
|
||||
// We know these methods exist with the same name on each object,
|
||||
// but need to invoke them reflectively as there isn't a common interface.
|
||||
try {
|
||||
this.expression = resolveExpression();
|
||||
this.argNames = (String)
|
||||
this.annotation.getClass().getMethod("argNames", (Class[]) null).invoke(this.annotation);
|
||||
this.pointcutExpression = resolveExpression(annotation);
|
||||
this.argumentNames = (String) annotation.getClass().getMethod("argNames").invoke(annotation);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalArgumentException(aspectjAnnotation + " cannot be an AspectJ annotation", ex);
|
||||
throw new IllegalArgumentException(annotation + " cannot be an AspectJ annotation", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveExpression() throws Exception {
|
||||
private AspectJAnnotationType determineAnnotationType(A annotation) {
|
||||
for (Class type : annotationTypes.keySet()) {
|
||||
if (type.isInstance(annotation)) {
|
||||
return annotationTypes.get(type);
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("Unknown annotation type: " + annotation.toString());
|
||||
}
|
||||
|
||||
private String resolveExpression(A annotation) throws Exception {
|
||||
String expression = null;
|
||||
for (String methodName : EXPRESSION_PROPERTIES) {
|
||||
Method method;
|
||||
try {
|
||||
method = this.annotation.getClass().getDeclaredMethod(methodName);
|
||||
method = annotation.getClass().getDeclaredMethod(methodName);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
method = null;
|
||||
}
|
||||
if (method != null) {
|
||||
String candidate = (String) method.invoke(this.annotation);
|
||||
String candidate = (String) method.invoke(annotation);
|
||||
if (StringUtils.hasText(candidate)) {
|
||||
expression = candidate;
|
||||
}
|
||||
@@ -286,11 +289,11 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
}
|
||||
|
||||
public String getPointcutExpression() {
|
||||
return this.expression;
|
||||
return this.pointcutExpression;
|
||||
}
|
||||
|
||||
public String getArgNames() {
|
||||
return this.argNames;
|
||||
public String getArgumentNames() {
|
||||
return this.argumentNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -314,7 +317,7 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
if (annotation == null) {
|
||||
return null;
|
||||
}
|
||||
StringTokenizer strTok = new StringTokenizer(annotation.getArgNames(), ",");
|
||||
StringTokenizer strTok = new StringTokenizer(annotation.getArgumentNames(), ",");
|
||||
if (strTok.countTokens() > 0) {
|
||||
String[] names = new String[strTok.countTokens()];
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
|
||||
+5
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -58,18 +58,13 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
|
||||
private String aspectName;
|
||||
|
||||
private Boolean isBeforeAdvice = null;
|
||||
private Boolean isBeforeAdvice;
|
||||
|
||||
private Boolean isAfterAdvice = null;
|
||||
private Boolean isAfterAdvice;
|
||||
|
||||
|
||||
public InstantiationModelAwarePointcutAdvisorImpl(
|
||||
AspectJAdvisorFactory af,
|
||||
AspectJExpressionPointcut ajexp,
|
||||
MetadataAwareAspectInstanceFactory aif,
|
||||
Method method,
|
||||
int declarationOrderInAspect,
|
||||
String aspectName) {
|
||||
public InstantiationModelAwarePointcutAdvisorImpl(AspectJAdvisorFactory af, AspectJExpressionPointcut ajexp,
|
||||
MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect, String aspectName) {
|
||||
|
||||
this.declaredPointcut = ajexp;
|
||||
this.method = method;
|
||||
|
||||
+20
-14
@@ -21,9 +21,9 @@ import java.util.List;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactoryBean;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
@@ -63,33 +63,38 @@ public abstract class AbstractInterceptorDrivenBeanDefinitionDecorator implement
|
||||
|
||||
// get the root bean name - will be the name of the generated proxy factory bean
|
||||
String existingBeanName = definitionHolder.getBeanName();
|
||||
BeanDefinition existingDefinition = definitionHolder.getBeanDefinition();
|
||||
BeanDefinition targetDefinition = definitionHolder.getBeanDefinition();
|
||||
BeanDefinitionHolder targetHolder = new BeanDefinitionHolder(targetDefinition, existingBeanName + ".TARGET");
|
||||
|
||||
// delegate to subclass for interceptor definition
|
||||
BeanDefinition interceptorDefinition = createInterceptorDefinition(node);
|
||||
|
||||
// generate name and register the interceptor
|
||||
String interceptorName = existingBeanName + "." + getInterceptorNameSuffix(interceptorDefinition);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(new BeanDefinitionHolder(interceptorDefinition, interceptorName), registry);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(
|
||||
new BeanDefinitionHolder(interceptorDefinition, interceptorName), registry);
|
||||
|
||||
BeanDefinitionHolder result = definitionHolder;
|
||||
|
||||
if (!isProxyFactoryBeanDefinition(existingDefinition)) {
|
||||
if (!isProxyFactoryBeanDefinition(targetDefinition)) {
|
||||
// create the proxy definition
|
||||
RootBeanDefinition proxyDefinition = new RootBeanDefinition();
|
||||
// create proxy factory bean definition
|
||||
proxyDefinition.setBeanClass(ProxyFactoryBean.class);
|
||||
|
||||
// set up property values
|
||||
MutablePropertyValues mpvs = new MutablePropertyValues();
|
||||
proxyDefinition.setPropertyValues(mpvs);
|
||||
|
||||
proxyDefinition.setScope(targetDefinition.getScope());
|
||||
proxyDefinition.setLazyInit(targetDefinition.isLazyInit());
|
||||
// set the target
|
||||
mpvs.add("target", existingDefinition);
|
||||
|
||||
proxyDefinition.setDecoratedDefinition(targetHolder);
|
||||
proxyDefinition.getPropertyValues().add("target", targetHolder);
|
||||
// create the interceptor names list
|
||||
mpvs.add("interceptorNames", new ManagedList<String>());
|
||||
|
||||
proxyDefinition.getPropertyValues().add("interceptorNames", new ManagedList<String>());
|
||||
// copy autowire settings from original bean definition.
|
||||
proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
|
||||
proxyDefinition.setPrimary(targetDefinition.isPrimary());
|
||||
if (targetDefinition instanceof AbstractBeanDefinition) {
|
||||
proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
|
||||
}
|
||||
// wrap it in a BeanDefinitionHolder with bean name
|
||||
result = new BeanDefinitionHolder(proxyDefinition, existingBeanName);
|
||||
}
|
||||
|
||||
@@ -99,7 +104,8 @@ public abstract class AbstractInterceptorDrivenBeanDefinitionDecorator implement
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void addInterceptorNameToList(String interceptorName, BeanDefinition beanDefinition) {
|
||||
List<String> list = (List<String>) beanDefinition.getPropertyValues().getPropertyValue("interceptorNames").getValue();
|
||||
List<String> list = (List<String>)
|
||||
beanDefinition.getPropertyValues().getPropertyValue("interceptorNames").getValue();
|
||||
list.add(interceptorName);
|
||||
}
|
||||
|
||||
|
||||
+8
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -97,6 +97,13 @@ public abstract class AopConfigUtils {
|
||||
}
|
||||
}
|
||||
|
||||
static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
|
||||
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
|
||||
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
|
||||
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static BeanDefinition registerOrEscalateApcAsRequired(Class cls, BeanDefinitionRegistry registry, Object source) {
|
||||
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
|
||||
|
||||
+10
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,6 +46,11 @@ public abstract class AopNamespaceUtils {
|
||||
*/
|
||||
public static final String PROXY_TARGET_CLASS_ATTRIBUTE = "proxy-target-class";
|
||||
|
||||
/**
|
||||
* The <code>expose-proxy</code> attribute as found on AOP-related XML tags.
|
||||
*/
|
||||
private static final String EXPOSE_PROXY_ATTRIBUTE = "expose-proxy";
|
||||
|
||||
|
||||
public static void registerAutoProxyCreatorIfNecessary(
|
||||
ParserContext parserContext, Element sourceElement) {
|
||||
@@ -102,6 +107,10 @@ public abstract class AopNamespaceUtils {
|
||||
if (proxyTargetClass) {
|
||||
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
|
||||
}
|
||||
boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
|
||||
if (exposeProxy) {
|
||||
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-14
@@ -102,20 +102,17 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
configureAutoProxyCreator(parserContext, element);
|
||||
|
||||
NodeList childNodes = element.getChildNodes();
|
||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||
Node node = childNodes.item(i);
|
||||
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
||||
String localName = parserContext.getDelegate().getLocalName(node);
|
||||
if (POINTCUT.equals(localName)) {
|
||||
parsePointcut((Element) node, parserContext);
|
||||
}
|
||||
else if (ADVISOR.equals(localName)) {
|
||||
parseAdvisor((Element) node, parserContext);
|
||||
}
|
||||
else if (ASPECT.equals(localName)) {
|
||||
parseAspect((Element) node, parserContext);
|
||||
}
|
||||
List<Element> childElts = DomUtils.getChildElements(element);
|
||||
for (Element elt: childElts) {
|
||||
String localName = parserContext.getDelegate().getLocalName(elt);
|
||||
if (POINTCUT.equals(localName)) {
|
||||
parsePointcut(elt, parserContext);
|
||||
}
|
||||
else if (ADVISOR.equals(localName)) {
|
||||
parseAdvisor(elt, parserContext);
|
||||
}
|
||||
else if (ASPECT.equals(localName)) {
|
||||
parseAspect(elt, parserContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -162,7 +162,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
this.targetSource = EmptyTargetSource.forClass(targetClass);
|
||||
}
|
||||
|
||||
public Class getTargetClass() {
|
||||
public Class<?> getTargetClass() {
|
||||
return this.targetSource.getTargetClass();
|
||||
}
|
||||
|
||||
|
||||
+32
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,9 @@ package org.springframework.aop.framework;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.aop.SpringProxy;
|
||||
import org.springframework.aop.TargetClassAware;
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.target.SingletonTargetSource;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -34,6 +37,34 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public abstract class AopProxyUtils {
|
||||
|
||||
/**
|
||||
* Determine the ultimate target class of the given bean instance, traversing
|
||||
* not only a top-level proxy but any number of nested proxies as well -
|
||||
* as long as possible without side effects, that is, just for singleton targets.
|
||||
* @param candidate the instance to check (might be an AOP proxy)
|
||||
* @return the target class (or the plain class of the given object as fallback;
|
||||
* never <code>null</code>)
|
||||
* @see org.springframework.aop.TargetClassAware#getTargetClass()
|
||||
* @see org.springframework.aop.framework.Advised#getTargetSource()
|
||||
*/
|
||||
public static Class<?> ultimateTargetClass(Object candidate) {
|
||||
Assert.notNull(candidate, "Candidate object must not be null");
|
||||
Object current = candidate;
|
||||
Class<?> result = null;
|
||||
while (current instanceof TargetClassAware) {
|
||||
result = ((TargetClassAware) current).getTargetClass();
|
||||
Object nested = null;
|
||||
if (current instanceof Advised) {
|
||||
TargetSource targetSource = ((Advised) current).getTargetSource();
|
||||
if (targetSource instanceof SingletonTargetSource) {
|
||||
nested = ((SingletonTargetSource) targetSource).getTarget();
|
||||
}
|
||||
}
|
||||
current = nested;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the complete set of interfaces to proxy for the given AOP configuration.
|
||||
* <p>This will always add the {@link Advised} interface unless the AdvisedSupport's
|
||||
|
||||
+5
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -268,7 +268,7 @@ final class Cglib2AopProxy implements AopProxy, Serializable {
|
||||
|
||||
// Choose a "straight to target" interceptor. (used for calls that are
|
||||
// unadvised but can return this). May be required to expose the proxy.
|
||||
Callback targetInterceptor = null;
|
||||
Callback targetInterceptor;
|
||||
if (exposeProxy) {
|
||||
targetInterceptor = isStatic ?
|
||||
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
|
||||
@@ -316,12 +316,8 @@ final class Cglib2AopProxy implements AopProxy, Serializable {
|
||||
// Now copy both the callbacks from mainCallbacks
|
||||
// and fixedCallbacks into the callbacks array.
|
||||
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
|
||||
for (int x = 0; x < mainCallbacks.length; x++) {
|
||||
callbacks[x] = mainCallbacks[x];
|
||||
}
|
||||
for (int x = 0; x < fixedCallbacks.length; x++) {
|
||||
callbacks[x + mainCallbacks.length] = fixedCallbacks[x];
|
||||
}
|
||||
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
|
||||
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
|
||||
this.fixedInterceptorOffset = mainCallbacks.length;
|
||||
}
|
||||
else {
|
||||
@@ -610,7 +606,7 @@ final class Cglib2AopProxy implements AopProxy, Serializable {
|
||||
targetClass = target.getClass();
|
||||
}
|
||||
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
|
||||
Object retVal = null;
|
||||
Object retVal;
|
||||
// Check whether we only have one InvokerInterceptor: that is,
|
||||
// no real advice, but just reflective invocation of the target.
|
||||
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -146,7 +146,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
* unless a hook method throws an exception.
|
||||
*/
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
MethodInvocation invocation = null;
|
||||
MethodInvocation invocation;
|
||||
Object oldProxy = null;
|
||||
boolean setProxyContext = false;
|
||||
|
||||
@@ -169,7 +169,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
|
||||
}
|
||||
|
||||
Object retVal = null;
|
||||
Object retVal;
|
||||
|
||||
if (this.advised.exposeProxy) {
|
||||
// Make invocation available if necessary.
|
||||
@@ -239,7 +239,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
return false;
|
||||
}
|
||||
|
||||
JdkDynamicAopProxy otherProxy = null;
|
||||
JdkDynamicAopProxy otherProxy;
|
||||
if (other instanceof JdkDynamicAopProxy) {
|
||||
otherProxy = (JdkDynamicAopProxy) other;
|
||||
}
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -113,12 +113,14 @@ public class ProxyConfig implements Serializable {
|
||||
* ThreadLocal for retrieval via the AopContext class. This is useful
|
||||
* if an advised object needs to call another advised method on itself.
|
||||
* (If it uses <code>this</code>, the invocation will not be advised).
|
||||
* <p>Default is "false", for optimal performance.
|
||||
* <p>Default is "false", in order to avoid unnecessary extra interception.
|
||||
* This means that no guarantees are provided that AopContext access will
|
||||
* work consistently within any method of the advised object.
|
||||
*/
|
||||
public void setExposeProxy(boolean exposeProxy) {
|
||||
this.exposeProxy = exposeProxy;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return whether the AOP proxy will expose the AOP proxy for
|
||||
* each invocation.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2010 the original author 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 abstract class AutoProxyUtils {
|
||||
* @return whether the given bean should be proxied with its target class
|
||||
*/
|
||||
public static boolean shouldProxyTargetClass(ConfigurableListableBeanFactory beanFactory, String beanName) {
|
||||
if (beanFactory.containsBeanDefinition(beanName)) {
|
||||
if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
|
||||
BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
|
||||
return Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE));
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2010 the original author 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,7 +45,7 @@ public abstract class ExposeBeanNameAdvisors {
|
||||
* Binding for the bean name of the bean which is currently being invoked
|
||||
* in the ReflectiveMethodInvocation userAttributes Map.
|
||||
*/
|
||||
private static final String BEAN_NAME_ATTRIBUTE = ExposeBeanNameAdvisors.class.getName() + ".beanName";
|
||||
private static final String BEAN_NAME_ATTRIBUTE = ExposeBeanNameAdvisors.class.getName() + ".BEAN_NAME";
|
||||
|
||||
|
||||
/**
|
||||
@@ -114,7 +114,7 @@ public abstract class ExposeBeanNameAdvisors {
|
||||
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
|
||||
}
|
||||
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
|
||||
pmi.setUserAttribute(BEAN_NAME_ATTRIBUTE, beanName);
|
||||
pmi.setUserAttribute(BEAN_NAME_ATTRIBUTE, this.beanName);
|
||||
return mi.proceed();
|
||||
}
|
||||
}
|
||||
@@ -137,7 +137,7 @@ public abstract class ExposeBeanNameAdvisors {
|
||||
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
|
||||
}
|
||||
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
|
||||
pmi.setUserAttribute(BEAN_NAME_ATTRIBUTE, beanName);
|
||||
pmi.setUserAttribute(BEAN_NAME_ATTRIBUTE, this.beanName);
|
||||
return super.invoke(mi);
|
||||
}
|
||||
|
||||
|
||||
+12
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -53,28 +53,29 @@ public abstract class ScopedProxyUtils {
|
||||
|
||||
// Create a scoped proxy definition for the original bean name,
|
||||
// "hiding" the target bean in an internal target definition.
|
||||
RootBeanDefinition scopedProxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
|
||||
scopedProxyDefinition.setOriginatingBeanDefinition(definition.getBeanDefinition());
|
||||
scopedProxyDefinition.setSource(definition.getSource());
|
||||
scopedProxyDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
|
||||
proxyDefinition.setOriginatingBeanDefinition(definition.getBeanDefinition());
|
||||
proxyDefinition.setSource(definition.getSource());
|
||||
proxyDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
|
||||
String targetBeanName = getTargetBeanName(originalBeanName);
|
||||
scopedProxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
|
||||
proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
|
||||
|
||||
if (proxyTargetClass) {
|
||||
targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
|
||||
// ScopedFactoryBean's "proxyTargetClass" default is TRUE, so we don't need to set it explicitly here.
|
||||
}
|
||||
else {
|
||||
scopedProxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
|
||||
proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
|
||||
}
|
||||
|
||||
// Copy autowire settings from original bean definition.
|
||||
proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
|
||||
proxyDefinition.setPrimary(targetDefinition.isPrimary());
|
||||
if (targetDefinition instanceof AbstractBeanDefinition) {
|
||||
scopedProxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
|
||||
proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
|
||||
}
|
||||
scopedProxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
|
||||
scopedProxyDefinition.setPrimary(targetDefinition.isPrimary());
|
||||
|
||||
// The target bean should be ignored in favor of the scoped proxy.
|
||||
targetDefinition.setAutowireCandidate(false);
|
||||
targetDefinition.setPrimary(false);
|
||||
@@ -84,7 +85,7 @@ public abstract class ScopedProxyUtils {
|
||||
|
||||
// Return the scoped proxy definition as primary bean definition
|
||||
// (potentially an inner bean).
|
||||
return new BeanDefinitionHolder(scopedProxyDefinition, originalBeanName, definition.getAliases());
|
||||
return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+19
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -85,7 +85,7 @@ public abstract class AopUtils {
|
||||
* Check whether the specified class is a CGLIB-generated class.
|
||||
* @param clazz the class to check
|
||||
*/
|
||||
public static boolean isCglibProxyClass(Class clazz) {
|
||||
public static boolean isCglibProxyClass(Class<?> clazz) {
|
||||
return (clazz != null && isCglibProxyClassName(clazz.getName()));
|
||||
}
|
||||
|
||||
@@ -98,22 +98,24 @@ public abstract class AopUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the target class of the given bean instance,
|
||||
* which might be an AOP proxy.
|
||||
* Determine the target class of the given bean instance which might be an AOP proxy.
|
||||
* <p>Returns the target class for an AOP proxy and the plain class else.
|
||||
* @param candidate the instance to check (might be an AOP proxy)
|
||||
* @return the target class (or the plain class of the given object as fallback)
|
||||
* @return the target class (or the plain class of the given object as fallback;
|
||||
* never <code>null</code>)
|
||||
* @see org.springframework.aop.TargetClassAware#getTargetClass()
|
||||
* @see org.springframework.aop.framework.AopProxyUtils#ultimateTargetClass(Object)
|
||||
*/
|
||||
public static Class getTargetClass(Object candidate) {
|
||||
public static Class<?> getTargetClass(Object candidate) {
|
||||
Assert.notNull(candidate, "Candidate object must not be null");
|
||||
Class<?> result = null;
|
||||
if (candidate instanceof TargetClassAware) {
|
||||
return ((TargetClassAware) candidate).getTargetClass();
|
||||
result = ((TargetClassAware) candidate).getTargetClass();
|
||||
}
|
||||
if (isCglibProxy(candidate)) {
|
||||
return candidate.getClass().getSuperclass();
|
||||
if (result == null) {
|
||||
result = (isCglibProxy(candidate) ? candidate.getClass().getSuperclass() : candidate.getClass());
|
||||
}
|
||||
return candidate.getClass();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,7 +167,7 @@ public abstract class AopUtils {
|
||||
* <code>targetClass</code> doesn't implement it or is <code>null</code>
|
||||
* @see org.springframework.util.ClassUtils#getMostSpecificMethod
|
||||
*/
|
||||
public static Method getMostSpecificMethod(Method method, Class targetClass) {
|
||||
public static Method getMostSpecificMethod(Method method, Class<?> targetClass) {
|
||||
Method resolvedMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
|
||||
// If we are dealing with method with generic parameters, find the original method.
|
||||
return BridgeMethodResolver.findBridgedMethod(resolvedMethod);
|
||||
@@ -180,7 +182,7 @@ public abstract class AopUtils {
|
||||
* @param targetClass the class to test
|
||||
* @return whether the pointcut can apply on any method
|
||||
*/
|
||||
public static boolean canApply(Pointcut pc, Class targetClass) {
|
||||
public static boolean canApply(Pointcut pc, Class<?> targetClass) {
|
||||
return canApply(pc, targetClass, false);
|
||||
}
|
||||
|
||||
@@ -194,7 +196,7 @@ public abstract class AopUtils {
|
||||
* for this bean includes any introductions
|
||||
* @return whether the pointcut can apply on any method
|
||||
*/
|
||||
public static boolean canApply(Pointcut pc, Class targetClass, boolean hasIntroductions) {
|
||||
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
|
||||
if (!pc.getClassFilter().matches(targetClass)) {
|
||||
return false;
|
||||
}
|
||||
@@ -207,7 +209,7 @@ public abstract class AopUtils {
|
||||
|
||||
Set<Class> classes = new HashSet<Class>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
|
||||
classes.add(targetClass);
|
||||
for (Class clazz : classes) {
|
||||
for (Class<?> clazz : classes) {
|
||||
Method[] methods = clazz.getMethods();
|
||||
for (Method method : methods) {
|
||||
if ((introductionAwareMethodMatcher != null &&
|
||||
@@ -229,7 +231,7 @@ public abstract class AopUtils {
|
||||
* @param targetClass class we're testing
|
||||
* @return whether the pointcut can apply on any method
|
||||
*/
|
||||
public static boolean canApply(Advisor advisor, Class targetClass) {
|
||||
public static boolean canApply(Advisor advisor, Class<?> targetClass) {
|
||||
return canApply(advisor, targetClass, false);
|
||||
}
|
||||
|
||||
@@ -243,7 +245,7 @@ public abstract class AopUtils {
|
||||
* any introductions
|
||||
* @return whether the pointcut can apply on any method
|
||||
*/
|
||||
public static boolean canApply(Advisor advisor, Class targetClass, boolean hasIntroductions) {
|
||||
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
|
||||
if (advisor instanceof IntroductionAdvisor) {
|
||||
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
|
||||
}
|
||||
@@ -265,7 +267,7 @@ public abstract class AopUtils {
|
||||
* @return sublist of Advisors that can apply to an object of the given class
|
||||
* (may be the incoming List as-is)
|
||||
*/
|
||||
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class clazz) {
|
||||
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
|
||||
if (candidateAdvisors.isEmpty()) {
|
||||
return candidateAdvisors;
|
||||
}
|
||||
|
||||
+8
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author 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,15 +16,12 @@
|
||||
|
||||
package org.springframework.aop.target;
|
||||
|
||||
import java.io.NotSerializableException;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@@ -65,7 +62,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource
|
||||
private String targetBeanName;
|
||||
|
||||
/** Class of the target */
|
||||
private Class targetClass;
|
||||
private Class<?> targetClass;
|
||||
|
||||
/**
|
||||
* BeanFactory that owns this TargetSource. We need to hold onto this
|
||||
@@ -108,7 +105,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource
|
||||
* Set the owning BeanFactory. We need to save a reference so that we can
|
||||
* use the <code>getBean</code> method on every invocation.
|
||||
*/
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
if (this.targetBeanName == null) {
|
||||
throw new IllegalStateException("Property'targetBeanName' is required");
|
||||
}
|
||||
@@ -123,7 +120,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource
|
||||
}
|
||||
|
||||
|
||||
public synchronized Class getTargetClass() {
|
||||
public synchronized Class<?> getTargetClass() {
|
||||
if (this.targetClass == null && this.beanFactory != null) {
|
||||
// Determine type of the target bean.
|
||||
this.targetClass = this.beanFactory.getType(this.targetBeanName);
|
||||
@@ -131,7 +128,10 @@ public abstract class AbstractBeanFactoryBasedTargetSource
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Getting bean with name '" + this.targetBeanName + "' in order to determine type");
|
||||
}
|
||||
this.targetClass = this.beanFactory.getBean(this.targetBeanName).getClass();
|
||||
Object beanInstance = this.beanFactory.getBean(this.targetBeanName);
|
||||
if (beanInstance != null) {
|
||||
this.targetClass = beanInstance.getClass();
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.targetClass;
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -64,7 +64,7 @@ public abstract class AbstractLazyCreationTargetSource implements TargetSource {
|
||||
* a meaningful value when the target is still <code>null</code>.
|
||||
* @see #isInitialized()
|
||||
*/
|
||||
public synchronized Class getTargetClass() {
|
||||
public synchronized Class<?> getTargetClass() {
|
||||
return (this.lazyTarget != null ? this.lazyTarget.getClass() : null);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -89,7 +89,7 @@ public class EmptyTargetSource implements TargetSource, Serializable {
|
||||
/**
|
||||
* Always returns the specified target Class, or <code>null</code> if none.
|
||||
*/
|
||||
public Class getTargetClass() {
|
||||
public Class<?> getTargetClass() {
|
||||
return this.targetClass;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2010 the original author 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,7 +59,7 @@ public class HotSwappableTargetSource implements TargetSource, Serializable {
|
||||
* Return the type of the current target object.
|
||||
* <p>The returned type should usually be constant across all target objects.
|
||||
*/
|
||||
public synchronized Class getTargetClass() {
|
||||
public synchronized Class<?> getTargetClass() {
|
||||
return this.target.getClass();
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2010 the original author 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,7 +55,7 @@ public class SingletonTargetSource implements TargetSource, Serializable {
|
||||
}
|
||||
|
||||
|
||||
public Class getTargetClass() {
|
||||
public Class<?> getTargetClass() {
|
||||
return this.target.getClass();
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2010 the original author 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,7 +63,7 @@ public abstract class AbstractRefreshableTargetSource implements TargetSource, R
|
||||
}
|
||||
|
||||
|
||||
public synchronized Class getTargetClass() {
|
||||
public synchronized Class<?> getTargetClass() {
|
||||
if (this.targetObject == null) {
|
||||
refresh();
|
||||
}
|
||||
|
||||
+18
@@ -56,6 +56,15 @@
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="expose-proxy" type="xsd:boolean" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Indicate that the proxy should be exposed by the AOP framework as a
|
||||
ThreadLocal for retrieval via the AopContext class. Off by default,
|
||||
i.e. no guarantees that AopContext access will work.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
@@ -84,6 +93,15 @@
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="expose-proxy" type="xsd:boolean" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Indicate that the proxy should be exposed by the AOP framework as a
|
||||
ThreadLocal for retrieval via the AopContext class. Off by default,
|
||||
i.e. no guarantees that AopContext access will work.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
|
||||
+8
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2010 the original author 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,15 +16,14 @@
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import test.aop.PerThisAspect;
|
||||
|
||||
import test.util.SerializationTestUtils;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
@@ -76,6 +75,7 @@ public final class AspectProxyFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // InstantiationModelAwarePointcutAdvisorImpl not serializable yet
|
||||
public void testWithInstance() throws Exception {
|
||||
MultiplyReturnValue aspect = new MultiplyReturnValue();
|
||||
int multiple = 3;
|
||||
@@ -88,8 +88,10 @@ public final class AspectProxyFactoryTests {
|
||||
proxyFactory.addAspect(aspect);
|
||||
|
||||
ITestBean proxy = proxyFactory.getProxy();
|
||||
|
||||
assertEquals(target.getAge() * multiple, proxy.getAge());
|
||||
|
||||
ITestBean serializedProxy = (ITestBean) SerializationTestUtils.serializeAndDeserialize(proxy);
|
||||
assertEquals(target.getAge() * multiple, serializedProxy.getAge());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
|
||||
+16
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -293,20 +293,33 @@ public final class ProxyFactoryTests {
|
||||
public void testProxyTargetClassWithInterfaceAsTarget() {
|
||||
ProxyFactory pf = new ProxyFactory();
|
||||
pf.setTargetClass(ITestBean.class);
|
||||
|
||||
Object proxy = pf.getProxy();
|
||||
assertTrue("Proxy is a JDK proxy", AopUtils.isJdkDynamicProxy(proxy));
|
||||
assertTrue(proxy instanceof ITestBean);
|
||||
assertEquals(ITestBean.class, AopProxyUtils.ultimateTargetClass(proxy));
|
||||
|
||||
ProxyFactory pf2 = new ProxyFactory(proxy);
|
||||
Object proxy2 = pf2.getProxy();
|
||||
assertTrue("Proxy is a JDK proxy", AopUtils.isJdkDynamicProxy(proxy2));
|
||||
assertTrue(proxy2 instanceof ITestBean);
|
||||
assertEquals(ITestBean.class, AopProxyUtils.ultimateTargetClass(proxy2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProxyTargetClassWithConcreteClassAsTarget() {
|
||||
ProxyFactory pf = new ProxyFactory();
|
||||
pf.setTargetClass(TestBean.class);
|
||||
|
||||
Object proxy = pf.getProxy();
|
||||
assertTrue("Proxy is a CGLIB proxy", AopUtils.isCglibProxy(proxy));
|
||||
assertTrue(proxy instanceof TestBean);
|
||||
assertEquals(TestBean.class, AopProxyUtils.ultimateTargetClass(proxy));
|
||||
|
||||
ProxyFactory pf2 = new ProxyFactory(proxy);
|
||||
pf2.setProxyTargetClass(true);
|
||||
Object proxy2 = pf2.getProxy();
|
||||
assertTrue("Proxy is a CGLIB proxy", AopUtils.isCglibProxy(proxy2));
|
||||
assertTrue(proxy2 instanceof TestBean);
|
||||
assertEquals(TestBean.class, AopProxyUtils.ultimateTargetClass(proxy2));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -8,10 +8,10 @@ Import-Template:
|
||||
org.aopalliance.*;version="[1.0.0, 2.0.0)",
|
||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||
org.apache.commons.pool.*;version="[1.3.0, 2.0.0)";resolution:=optional,
|
||||
org.aspectj.*;version="[1.5.4, 2.0.0)";resolution:=optional,
|
||||
org.springframework.beans.*;version="[3.0.0, 3.0.1)";resolution:=optional,
|
||||
org.springframework.core.*;version="[3.0.0, 3.0.1)",
|
||||
org.springframework.util.*;version="[3.0.0, 3.0.1)",
|
||||
org.aspectj.*;version=${aj.osgi.range};resolution:=optional,
|
||||
org.springframework.beans.*;version=${spring.osgi.range};resolution:=optional,
|
||||
org.springframework.core.*;version=${spring.osgi.range},
|
||||
org.springframework.util.*;version=${spring.osgi.range},
|
||||
org.w3c.dom.*;version="0";resolution:=optional
|
||||
Ignored-Existing-Headers:
|
||||
Bnd-LastModified,
|
||||
|
||||
@@ -1,56 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-asm</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.1.BUILD-SNAPSHOT</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.1.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>jarjar</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<tasks>
|
||||
<taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpathref="maven.plugin.classpath" />
|
||||
<jarjar jarfile="${project.build.directory}${file.separator}${project.build.finalName}-jarjar.jar">
|
||||
<zipfileset src="${project.build.directory}/jarjar-staging/com.springsource.org.objectweb.asm.jar"/>
|
||||
<zipfileset src="${project.build.directory}/jarjar-staging/com.springsource.org.objectweb.asm.commons.jar"/>
|
||||
<rule pattern="org.objectweb.asm.**" result="org.springframework.asm.@1"/>
|
||||
</jarjar>
|
||||
<unjar src="${project.build.directory}${file.separator}${project.build.finalName}-jarjar.jar"
|
||||
dest="${project.build.outputDirectory}">
|
||||
<patternset>
|
||||
<include name="**/*.class"/>
|
||||
<exclude name="*"/>
|
||||
</patternset>
|
||||
</unjar>
|
||||
</tasks>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.code</groupId>
|
||||
<artifactId>jarjar</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-asm</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.3.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.3.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>jarjar</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<tasks>
|
||||
<taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpathref="maven.plugin.classpath" />
|
||||
<jarjar jarfile="${project.build.directory}${file.separator}${project.build.finalName}-jarjar.jar">
|
||||
<zipfileset src="${project.build.directory}/jarjar-staging/com.springsource.org.objectweb.asm.jar"/>
|
||||
<zipfileset src="${project.build.directory}/jarjar-staging/com.springsource.org.objectweb.asm.commons.jar"/>
|
||||
<rule pattern="org.objectweb.asm.**" result="org.springframework.asm.@1"/>
|
||||
</jarjar>
|
||||
<unjar src="${project.build.directory}${file.separator}${project.build.finalName}-jarjar.jar"
|
||||
dest="${project.build.outputDirectory}">
|
||||
<patternset>
|
||||
<include name="**/*.class"/>
|
||||
<exclude name="*"/>
|
||||
</patternset>
|
||||
</unjar>
|
||||
</tasks>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.code</groupId>
|
||||
<artifactId>jarjar</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
@@ -1,83 +1,84 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aspects</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.1.BUILD-SNAPSHOT</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.1.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<!-- common logging dependency is in spring-core -->
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.mail</groupId>
|
||||
<artifactId>mail</artifactId>
|
||||
<version>1.4</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.persistence</groupId>
|
||||
<artifactId>persistence-api</artifactId>
|
||||
<version>1.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<junitArtifactName>junit:junit</junitArtifactName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aspects</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.3.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.3.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<!-- common logging dependency is in spring-core -->
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.persistence</groupId>
|
||||
<artifactId>persistence-api</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.mail</groupId>
|
||||
<artifactId>mail</artifactId>
|
||||
<version>1.4</version>
|
||||
<scope>test</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<junitArtifactName>junit:junit</junitArtifactName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
+1
-1
@@ -151,7 +151,7 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
|
||||
expectations.verify();
|
||||
}
|
||||
|
||||
Object around() : methodToMock() {
|
||||
Object around() : methodToMock() && cflowbelow(mockStaticsTestMethod()) {
|
||||
if (recording) {
|
||||
expectations.expectCall(thisJoinPointStaticPart.toLongString(), thisJoinPoint.getArgs());
|
||||
// Return value doesn't matter
|
||||
|
||||
@@ -4,11 +4,11 @@ Bundle-Vendor: SpringSource
|
||||
Bundle-ManifestVersion: 2
|
||||
Import-Template:
|
||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||
org.aspectj.*;version="[1.5.4, 2.0.0)";resolution:=optional,
|
||||
org.springframework.beans.*;version="[3.0.0, 3.0.1)",
|
||||
org.springframework.transaction.*;version="[3.0.0, 3.0.1)";resolution:=optional,
|
||||
org.springframework.orm.jpa.*;version="[3.0.0, 3.0.1)";resolution:=optional,
|
||||
org.springframework.dao.*;version="[3.0.0, 3.0.1)";resolution:=optional
|
||||
org.aspectj.*;version=${aj.osgi.range};resolution:=optional,
|
||||
org.springframework.beans.*;version=${spring.osgi.range},
|
||||
org.springframework.transaction.*;version=${spring.osgi.range};resolution:=optional,
|
||||
org.springframework.orm.jpa.*;version=${spring.osgi.range};resolution:=optional,
|
||||
org.springframework.dao.*;version=${spring.osgi.range};resolution:=optional
|
||||
Ignored-Existing-Headers:
|
||||
Bnd-LastModified,
|
||||
Import-Package,
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.1.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.3.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.1.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.3.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -389,8 +389,17 @@ public abstract class BeanUtils {
|
||||
}
|
||||
ClassLoader cl = targetType.getClassLoader();
|
||||
if (cl == null) {
|
||||
cl = ClassLoader.getSystemClassLoader();
|
||||
if (cl == null) {
|
||||
try {
|
||||
cl = ClassLoader.getSystemClassLoader();
|
||||
if (cl == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// e.g. AccessControlException on Google App Engine
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not access system ClassLoader: " + ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -398,8 +407,10 @@ public abstract class BeanUtils {
|
||||
try {
|
||||
Class<?> editorClass = cl.loadClass(editorName);
|
||||
if (!PropertyEditor.class.isAssignableFrom(editorClass)) {
|
||||
logger.warn("Editor class [" + editorName +
|
||||
"] does not implement [java.beans.PropertyEditor] interface");
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Editor class [" + editorName +
|
||||
"] does not implement [java.beans.PropertyEditor] interface");
|
||||
}
|
||||
unknownEditorTypes.put(targetType, Boolean.TRUE);
|
||||
return null;
|
||||
}
|
||||
|
||||
+121
-139
@@ -44,6 +44,7 @@ import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.ConversionException;
|
||||
import org.springframework.core.convert.ConverterNotFoundException;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.support.PropertyTypeDescriptor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -101,6 +102,11 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
|
||||
private TypeConverterDelegate typeConverterDelegate;
|
||||
|
||||
/**
|
||||
* The security context used for invoking the property methods
|
||||
*/
|
||||
private AccessControlContext acc;
|
||||
|
||||
/**
|
||||
* Cached introspections results for this object, to prevent encountering
|
||||
* the cost of JavaBeans introspection every time.
|
||||
@@ -112,9 +118,6 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
*/
|
||||
private Map<String, BeanWrapperImpl> nestedBeanWrappers;
|
||||
|
||||
/** The security context used for invoking the property methods */
|
||||
private AccessControlContext acc;
|
||||
|
||||
private boolean autoGrowNestedPaths = false;
|
||||
|
||||
|
||||
@@ -216,16 +219,6 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
setIntrospectionClass(object.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the security context used during the invocation of the wrapped instance methods.
|
||||
* Can be null.
|
||||
*
|
||||
* @param acc
|
||||
*/
|
||||
public void setSecurityContext(AccessControlContext acc) {
|
||||
this.acc = acc;
|
||||
}
|
||||
|
||||
public final Object getWrappedInstance() {
|
||||
return this.object;
|
||||
}
|
||||
@@ -274,6 +267,22 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
return this.autoGrowNestedPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the security context used during the invocation of the wrapped instance methods.
|
||||
* Can be null.
|
||||
*/
|
||||
public void setSecurityContext(AccessControlContext acc) {
|
||||
this.acc = acc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the security context used during the invocation of the wrapped instance methods.
|
||||
* Can be null.
|
||||
*/
|
||||
public AccessControlContext getSecurityContext() {
|
||||
return this.acc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the class to introspect.
|
||||
* Needs to be called when the target object changes.
|
||||
@@ -360,10 +369,10 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
if (pd != null) {
|
||||
Class type = getPropertyType(propertyName);
|
||||
if (pd.getReadMethod() != null) {
|
||||
return new BeanTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), type);
|
||||
return new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), type);
|
||||
}
|
||||
else if (pd.getWriteMethod() != null) {
|
||||
return new BeanTypeDescriptor(pd, BeanUtils.getWriteMethodParameter(pd), type);
|
||||
return new PropertyTypeDescriptor(pd, BeanUtils.getWriteMethodParameter(pd), type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -413,8 +422,8 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
return false;
|
||||
}
|
||||
|
||||
public <T> T convertIfNecessary(
|
||||
Object value, Class<T> requiredType, MethodParameter methodParam) throws TypeMismatchException {
|
||||
public <T> T convertIfNecessary(Object value, Class<T> requiredType, MethodParameter methodParam)
|
||||
throws TypeMismatchException {
|
||||
try {
|
||||
return this.typeConverterDelegate.convertIfNecessary(value, requiredType, methodParam);
|
||||
}
|
||||
@@ -432,6 +441,39 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
}
|
||||
}
|
||||
|
||||
private Object convertIfNecessary(String propertyName, Object oldValue, Object newValue, Class<?> requiredType,
|
||||
TypeDescriptor td) throws TypeMismatchException {
|
||||
try {
|
||||
return this.typeConverterDelegate.convertIfNecessary(propertyName, oldValue, newValue, requiredType, td);
|
||||
}
|
||||
catch (ConverterNotFoundException ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
|
||||
throw new ConversionNotSupportedException(pce, td.getType(), ex);
|
||||
}
|
||||
catch (ConversionException ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
|
||||
throw new TypeMismatchException(pce, requiredType, ex);
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
|
||||
throw new ConversionNotSupportedException(pce, requiredType, ex);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
|
||||
throw new TypeMismatchException(pce, requiredType, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private Object convertIfNecessary(String propertyName, Object oldValue, Object newValue, Class<?> requiredType)
|
||||
throws TypeMismatchException {
|
||||
|
||||
return convertIfNecessary(propertyName, oldValue, newValue, requiredType, TypeDescriptor.valueOf(requiredType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given value for the specified property to the latter's type.
|
||||
* <p>This method is only intended for optimizations in a BeanFactory.
|
||||
@@ -448,19 +490,14 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||
"No property '" + propertyName + "' found");
|
||||
}
|
||||
try {
|
||||
return this.typeConverterDelegate.convertIfNecessary(null, value, pd);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, null, value);
|
||||
throw new TypeMismatchException(pce, pd.getPropertyType(), ex);
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, null, value);
|
||||
throw new ConversionNotSupportedException(pce, pd.getPropertyType(), ex);
|
||||
}
|
||||
return convertForProperty(propertyName, null, value, pd);
|
||||
}
|
||||
|
||||
private Object convertForProperty(String propertyName, Object oldValue, Object newValue, PropertyDescriptor pd)
|
||||
throws TypeMismatchException {
|
||||
|
||||
return convertIfNecessary(propertyName, oldValue, newValue, pd.getPropertyType(),
|
||||
new PropertyTypeDescriptor(pd, BeanUtils.getWriteMethodParameter(pd)));
|
||||
}
|
||||
|
||||
|
||||
@@ -681,7 +718,6 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
}
|
||||
|
||||
Object value;
|
||||
|
||||
if (System.getSecurityManager() != null) {
|
||||
try {
|
||||
value = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
|
||||
@@ -695,7 +731,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
}
|
||||
}
|
||||
else {
|
||||
value = readMethod.invoke(object, (Object[]) null);
|
||||
value = readMethod.invoke(object, (Object[]) null);
|
||||
}
|
||||
|
||||
if (tokens.keys != null) {
|
||||
@@ -752,7 +788,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
Class<?> mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType(pd.getReadMethod(), i + 1);
|
||||
// IMPORTANT: Do not pass full property name in here - property editors
|
||||
// must not kick in for map keys but rather only for map values.
|
||||
Object convertedMapKey = this.typeConverterDelegate.convertIfNecessary(key, mapKeyType);
|
||||
Object convertedMapKey = convertIfNecessary(null, null, key, mapKeyType);
|
||||
// Pass full property name and old value in here, since we want full
|
||||
// conversion ability for map values.
|
||||
value = map.get(convertedMapKey);
|
||||
@@ -767,15 +803,6 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
}
|
||||
return value;
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||
"Getter for property '" + actualName + "' threw exception", ex);
|
||||
}
|
||||
|
||||
catch(IllegalAccessException ex) {
|
||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||
"Illegal attempt to get property '" + actualName + "' threw exception", ex);
|
||||
}
|
||||
catch (IndexOutOfBoundsException ex) {
|
||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||
"Index of out of bounds in property path '" + propertyName + "'", ex);
|
||||
@@ -784,10 +811,18 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||
"Invalid index in property path '" + propertyName + "'", ex);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (TypeMismatchException ex) {
|
||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||
"Invalid index in property path '" + propertyName + "'", ex);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||
"Getter for property '" + actualName + "' threw exception", ex);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||
"Illegal attempt to get property '" + actualName + "' threw exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private Object growArrayIfNecessary(Object array, int index, String name) {
|
||||
@@ -804,12 +839,16 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
}
|
||||
setPropertyValue(name, newArray);
|
||||
return newArray;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
private void growCollectionIfNecessary(Collection collection, int index, String name, PropertyDescriptor pd, int nestingLevel) {
|
||||
@SuppressWarnings("unchecked")
|
||||
private void growCollectionIfNecessary(
|
||||
Collection collection, int index, String name, PropertyDescriptor pd, int nestingLevel) {
|
||||
|
||||
if (!this.autoGrowNestedPaths) {
|
||||
return;
|
||||
}
|
||||
@@ -897,19 +936,8 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
if (isExtractOldValueForEditor()) {
|
||||
oldValue = Array.get(propValue, arrayIndex);
|
||||
}
|
||||
Object convertedValue = this.typeConverterDelegate.convertIfNecessary(
|
||||
propertyName, oldValue, pv.getValue(), requiredType);
|
||||
Array.set(propValue, Integer.parseInt(key), convertedValue);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
|
||||
throw new TypeMismatchException(pce, requiredType, ex);
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
|
||||
throw new ConversionNotSupportedException(pce, requiredType, ex);
|
||||
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType);
|
||||
Array.set(propValue, arrayIndex, convertedValue);
|
||||
}
|
||||
catch (IndexOutOfBoundsException ex) {
|
||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||
@@ -926,31 +954,23 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
if (isExtractOldValueForEditor() && index < list.size()) {
|
||||
oldValue = list.get(index);
|
||||
}
|
||||
try {
|
||||
Object convertedValue = this.typeConverterDelegate.convertIfNecessary(
|
||||
propertyName, oldValue, pv.getValue(), requiredType);
|
||||
if (index < list.size()) {
|
||||
list.set(index, convertedValue);
|
||||
}
|
||||
else if (index >= list.size()) {
|
||||
for (int i = list.size(); i < index; i++) {
|
||||
try {
|
||||
list.add(null);
|
||||
}
|
||||
catch (NullPointerException ex) {
|
||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||
"Cannot set element with index " + index + " in List of size " +
|
||||
list.size() + ", accessed using property path '" + propertyName +
|
||||
"': List does not support filling up gaps with null elements");
|
||||
}
|
||||
}
|
||||
list.add(convertedValue);
|
||||
}
|
||||
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType);
|
||||
if (index < list.size()) {
|
||||
list.set(index, convertedValue);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
|
||||
throw new TypeMismatchException(pce, requiredType, ex);
|
||||
else if (index >= list.size()) {
|
||||
for (int i = list.size(); i < index; i++) {
|
||||
try {
|
||||
list.add(null);
|
||||
}
|
||||
catch (NullPointerException ex) {
|
||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||
"Cannot set element with index " + index + " in List of size " +
|
||||
list.size() + ", accessed using property path '" + propertyName +
|
||||
"': List does not support filling up gaps with null elements");
|
||||
}
|
||||
}
|
||||
list.add(convertedValue);
|
||||
}
|
||||
}
|
||||
else if (propValue instanceof Map) {
|
||||
@@ -960,34 +980,18 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
Class mapValueType = GenericCollectionTypeResolver.getMapValueReturnType(
|
||||
pd.getReadMethod(), tokens.keys.length);
|
||||
Map map = (Map) propValue;
|
||||
Object convertedMapKey;
|
||||
Object convertedMapValue;
|
||||
try {
|
||||
// IMPORTANT: Do not pass full property name in here - property editors
|
||||
// must not kick in for map keys but rather only for map values.
|
||||
convertedMapKey = this.typeConverterDelegate.convertIfNecessary(key, mapKeyType);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, null, pv.getValue());
|
||||
throw new TypeMismatchException(pce, mapKeyType, ex);
|
||||
}
|
||||
// IMPORTANT: Do not pass full property name in here - property editors
|
||||
// must not kick in for map keys but rather only for map values.
|
||||
Object convertedMapKey = convertIfNecessary(null, null, key, mapKeyType);
|
||||
Object oldValue = null;
|
||||
if (isExtractOldValueForEditor()) {
|
||||
oldValue = map.get(convertedMapKey);
|
||||
}
|
||||
try {
|
||||
// Pass full property name and old value in here, since we want full
|
||||
// conversion ability for map values.
|
||||
convertedMapValue = this.typeConverterDelegate.convertIfNecessary(
|
||||
propertyName, oldValue, pv.getValue(), mapValueType,
|
||||
new MethodParameter(pd.getReadMethod(), -1, tokens.keys.length + 1));
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
|
||||
throw new TypeMismatchException(pce, mapValueType, ex);
|
||||
}
|
||||
// Pass full property name and old value in here, since we want full
|
||||
// conversion ability for map values.
|
||||
Object convertedMapValue = convertIfNecessary(
|
||||
propertyName, oldValue, pv.getValue(), mapValueType,
|
||||
new TypeDescriptor(new MethodParameter(pd.getReadMethod(), -1, tokens.keys.length + 1)));
|
||||
map.put(convertedMapKey, convertedMapValue);
|
||||
}
|
||||
else {
|
||||
@@ -1028,7 +1032,8 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
else {
|
||||
if (isExtractOldValueForEditor() && pd.getReadMethod() != null) {
|
||||
final Method readMethod = pd.getReadMethod();
|
||||
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()) && !readMethod.isAccessible()) {
|
||||
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()) &&
|
||||
!readMethod.isAccessible()) {
|
||||
if (System.getSecurityManager()!= null) {
|
||||
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
public Object run() {
|
||||
@@ -1047,7 +1052,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
public Object run() throws Exception {
|
||||
return readMethod.invoke(object);
|
||||
}
|
||||
},acc);
|
||||
}, acc);
|
||||
}
|
||||
else {
|
||||
oldValue = readMethod.invoke(object);
|
||||
@@ -1063,7 +1068,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
}
|
||||
}
|
||||
}
|
||||
valueToApply = this.typeConverterDelegate.convertIfNecessary(oldValue, originalValue, pd);
|
||||
valueToApply = convertForProperty(propertyName, oldValue, originalValue, pd);
|
||||
}
|
||||
pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
|
||||
}
|
||||
@@ -1084,7 +1089,6 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
}
|
||||
}
|
||||
final Object value = valueToApply;
|
||||
|
||||
if (System.getSecurityManager() != null) {
|
||||
try {
|
||||
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
|
||||
@@ -1093,14 +1097,17 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
return null;
|
||||
}
|
||||
}, acc);
|
||||
} catch (PrivilegedActionException ex) {
|
||||
}
|
||||
catch (PrivilegedActionException ex) {
|
||||
throw ex.getException();
|
||||
}
|
||||
}
|
||||
else {
|
||||
writeMethod.invoke(object, value);
|
||||
writeMethod.invoke(this.object, value);
|
||||
}
|
||||
|
||||
}
|
||||
catch (TypeMismatchException ex) {
|
||||
throw ex;
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
PropertyChangeEvent propertyChangeEvent =
|
||||
@@ -1112,34 +1119,9 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
throw new MethodInvocationException(propertyChangeEvent, ex.getTargetException());
|
||||
}
|
||||
}
|
||||
catch (ConverterNotFoundException ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
|
||||
throw new ConversionNotSupportedException(pce, pd.getPropertyType(), ex);
|
||||
}
|
||||
catch (ConversionException ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
|
||||
throw new TypeMismatchException(pce, pd.getPropertyType(), ex);
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
|
||||
throw new ConversionNotSupportedException(pce, pd.getPropertyType(), ex);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
|
||||
throw new TypeMismatchException(pce, pd.getPropertyType(), ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
|
||||
throw new MethodInvocationException(pce, ex);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
|
||||
throw new MethodInvocationException(pce, ex);
|
||||
}
|
||||
}
|
||||
|
||||
+39
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,11 +22,10 @@ import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
@@ -141,19 +140,20 @@ public class CachedIntrospectionResults {
|
||||
results = (CachedIntrospectionResults) value;
|
||||
}
|
||||
if (results == null) {
|
||||
// can throw BeansException
|
||||
results = new CachedIntrospectionResults(beanClass);
|
||||
// On JDK 1.5 and higher, it is almost always safe to cache the bean class...
|
||||
// The sole exception is a custom BeanInfo class being provided in a non-safe ClassLoader.
|
||||
if (ClassUtils.isCacheSafe(beanClass, CachedIntrospectionResults.class.getClassLoader()) ||
|
||||
isClassLoaderAccepted(beanClass.getClassLoader()) ||
|
||||
!ClassUtils.isPresent(beanClass.getName() + "BeanInfo", beanClass.getClassLoader())) {
|
||||
boolean fullyCacheable =
|
||||
ClassUtils.isCacheSafe(beanClass, CachedIntrospectionResults.class.getClassLoader()) ||
|
||||
isClassLoaderAccepted(beanClass.getClassLoader());
|
||||
if (fullyCacheable || !ClassUtils.isPresent(beanClass.getName() + "BeanInfo", beanClass.getClassLoader())) {
|
||||
results = new CachedIntrospectionResults(beanClass, fullyCacheable);
|
||||
classCache.put(beanClass, results);
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Not strongly caching class [" + beanClass.getName() + "] because it is not cache-safe");
|
||||
}
|
||||
results = new CachedIntrospectionResults(beanClass, true);
|
||||
classCache.put(beanClass, new WeakReference<CachedIntrospectionResults>(results));
|
||||
}
|
||||
}
|
||||
@@ -216,7 +216,7 @@ public class CachedIntrospectionResults {
|
||||
* @param beanClass the bean class to analyze
|
||||
* @throws BeansException in case of introspection failure
|
||||
*/
|
||||
private CachedIntrospectionResults(Class beanClass) throws BeansException {
|
||||
private CachedIntrospectionResults(Class beanClass, boolean cacheFullMetadata) throws BeansException {
|
||||
try {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Getting BeanInfo for class [" + beanClass.getName() + "]");
|
||||
@@ -237,24 +237,29 @@ public class CachedIntrospectionResults {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Caching PropertyDescriptors for class [" + beanClass.getName() + "]");
|
||||
}
|
||||
this.propertyDescriptorCache = new HashMap<String, PropertyDescriptor>();
|
||||
this.propertyDescriptorCache = new LinkedHashMap<String, PropertyDescriptor>();
|
||||
|
||||
// This call is slow so we do it once.
|
||||
PropertyDescriptor[] pds = this.beanInfo.getPropertyDescriptors();
|
||||
for (PropertyDescriptor pd : pds) {
|
||||
if (Class.class.equals(beanClass) && "classLoader".equals(pd.getName())) {
|
||||
// Ignore Class.getClassLoader() method - nobody needs to bind to that
|
||||
continue;
|
||||
}
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Found bean property '" + pd.getName() + "'" +
|
||||
(pd.getPropertyType() != null ? " of type [" + pd.getPropertyType().getName() + "]" : "") +
|
||||
(pd.getPropertyEditorClass() != null ?
|
||||
"; editor [" + pd.getPropertyEditorClass().getName() + "]" : ""));
|
||||
}
|
||||
pd = new GenericTypeAwarePropertyDescriptor(beanClass, pd.getName(), pd.getReadMethod(),
|
||||
pd.getWriteMethod(), pd.getPropertyEditorClass());
|
||||
if (cacheFullMetadata) {
|
||||
pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd);
|
||||
}
|
||||
this.propertyDescriptorCache.put(pd.getName(), pd);
|
||||
}
|
||||
}
|
||||
catch (IntrospectionException ex) {
|
||||
throw new FatalBeanException("Cannot get BeanInfo for object of class [" + beanClass.getName() + "]", ex);
|
||||
throw new FatalBeanException("Failed to obtain BeanInfo for class [" + beanClass.getName() + "]", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,17 +274,35 @@ public class CachedIntrospectionResults {
|
||||
PropertyDescriptor getPropertyDescriptor(String name) {
|
||||
PropertyDescriptor pd = this.propertyDescriptorCache.get(name);
|
||||
if (pd == null && StringUtils.hasLength(name)) {
|
||||
// Same lenient fallback checking as in PropertyTypeDescriptor...
|
||||
pd = this.propertyDescriptorCache.get(name.substring(0, 1).toLowerCase() + name.substring(1));
|
||||
if (pd == null) {
|
||||
pd = this.propertyDescriptorCache.get(name.substring(0, 1).toUpperCase() + name.substring(1));
|
||||
}
|
||||
}
|
||||
return pd;
|
||||
return (pd == null || pd instanceof GenericTypeAwarePropertyDescriptor ? pd :
|
||||
buildGenericTypeAwarePropertyDescriptor(getBeanClass(), pd));
|
||||
}
|
||||
|
||||
PropertyDescriptor[] getPropertyDescriptors() {
|
||||
Collection<PropertyDescriptor> descriptorCollection = this.propertyDescriptorCache.values();
|
||||
return descriptorCollection.toArray(new PropertyDescriptor[descriptorCollection.size()]);
|
||||
PropertyDescriptor[] pds = new PropertyDescriptor[this.propertyDescriptorCache.size()];
|
||||
int i = 0;
|
||||
for (PropertyDescriptor pd : this.propertyDescriptorCache.values()) {
|
||||
pds[i] = (pd instanceof GenericTypeAwarePropertyDescriptor ? pd :
|
||||
buildGenericTypeAwarePropertyDescriptor(getBeanClass(), pd));
|
||||
i++;
|
||||
}
|
||||
return pds;
|
||||
}
|
||||
|
||||
private PropertyDescriptor buildGenericTypeAwarePropertyDescriptor(Class beanClass, PropertyDescriptor pd) {
|
||||
try {
|
||||
return new GenericTypeAwarePropertyDescriptor(beanClass, pd.getName(), pd.getReadMethod(),
|
||||
pd.getWriteMethod(), pd.getPropertyEditorClass());
|
||||
}
|
||||
catch (IntrospectionException ex) {
|
||||
throw new FatalBeanException("Failed to re-introspect class [" + beanClass.getName() + "]", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+16
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,6 +22,8 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.ConversionException;
|
||||
import org.springframework.core.convert.ConverterNotFoundException;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
@@ -122,13 +124,15 @@ public class DirectFieldAccessor extends AbstractPropertyAccessor {
|
||||
try {
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
oldValue = field.get(this.target);
|
||||
Object convertedValue = this.typeConverterDelegate.convertIfNecessary(oldValue, newValue, field);
|
||||
Object convertedValue = this.typeConverterDelegate.convertIfNecessary(
|
||||
field.getName(), oldValue, newValue, field.getType(), new TypeDescriptor(field));
|
||||
field.set(this.target, convertedValue);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new InvalidPropertyException(this.target.getClass(), propertyName, "Field is not accessible", ex);
|
||||
catch (ConverterNotFoundException ex) {
|
||||
PropertyChangeEvent pce = new PropertyChangeEvent(this.target, propertyName, oldValue, newValue);
|
||||
throw new ConversionNotSupportedException(pce, field.getType(), ex);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
catch (ConversionException ex) {
|
||||
PropertyChangeEvent pce = new PropertyChangeEvent(this.target, propertyName, oldValue, newValue);
|
||||
throw new TypeMismatchException(pce, field.getType(), ex);
|
||||
}
|
||||
@@ -136,6 +140,13 @@ public class DirectFieldAccessor extends AbstractPropertyAccessor {
|
||||
PropertyChangeEvent pce = new PropertyChangeEvent(this.target, propertyName, oldValue, newValue);
|
||||
throw new ConversionNotSupportedException(pce, field.getType(), ex);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
PropertyChangeEvent pce = new PropertyChangeEvent(this.target, propertyName, oldValue, newValue);
|
||||
throw new TypeMismatchException(pce, field.getType(), ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new InvalidPropertyException(this.target.getClass(), propertyName, "Field is not accessible", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> T convertIfNecessary(
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -339,8 +339,10 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
|
||||
@Override
|
||||
public String toString() {
|
||||
PropertyValue[] pvs = getPropertyValues();
|
||||
StringBuilder sb = new StringBuilder("PropertyValues: length=" + pvs.length + "; ");
|
||||
sb.append(StringUtils.arrayToDelimitedString(pvs, "; "));
|
||||
StringBuilder sb = new StringBuilder("PropertyValues: length=").append(pvs.length);
|
||||
if (pvs.length > 0) {
|
||||
sb.append("; ").append(StringUtils.arrayToDelimitedString(pvs, "; "));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
+32
-3
@@ -42,6 +42,8 @@ import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import org.springframework.beans.propertyeditors.ByteArrayPropertyEditor;
|
||||
import org.springframework.beans.propertyeditors.CharArrayPropertyEditor;
|
||||
import org.springframework.beans.propertyeditors.CharacterEditor;
|
||||
@@ -54,6 +56,7 @@ import org.springframework.beans.propertyeditors.CustomCollectionEditor;
|
||||
import org.springframework.beans.propertyeditors.CustomMapEditor;
|
||||
import org.springframework.beans.propertyeditors.CustomNumberEditor;
|
||||
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.PatternEditor;
|
||||
@@ -90,6 +93,8 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
|
||||
private Map<Class, PropertyEditor> defaultEditors;
|
||||
|
||||
private Map<Class, PropertyEditor> overriddenDefaultEditors;
|
||||
|
||||
private Map<Class, PropertyEditor> customEditors;
|
||||
|
||||
private Map<String, CustomEditorHolder> customEditorsForPath;
|
||||
@@ -138,6 +143,22 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
this.configValueEditorsActive = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the default editor for the specified type with the given property editor.
|
||||
* <p>Note that this is different from registering a custom editor in that the editor
|
||||
* semantically still is a default editor. A ConversionService will override such a
|
||||
* default editor, whereas custom editors usually override the ConversionService.
|
||||
* @param requiredType the type of the property
|
||||
* @param propertyEditor the editor to register
|
||||
* @see #registerCustomEditor(Class, PropertyEditor)
|
||||
*/
|
||||
public void overrideDefaultEditor(Class requiredType, PropertyEditor propertyEditor) {
|
||||
if (this.overriddenDefaultEditors == null) {
|
||||
this.overriddenDefaultEditors = new HashMap<Class, PropertyEditor>();
|
||||
}
|
||||
this.overriddenDefaultEditors.put(requiredType, propertyEditor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the default editor for the given property type, if any.
|
||||
* <p>Lazily registers the default editors, if they are active.
|
||||
@@ -149,8 +170,14 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
if (!this.defaultEditorsActive) {
|
||||
return null;
|
||||
}
|
||||
if (this.overriddenDefaultEditors != null) {
|
||||
PropertyEditor editor = this.overriddenDefaultEditors.get(requiredType);
|
||||
if (editor != null) {
|
||||
return editor;
|
||||
}
|
||||
}
|
||||
if (this.defaultEditors == null) {
|
||||
doRegisterDefaultEditors();
|
||||
createDefaultEditors();
|
||||
}
|
||||
return this.defaultEditors.get(requiredType);
|
||||
}
|
||||
@@ -158,7 +185,7 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
/**
|
||||
* Actually register the default editors for this registry instance.
|
||||
*/
|
||||
private void doRegisterDefaultEditors() {
|
||||
private void createDefaultEditors() {
|
||||
this.defaultEditors = new HashMap<Class, PropertyEditor>(64);
|
||||
|
||||
// Simple editors, without parameterization capabilities.
|
||||
@@ -169,6 +196,7 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
this.defaultEditors.put(Currency.class, new CurrencyEditor());
|
||||
this.defaultEditors.put(File.class, new FileEditor());
|
||||
this.defaultEditors.put(InputStream.class, new InputStreamEditor());
|
||||
this.defaultEditors.put(InputSource.class, new InputSourceEditor());
|
||||
this.defaultEditors.put(Locale.class, new LocaleEditor());
|
||||
this.defaultEditors.put(Pattern.class, new PatternEditor());
|
||||
this.defaultEditors.put(Properties.class, new PropertiesEditor());
|
||||
@@ -230,9 +258,10 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
* @param target the target registry to copy to
|
||||
*/
|
||||
protected void copyDefaultEditorsTo(PropertyEditorRegistrySupport target) {
|
||||
target.defaultEditors = this.defaultEditors;
|
||||
target.defaultEditorsActive = this.defaultEditorsActive;
|
||||
target.configValueEditorsActive = this.configValueEditorsActive;
|
||||
target.defaultEditors = this.defaultEditors;
|
||||
target.overriddenDefaultEditors = this.overriddenDefaultEditors;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+22
-70
@@ -33,6 +33,7 @@ import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.support.PropertyTypeDescriptor;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -76,18 +77,6 @@ class TypeConverterDelegate {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert the value to the specified required type.
|
||||
* @param newValue the proposed new value
|
||||
* @param requiredType the type we must convert to
|
||||
* (or <code>null</code> if not known, for example in case of a collection element)
|
||||
* @return the new value, possibly the result of type conversion
|
||||
* @throws IllegalArgumentException if type conversion failed
|
||||
*/
|
||||
public <T> T convertIfNecessary(Object newValue, Class<T> requiredType) throws IllegalArgumentException {
|
||||
return convertIfNecessary(null, null, newValue, requiredType, TypeDescriptor.valueOf(requiredType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the value to the specified required type.
|
||||
* @param newValue the proposed new value
|
||||
@@ -122,54 +111,6 @@ class TypeConverterDelegate {
|
||||
return convertIfNecessary(propertyName, oldValue, newValue, requiredType, TypeDescriptor.valueOf(requiredType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the value to the required type (if necessary from a String),
|
||||
* for the specified property.
|
||||
* @param propertyName name of the property
|
||||
* @param oldValue the previous value, if available (may be <code>null</code>)
|
||||
* @param newValue the proposed new value
|
||||
* @param requiredType the type we must convert to
|
||||
* (or <code>null</code> if not known, for example in case of a collection element)
|
||||
* @param methodParam the method parameter that is the target of the conversion
|
||||
* @return the new value, possibly the result of type conversion
|
||||
* @throws IllegalArgumentException if type conversion failed
|
||||
*/
|
||||
public <T> T convertIfNecessary(String propertyName, Object oldValue, Object newValue,
|
||||
Class<T> requiredType, MethodParameter methodParam) throws IllegalArgumentException {
|
||||
|
||||
return convertIfNecessary(propertyName, oldValue, newValue, requiredType, new TypeDescriptor(methodParam));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the value to the required type for the specified property.
|
||||
* @param oldValue the previous value, if available (may be <code>null</code>)
|
||||
* @param newValue the proposed new value
|
||||
* @param descriptor the JavaBeans descriptor for the property
|
||||
* @return the new value, possibly the result of type conversion
|
||||
* @throws IllegalArgumentException if type conversion failed
|
||||
*/
|
||||
public Object convertIfNecessary(Object oldValue, Object newValue, PropertyDescriptor descriptor)
|
||||
throws IllegalArgumentException {
|
||||
|
||||
return convertIfNecessary(descriptor.getName(), oldValue, newValue, descriptor.getPropertyType(),
|
||||
new BeanTypeDescriptor(descriptor));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the value to the required type for the specified property.
|
||||
* @param oldValue the previous value, if available (may be <code>null</code>)
|
||||
* @param newValue the proposed new value
|
||||
* @param field the field that is the target of the conversion
|
||||
* @return the new value, possibly the result of type conversion
|
||||
* @throws IllegalArgumentException if type conversion failed
|
||||
*/
|
||||
public Object convertIfNecessary(Object oldValue, Object newValue, Field field)
|
||||
throws IllegalArgumentException {
|
||||
|
||||
return convertIfNecessary(field.getName(), oldValue, newValue, field.getType(), new TypeDescriptor(field));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert the value to the required type (if necessary from a String),
|
||||
* for the specified property.
|
||||
@@ -183,7 +124,7 @@ class TypeConverterDelegate {
|
||||
* @throws IllegalArgumentException if type conversion failed
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T convertIfNecessary(String propertyName, Object oldValue, Object newValue,
|
||||
public <T> T convertIfNecessary(String propertyName, Object oldValue, Object newValue,
|
||||
Class<T> requiredType, TypeDescriptor typeDescriptor) throws IllegalArgumentException {
|
||||
|
||||
Object convertedValue = newValue;
|
||||
@@ -195,8 +136,9 @@ class TypeConverterDelegate {
|
||||
ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
|
||||
if (editor == null && conversionService != null && convertedValue != null) {
|
||||
TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(convertedValue);
|
||||
if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
|
||||
return (T) conversionService.convert(convertedValue, sourceTypeDesc, typeDescriptor);
|
||||
TypeDescriptor targetTypeDesc = typeDescriptor.forElementType(requiredType);
|
||||
if (conversionService.canConvert(sourceTypeDesc, targetTypeDesc)) {
|
||||
return (T) conversionService.convert(convertedValue, sourceTypeDesc, targetTypeDesc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,8 +146,8 @@ class TypeConverterDelegate {
|
||||
if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {
|
||||
if (requiredType != null && Collection.class.isAssignableFrom(requiredType) &&
|
||||
convertedValue instanceof String && typeDescriptor.getMethodParameter() != null) {
|
||||
Class elementType = GenericCollectionTypeResolver.getCollectionParameterType(typeDescriptor.getMethodParameter());
|
||||
if (elementType != null && Enum.class.isAssignableFrom(elementType)) {
|
||||
Class elemType = GenericCollectionTypeResolver.getCollectionParameterType(typeDescriptor.getMethodParameter());
|
||||
if (elemType != null && Enum.class.isAssignableFrom(elemType)) {
|
||||
convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
|
||||
}
|
||||
}
|
||||
@@ -348,8 +290,8 @@ class TypeConverterDelegate {
|
||||
*/
|
||||
protected PropertyEditor findDefaultEditor(Class requiredType, TypeDescriptor typeDescriptor) {
|
||||
PropertyEditor editor = null;
|
||||
if (typeDescriptor instanceof BeanTypeDescriptor) {
|
||||
PropertyDescriptor pd = ((BeanTypeDescriptor) typeDescriptor).getPropertyDescriptor();
|
||||
if (typeDescriptor instanceof PropertyTypeDescriptor) {
|
||||
PropertyDescriptor pd = ((PropertyTypeDescriptor) typeDescriptor).getPropertyDescriptor();
|
||||
editor = pd.createPropertyEditor(this.targetObject);
|
||||
}
|
||||
if (editor == null && requiredType != null) {
|
||||
@@ -518,6 +460,10 @@ class TypeConverterDelegate {
|
||||
Collection original, String propertyName, Class requiredType, TypeDescriptor typeDescriptor) {
|
||||
|
||||
boolean originalAllowed = requiredType.isInstance(original);
|
||||
if (!originalAllowed && !Collection.class.isAssignableFrom(requiredType)) {
|
||||
return original;
|
||||
}
|
||||
|
||||
MethodParameter methodParam = typeDescriptor.getMethodParameter();
|
||||
Class elementType = null;
|
||||
if (methodParam != null) {
|
||||
@@ -571,8 +517,8 @@ class TypeConverterDelegate {
|
||||
if (methodParam != null) {
|
||||
methodParam.increaseNestingLevel();
|
||||
}
|
||||
Object convertedElement =
|
||||
convertIfNecessary(indexedPropertyName, null, element, elementType, typeDescriptor);
|
||||
Object convertedElement = convertIfNecessary(
|
||||
indexedPropertyName, null, element, elementType, typeDescriptor);
|
||||
if (methodParam != null) {
|
||||
methodParam.decreaseNestingLevel();
|
||||
}
|
||||
@@ -592,8 +538,14 @@ class TypeConverterDelegate {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Map convertToTypedMap(Map original, String propertyName, Class requiredType, TypeDescriptor typeDescriptor) {
|
||||
protected Map convertToTypedMap(
|
||||
Map original, String propertyName, Class requiredType, TypeDescriptor typeDescriptor) {
|
||||
|
||||
boolean originalAllowed = requiredType.isInstance(original);
|
||||
if (!originalAllowed && !Map.class.isAssignableFrom(requiredType)) {
|
||||
return original;
|
||||
}
|
||||
|
||||
Class keyType = null;
|
||||
Class valueType = null;
|
||||
MethodParameter methodParam = typeDescriptor.getMethodParameter();
|
||||
|
||||
+8
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -153,8 +153,14 @@ 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.
|
||||
* {@literal null} is disallowed.
|
||||
* @return bean matching required type
|
||||
* <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}.
|
||||
* @return an instance of the single bean matching the required type
|
||||
* @throws NoSuchBeanDefinitionException if there is not exactly one matching bean found
|
||||
* @since 3.0
|
||||
* @see ListableBeanFactory
|
||||
*/
|
||||
<T> T getBean(Class<T> requiredType) throws BeansException;
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -193,7 +193,7 @@ public abstract class AbstractFactoryBean<T>
|
||||
* interface, for a consistent offering of abstract template methods.
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
|
||||
*/
|
||||
public abstract Class<? extends T> getObjectType();
|
||||
public abstract Class<?> getObjectType();
|
||||
|
||||
/**
|
||||
* Template method that subclasses must override to construct
|
||||
|
||||
+15
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -183,6 +183,9 @@ public class BeanDefinitionVisitor {
|
||||
return new RuntimeBeanNameReference(newBeanName);
|
||||
}
|
||||
}
|
||||
else if (value instanceof Object[]) {
|
||||
visitArray((Object[]) value);
|
||||
}
|
||||
else if (value instanceof List) {
|
||||
visitList((List) value);
|
||||
}
|
||||
@@ -206,6 +209,17 @@ public class BeanDefinitionVisitor {
|
||||
return value;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void visitArray(Object[] arrayVal) {
|
||||
for (int i = 0; i < arrayVal.length; i++) {
|
||||
Object elem = arrayVal[i];
|
||||
Object newVal = resolveValue(elem);
|
||||
if (!ObjectUtils.nullSafeEquals(newVal, elem)) {
|
||||
arrayVal[i] = newVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void visitList(List listVal) {
|
||||
for (int i = 0; i < listVal.size(); i++) {
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -48,7 +48,8 @@ public interface BeanPostProcessor {
|
||||
* The returned bean instance may be a wrapper around the original.
|
||||
* @param bean the new bean instance
|
||||
* @param beanName the name of the bean
|
||||
* @return the bean instance to use, either the original or a wrapped one
|
||||
* @return the bean instance to use, either the original or a wrapped one; if
|
||||
* <code>null</code>, no subsequent BeanPostProcessors will be invoked
|
||||
* @throws org.springframework.beans.BeansException in case of errors
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
|
||||
*/
|
||||
@@ -68,7 +69,8 @@ public interface BeanPostProcessor {
|
||||
* in contrast to all other BeanPostProcessor callbacks.
|
||||
* @param bean the new bean instance
|
||||
* @param beanName the name of the bean
|
||||
* @return the bean instance to use, either the original or a wrapped one
|
||||
* @return the bean instance to use, either the original or a wrapped one; if
|
||||
* <code>null</code>, no subsequent BeanPostProcessors will be invoked
|
||||
* @throws org.springframework.beans.BeansException in case of errors
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
|
||||
* @see org.springframework.beans.factory.FactoryBean
|
||||
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author 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.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Bean factory post processor that logs a warning for {@link Deprecated @Deprecated} beans.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0.3
|
||||
*/
|
||||
public class DeprecatedBeanWarner implements BeanFactoryPostProcessor {
|
||||
|
||||
/**
|
||||
* Logger available to subclasses.
|
||||
*/
|
||||
protected transient Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
/**
|
||||
* Set the name of the logger to use. The name will be passed to the underlying logger implementation through
|
||||
* Commons Logging, getting interpreted as log category according to the logger's configuration.
|
||||
* <p>This can be specified to not log into the category of this warner class but rather into a specific named category.
|
||||
* @see org.apache.commons.logging.LogFactory#getLog(String)
|
||||
* @see org.apache.log4j.Logger#getLogger(String)
|
||||
* @see java.util.logging.Logger#getLogger(String)
|
||||
*/
|
||||
public void setLoggerName(String loggerName) {
|
||||
this.logger = LogFactory.getLog(loggerName);
|
||||
}
|
||||
|
||||
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||
if (isLogEnabled()) {
|
||||
String[] beanNames = beanFactory.getBeanDefinitionNames();
|
||||
for (String beanName : beanNames) {
|
||||
Class<?> beanType = beanFactory.getType(beanName);
|
||||
if (beanType != null && beanType.isAnnotationPresent(Deprecated.class)) {
|
||||
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
|
||||
logDeprecatedBean(beanName, beanDefinition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a warning for a bean annotated with {@link Deprecated @Deprecated}.
|
||||
*
|
||||
* @param beanName the name of the deprecated bean
|
||||
* @param beanDefinition the definition of the deprecated bean
|
||||
*/
|
||||
protected void logDeprecatedBean(String beanName, BeanDefinition beanDefinition) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(beanDefinition.getBeanClassName());
|
||||
builder.append(" ['");
|
||||
builder.append(beanName);
|
||||
builder.append('\'');
|
||||
String resourceDescription = beanDefinition.getResourceDescription();
|
||||
if (StringUtils.hasLength(resourceDescription)) {
|
||||
builder.append(" in ");
|
||||
builder.append(resourceDescription);
|
||||
}
|
||||
builder.append(" ] has been deprecated");
|
||||
logger.warn(builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the {@link #logger} field is enabled.
|
||||
* <p>Default is {@code true} when the "warn" level is enabled. Subclasses can override this to change the level
|
||||
* under which logging occurs.
|
||||
*/
|
||||
protected boolean isLogEnabled() {
|
||||
return logger.isWarnEnabled();
|
||||
}
|
||||
|
||||
}
|
||||
+30
-24
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,10 @@
|
||||
|
||||
package org.springframework.beans.factory.config;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -41,7 +44,7 @@ import org.springframework.util.Assert;
|
||||
* <pre class="code"><beans>
|
||||
*
|
||||
* <!-- Prototype bean since we have state -->
|
||||
* <bean id="myService" class="a.b.c.MyService" singleton="false"/>
|
||||
* <bean id="myService" class="a.b.c.MyService" scope="prototype"/>
|
||||
*
|
||||
* <bean id="myServiceFactory"
|
||||
* class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
|
||||
@@ -63,9 +66,9 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* public class MyClientBean {
|
||||
*
|
||||
* private ObjectFactory myServiceFactory;
|
||||
* private ObjectFactory<MyService> myServiceFactory;
|
||||
*
|
||||
* public void setMyServiceFactory(ObjectFactory myServiceFactory) {
|
||||
* public void setMyServiceFactory(ObjectFactory<MyService> myServiceFactory) {
|
||||
* this.myServiceFactory = myServiceFactory;
|
||||
* }
|
||||
*
|
||||
@@ -91,20 +94,17 @@ import org.springframework.util.Assert;
|
||||
* @see org.springframework.beans.factory.ObjectFactory
|
||||
* @see ServiceLocatorFactoryBean
|
||||
*/
|
||||
public class ObjectFactoryCreatingFactoryBean extends AbstractFactoryBean {
|
||||
public class ObjectFactoryCreatingFactoryBean extends AbstractFactoryBean<ObjectFactory> {
|
||||
|
||||
private String targetBeanName;
|
||||
|
||||
|
||||
/**
|
||||
* Set the name of the target bean.
|
||||
* <p>The target does not <i>have</> to be a prototype bean, but realisticially
|
||||
* always will be (because if the target bean were a singleton, then said
|
||||
* singleton bean could simply be injected straight into the dependent object,
|
||||
* thus obviating the need for the extra level of indirection afforded by
|
||||
* the approach encapsulated by this class). Please note that no exception
|
||||
* will be thrown if the supplied <code>targetBeanName</code> does not
|
||||
* reference a prototype bean.
|
||||
* <p>The target does not <i>have</> to be a non-singleton bean, but realisticially
|
||||
* always will be (because if the target bean were a singleton, then said singleton
|
||||
* bean could simply be injected straight into the dependent object, thus obviating
|
||||
* the need for the extra level of indirection afforded by this factory approach).
|
||||
*/
|
||||
public void setTargetBeanName(String targetBeanName) {
|
||||
this.targetBeanName = targetBeanName;
|
||||
@@ -123,22 +123,28 @@ public class ObjectFactoryCreatingFactoryBean extends AbstractFactoryBean {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createInstance() {
|
||||
return new ObjectFactory() {
|
||||
public Object getObject() throws BeansException {
|
||||
return getTargetBean(targetBeanName);
|
||||
}
|
||||
};
|
||||
protected ObjectFactory createInstance() {
|
||||
return new TargetBeanObjectFactory(getBeanFactory(), this.targetBeanName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Template method for obtaining a target bean instance.
|
||||
* Called by the exposed ObjectFactory's <code>getObject()</code> method.
|
||||
* @param targetBeanName the name of the target bean
|
||||
* @return the target bean instance
|
||||
* Independent inner class - for serialization purposes.
|
||||
*/
|
||||
protected Object getTargetBean(String targetBeanName) {
|
||||
return getBeanFactory().getBean(targetBeanName);
|
||||
private static class TargetBeanObjectFactory implements ObjectFactory, Serializable {
|
||||
|
||||
private final BeanFactory beanFactory;
|
||||
|
||||
private final String targetBeanName;
|
||||
|
||||
public TargetBeanObjectFactory(BeanFactory beanFactory, String targetBeanName) {
|
||||
this.beanFactory = beanFactory;
|
||||
this.targetBeanName = targetBeanName;
|
||||
}
|
||||
|
||||
public Object getObject() throws BeansException {
|
||||
return this.beanFactory.getBean(this.targetBeanName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -193,7 +193,8 @@ public class PropertyPathFactoryBean implements FactoryBean<Object>, BeanNameAwa
|
||||
public Object getObject() throws BeansException {
|
||||
BeanWrapper target = this.targetBeanWrapper;
|
||||
if (target != null) {
|
||||
if (logger.isWarnEnabled() && this.beanFactory instanceof ConfigurableBeanFactory &&
|
||||
if (logger.isWarnEnabled() && this.targetBeanName != null &&
|
||||
this.beanFactory instanceof ConfigurableBeanFactory &&
|
||||
((ConfigurableBeanFactory) this.beanFactory).isCurrentlyInCreation(this.targetBeanName)) {
|
||||
logger.warn("Target bean '" + this.targetBeanName + "' is still in creation due to a circular " +
|
||||
"reference - obtained value for property '" + this.propertyPath + "' may be outdated!");
|
||||
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author 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 java.io.Serializable;
|
||||
import javax.inject.Provider;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link org.springframework.beans.factory.FactoryBean} implementation that
|
||||
* returns a value which is a JSR-330 {@link javax.inject.Provider} that in turn
|
||||
* returns a bean sourced from a {@link org.springframework.beans.factory.BeanFactory}.
|
||||
*
|
||||
* <p>This is basically a JSR-330 compliant variant of Spring's good old
|
||||
* {@link ObjectFactoryCreatingFactoryBean}. It can be used for traditional
|
||||
* external dependency injection configuration that targets a property or
|
||||
* constructor argument of type <code>javax.inject.Provider</code>, as an
|
||||
* alternative to JSR-330's <code>@Inject</code> annotation-driven approach.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0.2
|
||||
* @see javax.inject.Provider
|
||||
* @see ObjectFactoryCreatingFactoryBean
|
||||
*/
|
||||
public class ProviderCreatingFactoryBean extends AbstractFactoryBean<Provider> {
|
||||
|
||||
private String targetBeanName;
|
||||
|
||||
|
||||
/**
|
||||
* Set the name of the target bean.
|
||||
* <p>The target does not <i>have</> to be a non-singleton bean, but realisticially
|
||||
* always will be (because if the target bean were a singleton, then said singleton
|
||||
* bean could simply be injected straight into the dependent object, thus obviating
|
||||
* the need for the extra level of indirection afforded by this factory approach).
|
||||
*/
|
||||
public void setTargetBeanName(String targetBeanName) {
|
||||
this.targetBeanName = targetBeanName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.hasText(this.targetBeanName, "Property 'targetBeanName' is required");
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class getObjectType() {
|
||||
return Provider.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Provider createInstance() {
|
||||
return new TargetBeanProvider(getBeanFactory(), this.targetBeanName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Independent inner class - for serialization purposes.
|
||||
*/
|
||||
private static class TargetBeanProvider implements Provider, Serializable {
|
||||
|
||||
private final BeanFactory beanFactory;
|
||||
|
||||
private final String targetBeanName;
|
||||
|
||||
public TargetBeanProvider(BeanFactory beanFactory, String targetBeanName) {
|
||||
this.beanFactory = beanFactory;
|
||||
this.targetBeanName = targetBeanName;
|
||||
}
|
||||
|
||||
public Object get() throws BeansException {
|
||||
return this.beanFactory.getBean(this.targetBeanName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+28
-2
@@ -392,6 +392,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
Object result = existingBean;
|
||||
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
|
||||
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
|
||||
if (result == null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -402,6 +405,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
Object result = existingBean;
|
||||
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
|
||||
result = beanProcessor.postProcessAfterInitialization(result, beanName);
|
||||
if (result == null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -682,11 +688,14 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
*/
|
||||
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
|
||||
Object exposedObject = bean;
|
||||
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
|
||||
if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
|
||||
for (BeanPostProcessor bp : getBeanPostProcessors()) {
|
||||
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
|
||||
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
|
||||
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
|
||||
if (exposedObject == null) {
|
||||
return exposedObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1130,7 +1139,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
|
||||
// Do not allow eager init for type matching in case of a prioritized post-processor.
|
||||
boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
|
||||
DependencyDescriptor desc = new DependencyDescriptor(methodParam, false, eager);
|
||||
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
|
||||
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
|
||||
if (autowiredArgument != null) {
|
||||
pvs.add(propertyName, autowiredArgument);
|
||||
@@ -1553,4 +1562,21 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
this.factoryBeanInstanceCache.remove(beanName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Special DependencyDescriptor variant for autowire="byType".
|
||||
* Always optional; never considering the parameter name for choosing a primary candidate.
|
||||
*/
|
||||
private static class AutowireByTypeDependencyDescriptor extends DependencyDescriptor {
|
||||
|
||||
public AutowireByTypeDependencyDescriptor(MethodParameter methodParameter, boolean eager) {
|
||||
super(methodParameter, false, eager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDependencyName() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+30
-3
@@ -57,6 +57,7 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.beans.factory.SmartFactoryBean;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.BeanExpressionContext;
|
||||
import org.springframework.beans.factory.config.BeanExpressionResolver;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
@@ -222,7 +223,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
* @throws BeansException if the bean could not be created
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T doGetBean(
|
||||
protected <T> T doGetBean(
|
||||
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
|
||||
throws BeansException {
|
||||
|
||||
@@ -473,7 +474,20 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
return parentBeanFactory.isTypeMatch(originalBeanName(name), targetType);
|
||||
}
|
||||
|
||||
// Retrieve corresponding bean definition.
|
||||
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
|
||||
|
||||
// Check decorated bean definition, if any: We assume it'll be easier
|
||||
// to determine the decorated bean's type than the proxy's type.
|
||||
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
|
||||
if (dbd != null && !BeanFactoryUtils.isFactoryDereference(name)) {
|
||||
RootBeanDefinition tbd = getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);
|
||||
Class targetClass = predictBeanType(dbd.getBeanName(), tbd, FactoryBean.class, typeToMatch);
|
||||
if (targetClass != null && !FactoryBean.class.isAssignableFrom(targetClass)) {
|
||||
return typeToMatch.isAssignableFrom(targetClass);
|
||||
}
|
||||
}
|
||||
|
||||
Class beanClass = predictBeanType(beanName, mbd, FactoryBean.class, typeToMatch);
|
||||
if (beanClass == null) {
|
||||
return false;
|
||||
@@ -520,12 +534,24 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
}
|
||||
|
||||
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
|
||||
|
||||
// Check decorated bean definition, if any: We assume it'll be easier
|
||||
// to determine the decorated bean's type than the proxy's type.
|
||||
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
|
||||
if (dbd != null && !BeanFactoryUtils.isFactoryDereference(name)) {
|
||||
RootBeanDefinition tbd = getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);
|
||||
Class targetClass = predictBeanType(dbd.getBeanName(), tbd);
|
||||
if (targetClass != null && !FactoryBean.class.isAssignableFrom(targetClass)) {
|
||||
return targetClass;
|
||||
}
|
||||
}
|
||||
|
||||
Class beanClass = predictBeanType(beanName, mbd);
|
||||
|
||||
// Check bean class whether we're dealing with a FactoryBean.
|
||||
if (beanClass != null && FactoryBean.class.isAssignableFrom(beanClass)) {
|
||||
if (!BeanFactoryUtils.isFactoryDereference(name)) {
|
||||
// If it's a FactoryBean, we want to look at what it creates, not the factory class.
|
||||
// If it's a FactoryBean, we want to look at what it creates, not at the factory class.
|
||||
return getTypeForFactoryBean(beanName, mbd);
|
||||
}
|
||||
else {
|
||||
@@ -901,6 +927,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
}
|
||||
|
||||
public boolean isCurrentlyInCreation(String beanName) {
|
||||
Assert.notNull(beanName, "Bean name must not be null");
|
||||
return isSingletonCurrentlyInCreation(beanName) || isPrototypeCurrentlyInCreation(beanName);
|
||||
}
|
||||
|
||||
@@ -1241,7 +1268,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
if (this.beanExpressionResolver == null) {
|
||||
return value;
|
||||
}
|
||||
Scope scope = getRegisteredScope(beanDefinition.getScope());
|
||||
Scope scope = (beanDefinition != null ? getRegisteredScope(beanDefinition.getScope()) : null);
|
||||
return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope));
|
||||
}
|
||||
|
||||
|
||||
+10
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -136,11 +136,15 @@ abstract class AutowireUtils {
|
||||
* @return the resolved value
|
||||
*/
|
||||
public static Object resolveAutowiringValue(Object autowiringValue, Class requiredType) {
|
||||
if (autowiringValue instanceof ObjectFactory && !requiredType.isInstance(autowiringValue) &&
|
||||
autowiringValue instanceof Serializable && requiredType.isInterface()) {
|
||||
autowiringValue = Proxy.newProxyInstance(
|
||||
requiredType.getClassLoader(), new Class[] {requiredType},
|
||||
new ObjectFactoryDelegatingInvocationHandler((ObjectFactory) autowiringValue));
|
||||
if (autowiringValue instanceof ObjectFactory && !requiredType.isInstance(autowiringValue)) {
|
||||
ObjectFactory factory = (ObjectFactory) autowiringValue;
|
||||
if (autowiringValue instanceof Serializable && requiredType.isInterface()) {
|
||||
autowiringValue = Proxy.newProxyInstance(requiredType.getClassLoader(),
|
||||
new Class[] {requiredType}, new ObjectFactoryDelegatingInvocationHandler(factory));
|
||||
}
|
||||
else {
|
||||
return factory.getObject();
|
||||
}
|
||||
}
|
||||
return autowiringValue;
|
||||
}
|
||||
|
||||
+50
-25
@@ -42,6 +42,7 @@ import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.UnsatisfiedDependencyException;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
|
||||
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||
import org.springframework.beans.factory.config.TypedStringValue;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
@@ -51,6 +52,7 @@ import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.MethodInvoker;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Helper class for resolving constructors and factory methods.
|
||||
@@ -108,6 +110,7 @@ class ConstructorResolver {
|
||||
this.beanFactory.initBeanWrapper(bw);
|
||||
|
||||
Constructor constructorToUse = null;
|
||||
ArgumentsHolder argsHolderToUse = null;
|
||||
Object[] argsToUse = null;
|
||||
|
||||
if (explicitArgs != null) {
|
||||
@@ -175,7 +178,7 @@ class ConstructorResolver {
|
||||
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
|
||||
}
|
||||
|
||||
ArgumentsHolder args;
|
||||
ArgumentsHolder argsHolder;
|
||||
if (resolvedValues != null) {
|
||||
try {
|
||||
String[] paramNames = null;
|
||||
@@ -188,7 +191,7 @@ class ConstructorResolver {
|
||||
paramNames = pnd.getParameterNames(candidate);
|
||||
}
|
||||
}
|
||||
args = createArgumentArray(
|
||||
argsHolder = createArgumentArray(
|
||||
beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
|
||||
}
|
||||
catch (UnsatisfiedDependencyException ex) {
|
||||
@@ -219,15 +222,16 @@ class ConstructorResolver {
|
||||
if (paramTypes.length != explicitArgs.length) {
|
||||
continue;
|
||||
}
|
||||
args = new ArgumentsHolder(explicitArgs);
|
||||
argsHolder = new ArgumentsHolder(explicitArgs);
|
||||
}
|
||||
|
||||
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
|
||||
args.getTypeDifferenceWeight(paramTypes) : args.getAssignabilityWeight(paramTypes));
|
||||
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
|
||||
// Choose this constructor if it represents the closest match.
|
||||
if (typeDiffWeight < minTypeDiffWeight) {
|
||||
constructorToUse = candidate;
|
||||
argsToUse = args.arguments;
|
||||
argsHolderToUse = argsHolder;
|
||||
argsToUse = argsHolder.arguments;
|
||||
minTypeDiffWeight = typeDiffWeight;
|
||||
ambiguousConstructors = null;
|
||||
}
|
||||
@@ -253,6 +257,7 @@ class ConstructorResolver {
|
||||
|
||||
if (explicitArgs == null) {
|
||||
mbd.resolvedConstructorOrFactoryMethod = constructorToUse;
|
||||
argsHolderToUse.storeCache(mbd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,8 +275,8 @@ class ConstructorResolver {
|
||||
}, beanFactory.getAccessControlContext());
|
||||
}
|
||||
else {
|
||||
beanInstance = beanFactory.getInstantiationStrategy().instantiate(
|
||||
mbd, beanName, beanFactory, constructorToUse, argsToUse);
|
||||
beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
|
||||
mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
|
||||
}
|
||||
|
||||
bw.setWrappedInstance(beanInstance);
|
||||
@@ -361,6 +366,7 @@ class ConstructorResolver {
|
||||
}
|
||||
|
||||
Method factoryMethodToUse = null;
|
||||
ArgumentsHolder argsHolderToUse = null;
|
||||
Object[] argsToUse = null;
|
||||
|
||||
if (explicitArgs != null) {
|
||||
@@ -432,7 +438,7 @@ class ConstructorResolver {
|
||||
Class[] paramTypes = candidate.getParameterTypes();
|
||||
|
||||
if (paramTypes.length >= minNrOfArgs) {
|
||||
ArgumentsHolder args;
|
||||
ArgumentsHolder argsHolder;
|
||||
|
||||
if (resolvedValues != null) {
|
||||
// Resolved constructor arguments: type conversion and/or autowiring necessary.
|
||||
@@ -442,7 +448,7 @@ class ConstructorResolver {
|
||||
if (pnd != null) {
|
||||
paramNames = pnd.getParameterNames(candidate);
|
||||
}
|
||||
args = createArgumentArray(
|
||||
argsHolder = createArgumentArray(
|
||||
beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
|
||||
}
|
||||
catch (UnsatisfiedDependencyException ex) {
|
||||
@@ -474,15 +480,16 @@ class ConstructorResolver {
|
||||
if (paramTypes.length != explicitArgs.length) {
|
||||
continue;
|
||||
}
|
||||
args = new ArgumentsHolder(explicitArgs);
|
||||
argsHolder = new ArgumentsHolder(explicitArgs);
|
||||
}
|
||||
|
||||
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
|
||||
args.getTypeDifferenceWeight(paramTypes) : args.getAssignabilityWeight(paramTypes));
|
||||
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
|
||||
// Choose this factory method if it represents the closest match.
|
||||
if (typeDiffWeight < minTypeDiffWeight) {
|
||||
factoryMethodToUse = candidate;
|
||||
argsToUse = args.arguments;
|
||||
argsHolderToUse = argsHolder;
|
||||
argsToUse = argsHolder.arguments;
|
||||
minTypeDiffWeight = typeDiffWeight;
|
||||
ambiguousFactoryMethods = null;
|
||||
}
|
||||
@@ -497,12 +504,25 @@ class ConstructorResolver {
|
||||
}
|
||||
|
||||
if (factoryMethodToUse == null) {
|
||||
boolean hasArgs = resolvedValues.getArgumentCount() > 0;
|
||||
String argDesc = "";
|
||||
if (hasArgs) {
|
||||
List<String> argTypes = new ArrayList<String>();
|
||||
for (ValueHolder value : resolvedValues.getIndexedArgumentValues().values()) {
|
||||
String argType = value.getType() != null ?
|
||||
ClassUtils.getShortName(value.getType()) : value.getValue().getClass().getSimpleName();
|
||||
argTypes.add(argType);
|
||||
}
|
||||
argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
|
||||
}
|
||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
||||
"No matching factory method found: " +
|
||||
(mbd.getFactoryBeanName() != null ?
|
||||
"factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
|
||||
"factory method '" + mbd.getFactoryMethodName() + "'. " +
|
||||
"Check that a method of the specified name exists and that it is " +
|
||||
"factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
|
||||
"factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +
|
||||
"Check that a method with the specified name " +
|
||||
(hasArgs ? "and arguments " : "") +
|
||||
"exists and that it is " +
|
||||
(isStatic ? "static" : "non-static") + ".");
|
||||
}
|
||||
else if (void.class.equals(factoryMethodToUse.getReturnType())) {
|
||||
@@ -519,6 +539,7 @@ class ConstructorResolver {
|
||||
|
||||
if (explicitArgs == null) {
|
||||
mbd.resolvedConstructorOrFactoryMethod = factoryMethodToUse;
|
||||
argsHolderToUse.storeCache(mbd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -625,7 +646,6 @@ class ConstructorResolver {
|
||||
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders =
|
||||
new HashSet<ConstructorArgumentValues.ValueHolder>(paramTypes.length);
|
||||
Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);
|
||||
boolean resolveNecessary = false;
|
||||
|
||||
for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
|
||||
Class<?> paramType = paramTypes[paramIndex];
|
||||
@@ -662,7 +682,7 @@ class ConstructorResolver {
|
||||
args.preparedArguments[paramIndex] = convertedValue;
|
||||
}
|
||||
else {
|
||||
resolveNecessary = true;
|
||||
args.resolveNecessary = true;
|
||||
args.preparedArguments[paramIndex] = sourceValue;
|
||||
}
|
||||
}
|
||||
@@ -692,7 +712,7 @@ class ConstructorResolver {
|
||||
args.rawArguments[paramIndex] = autowiredArgument;
|
||||
args.arguments[paramIndex] = autowiredArgument;
|
||||
args.preparedArguments[paramIndex] = new AutowiredArgumentMarker();
|
||||
resolveNecessary = true;
|
||||
args.resolveNecessary = true;
|
||||
}
|
||||
catch (BeansException ex) {
|
||||
throw new UnsatisfiedDependencyException(
|
||||
@@ -709,13 +729,6 @@ class ConstructorResolver {
|
||||
}
|
||||
}
|
||||
|
||||
if (resolveNecessary) {
|
||||
mbd.preparedConstructorArguments = args.preparedArguments;
|
||||
}
|
||||
else {
|
||||
mbd.resolvedConstructorArguments = args.arguments;
|
||||
}
|
||||
mbd.constructorArgumentsResolved = true;
|
||||
return args;
|
||||
}
|
||||
|
||||
@@ -784,6 +797,8 @@ class ConstructorResolver {
|
||||
|
||||
public Object preparedArguments[];
|
||||
|
||||
public boolean resolveNecessary = false;
|
||||
|
||||
public ArgumentsHolder(int size) {
|
||||
this.rawArguments = new Object[size];
|
||||
this.arguments = new Object[size];
|
||||
@@ -819,6 +834,16 @@ class ConstructorResolver {
|
||||
}
|
||||
return Integer.MAX_VALUE - 1024;
|
||||
}
|
||||
|
||||
public void storeCache(RootBeanDefinition mbd) {
|
||||
if (this.resolveNecessary) {
|
||||
mbd.preparedConstructorArguments = this.preparedArguments;
|
||||
}
|
||||
else {
|
||||
mbd.resolvedConstructorArguments = this.arguments;
|
||||
}
|
||||
mbd.constructorArgumentsResolved = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+15
-2
@@ -248,6 +248,17 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
public <T> T getBean(Class<T> requiredType) 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 (getBeanDefinition(beanName).isAutowireCandidate()) {
|
||||
autowireCandidates.add(beanName);
|
||||
}
|
||||
}
|
||||
if (autowireCandidates.size() > 0) {
|
||||
beanNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
|
||||
}
|
||||
}
|
||||
if (beanNames.length == 1) {
|
||||
return getBean(beanNames[0], requiredType);
|
||||
}
|
||||
@@ -262,6 +273,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
@Override
|
||||
public boolean containsBeanDefinition(String beanName) {
|
||||
Assert.notNull(beanName, "Bean name must not be null");
|
||||
return this.beanDefinitionMap.containsKey(beanName);
|
||||
}
|
||||
|
||||
@@ -574,7 +586,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
|
||||
throws BeanDefinitionStoreException {
|
||||
|
||||
Assert.hasText(beanName, "'beanName' must not be empty");
|
||||
Assert.hasText(beanName, "Bean name must not be empty");
|
||||
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
|
||||
|
||||
if (beanDefinition instanceof AbstractBeanDefinition) {
|
||||
@@ -693,7 +705,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
if (value != null) {
|
||||
if (value instanceof String) {
|
||||
String strVal = resolveEmbeddedValue((String) value);
|
||||
value = evaluateBeanDefinitionString(strVal, getMergedBeanDefinition(beanName));
|
||||
BeanDefinition bd = (containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
|
||||
value = evaluateBeanDefinitionString(strVal, bd);
|
||||
}
|
||||
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
|
||||
return converter.convertIfNecessary(value, type);
|
||||
|
||||
+6
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -363,11 +363,12 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
||||
* @param dependentBeanName the name of the dependent bean
|
||||
*/
|
||||
public void registerDependentBean(String beanName, String dependentBeanName) {
|
||||
String canonicalName = canonicalName(beanName);
|
||||
synchronized (this.dependentBeanMap) {
|
||||
Set<String> dependentBeans = this.dependentBeanMap.get(beanName);
|
||||
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
|
||||
if (dependentBeans == null) {
|
||||
dependentBeans = new LinkedHashSet<String>(8);
|
||||
this.dependentBeanMap.put(beanName, dependentBeans);
|
||||
this.dependentBeanMap.put(canonicalName, dependentBeans);
|
||||
}
|
||||
dependentBeans.add(dependentBeanName);
|
||||
}
|
||||
@@ -377,7 +378,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
||||
dependenciesForBean = new LinkedHashSet<String>(8);
|
||||
this.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean);
|
||||
}
|
||||
dependenciesForBean.add(beanName);
|
||||
dependenciesForBean.add(canonicalName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,7 +456,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
||||
removeSingleton(beanName);
|
||||
|
||||
// Destroy the corresponding DisposableBean instance.
|
||||
DisposableBean disposableBean = null;
|
||||
DisposableBean disposableBean;
|
||||
synchronized (this.disposableBeans) {
|
||||
disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
|
||||
}
|
||||
|
||||
+3
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -123,8 +123,6 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
|
||||
final FactoryBean factory, final String beanName, final boolean shouldPostProcess)
|
||||
throws BeanCreationException {
|
||||
|
||||
|
||||
|
||||
Object object;
|
||||
try {
|
||||
if (System.getSecurityManager() != null) {
|
||||
@@ -135,7 +133,8 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
|
||||
return factory.getObject();
|
||||
}
|
||||
}, acc);
|
||||
} catch (PrivilegedActionException pae) {
|
||||
}
|
||||
catch (PrivilegedActionException pae) {
|
||||
throw pae.getException();
|
||||
}
|
||||
}
|
||||
|
||||
+13
-15
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2002-2005 the original author or authors.
|
||||
*
|
||||
* Copyright 2002-2010 the original author 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.
|
||||
@@ -32,7 +32,7 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
* @since 1.1
|
||||
*/
|
||||
public interface InstantiationStrategy {
|
||||
|
||||
|
||||
/**
|
||||
* Return an instance of the bean with the given name in this factory.
|
||||
* @param beanDefinition the bean definition
|
||||
@@ -43,9 +43,9 @@ public interface InstantiationStrategy {
|
||||
* @return a bean instance for this bean definition
|
||||
* @throws BeansException if the instantiation failed
|
||||
*/
|
||||
Object instantiate(
|
||||
RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) throws BeansException;
|
||||
|
||||
Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner)
|
||||
throws BeansException;
|
||||
|
||||
/**
|
||||
* Return an instance of the bean with the given name in this factory,
|
||||
* creating it via the given constructor.
|
||||
@@ -59,10 +59,9 @@ public interface InstantiationStrategy {
|
||||
* @return a bean instance for this bean definition
|
||||
* @throws BeansException if the instantiation failed
|
||||
*/
|
||||
Object instantiate(
|
||||
RootBeanDefinition beanDefinition, String beanName, BeanFactory owner,
|
||||
Constructor ctor, Object[] args) throws BeansException;
|
||||
|
||||
Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner,
|
||||
Constructor<?> ctor, Object[] args) throws BeansException;
|
||||
|
||||
/**
|
||||
* Return an instance of the bean with the given name in this factory,
|
||||
* creating it via the given factory method.
|
||||
@@ -78,8 +77,7 @@ public interface InstantiationStrategy {
|
||||
* @return a bean instance for this bean definition
|
||||
* @throws BeansException if the instantiation failed
|
||||
*/
|
||||
Object instantiate(
|
||||
RootBeanDefinition beanDefinition, String beanName, BeanFactory owner,
|
||||
Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner,
|
||||
Object factoryBean, Method factoryMethod, Object[] args) throws BeansException;
|
||||
|
||||
|
||||
}
|
||||
|
||||
+14
-2
@@ -24,6 +24,7 @@ import java.util.Set;
|
||||
|
||||
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.util.Assert;
|
||||
|
||||
@@ -53,6 +54,8 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
|
||||
private final Set<String> externallyManagedDestroyMethods = Collections.synchronizedSet(new HashSet<String>());
|
||||
|
||||
private BeanDefinitionHolder decoratedDefinition;
|
||||
|
||||
boolean isFactoryMethodUnique;
|
||||
|
||||
/** Package-visible field for caching the resolved constructor or factory method */
|
||||
@@ -75,7 +78,6 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
|
||||
final Object postProcessingLock = new Object();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new RootBeanDefinition, to be configured through its bean
|
||||
* properties and configuration methods.
|
||||
@@ -224,7 +226,9 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
RootBeanDefinition(BeanDefinition original) {
|
||||
super(original);
|
||||
if (original instanceof RootBeanDefinition) {
|
||||
this.isFactoryMethodUnique = ((RootBeanDefinition) original).isFactoryMethodUnique;
|
||||
RootBeanDefinition originalRbd = (RootBeanDefinition) original;
|
||||
this.decoratedDefinition = originalRbd.decoratedDefinition;
|
||||
this.isFactoryMethodUnique = originalRbd.isFactoryMethodUnique;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,6 +293,14 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
return this.externallyManagedDestroyMethods.contains(destroyMethod);
|
||||
}
|
||||
|
||||
public void setDecoratedDefinition(BeanDefinitionHolder decoratedDefinition) {
|
||||
this.decoratedDefinition = decoratedDefinition;
|
||||
}
|
||||
|
||||
public BeanDefinitionHolder getDecoratedDefinition() {
|
||||
return this.decoratedDefinition;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public RootBeanDefinition cloneBeanDefinition() {
|
||||
|
||||
+12
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -42,12 +42,10 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class SimpleInstantiationStrategy implements InstantiationStrategy {
|
||||
|
||||
public Object instantiate(
|
||||
RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
|
||||
|
||||
public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
|
||||
// Don't override the class with CGLIB if no overrides.
|
||||
if (beanDefinition.getMethodOverrides().isEmpty()) {
|
||||
Constructor constructorToUse = (Constructor) beanDefinition.resolvedConstructorOrFactoryMethod;
|
||||
Constructor<?> constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;
|
||||
if (constructorToUse == null) {
|
||||
final Class clazz = beanDefinition.getBeanClass();
|
||||
if (clazz.isInterface()) {
|
||||
@@ -60,7 +58,8 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
|
||||
return clazz.getDeclaredConstructor((Class[]) null);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
|
||||
}
|
||||
beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;
|
||||
@@ -90,9 +89,8 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
|
||||
"Method Injection not supported in SimpleInstantiationStrategy");
|
||||
}
|
||||
|
||||
public Object instantiate(
|
||||
RootBeanDefinition beanDefinition, String beanName, BeanFactory owner,
|
||||
final Constructor ctor, Object[] args) {
|
||||
public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner,
|
||||
final Constructor<?> ctor, Object[] args) {
|
||||
|
||||
if (beanDefinition.getMethodOverrides().isEmpty()) {
|
||||
if (System.getSecurityManager() != null) {
|
||||
@@ -117,16 +115,14 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
|
||||
* the Method Injection specified in the given RootBeanDefinition.
|
||||
* Instantiation should use the given constructor and parameters.
|
||||
*/
|
||||
protected Object instantiateWithMethodInjection(
|
||||
RootBeanDefinition beanDefinition, String beanName, BeanFactory owner,
|
||||
Constructor ctor, Object[] args) {
|
||||
protected Object instantiateWithMethodInjection(RootBeanDefinition beanDefinition,
|
||||
String beanName, BeanFactory owner, Constructor ctor, Object[] args) {
|
||||
|
||||
throw new UnsupportedOperationException(
|
||||
"Method Injection not supported in SimpleInstantiationStrategy");
|
||||
}
|
||||
|
||||
public Object instantiate(
|
||||
RootBeanDefinition beanDefinition, String beanName, BeanFactory owner,
|
||||
public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner,
|
||||
Object factoryBean, final Method factoryMethod, Object[] args) {
|
||||
|
||||
try {
|
||||
@@ -159,4 +155,5 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
|
||||
"Factory method [" + factoryMethod + "] threw exception", ex.getTargetException());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+36
-28
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -621,7 +621,7 @@ public class BeanDefinitionParserDelegate {
|
||||
NodeList nl = ele.getChildNodes();
|
||||
for (int i = 0; i < nl.getLength(); i++) {
|
||||
Node node = nl.item(i);
|
||||
if (node instanceof Element && nodeNameEquals(node, META_ELEMENT)) {
|
||||
if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) {
|
||||
Element metaElement = (Element) node;
|
||||
String key = metaElement.getAttribute(KEY_ATTRIBUTE);
|
||||
String value = metaElement.getAttribute(VALUE_ATTRIBUTE);
|
||||
@@ -680,7 +680,7 @@ public class BeanDefinitionParserDelegate {
|
||||
NodeList nl = beanEle.getChildNodes();
|
||||
for (int i = 0; i < nl.getLength(); i++) {
|
||||
Node node = nl.item(i);
|
||||
if (node instanceof Element && nodeNameEquals(node, CONSTRUCTOR_ARG_ELEMENT)) {
|
||||
if (isCandidateElement(node) && nodeNameEquals(node, CONSTRUCTOR_ARG_ELEMENT)) {
|
||||
parseConstructorArgElement((Element) node, bd);
|
||||
}
|
||||
}
|
||||
@@ -693,7 +693,7 @@ public class BeanDefinitionParserDelegate {
|
||||
NodeList nl = beanEle.getChildNodes();
|
||||
for (int i = 0; i < nl.getLength(); i++) {
|
||||
Node node = nl.item(i);
|
||||
if (node instanceof Element && nodeNameEquals(node, PROPERTY_ELEMENT)) {
|
||||
if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
|
||||
parsePropertyElement((Element) node, bd);
|
||||
}
|
||||
}
|
||||
@@ -706,7 +706,7 @@ public class BeanDefinitionParserDelegate {
|
||||
NodeList nl = beanEle.getChildNodes();
|
||||
for (int i = 0; i < nl.getLength(); i++) {
|
||||
Node node = nl.item(i);
|
||||
if (node instanceof Element && nodeNameEquals(node, QUALIFIER_ELEMENT)) {
|
||||
if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ELEMENT)) {
|
||||
parseQualifierElement((Element) node, bd);
|
||||
}
|
||||
}
|
||||
@@ -719,7 +719,7 @@ public class BeanDefinitionParserDelegate {
|
||||
NodeList nl = beanEle.getChildNodes();
|
||||
for (int i = 0; i < nl.getLength(); i++) {
|
||||
Node node = nl.item(i);
|
||||
if (node instanceof Element && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)) {
|
||||
if (isCandidateElement(node) && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)) {
|
||||
Element ele = (Element) node;
|
||||
String methodName = ele.getAttribute(NAME_ATTRIBUTE);
|
||||
String beanRef = ele.getAttribute(BEAN_ELEMENT);
|
||||
@@ -737,7 +737,7 @@ public class BeanDefinitionParserDelegate {
|
||||
NodeList nl = beanEle.getChildNodes();
|
||||
for (int i = 0; i < nl.getLength(); i++) {
|
||||
Node node = nl.item(i);
|
||||
if (node instanceof Element && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) {
|
||||
if (isCandidateElement(node) && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) {
|
||||
Element replacedMethodEle = (Element) node;
|
||||
String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE);
|
||||
String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE);
|
||||
@@ -860,7 +860,7 @@ public class BeanDefinitionParserDelegate {
|
||||
NodeList nl = ele.getChildNodes();
|
||||
for (int i = 0; i < nl.getLength(); i++) {
|
||||
Node node = nl.item(i);
|
||||
if (node instanceof Element && nodeNameEquals(node, QUALIFIER_ATTRIBUTE_ELEMENT)) {
|
||||
if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ATTRIBUTE_ELEMENT)) {
|
||||
Element attributeEle = (Element) node;
|
||||
String attributeName = attributeEle.getAttribute(KEY_ATTRIBUTE);
|
||||
String attributeValue = attributeEle.getAttribute(VALUE_ATTRIBUTE);
|
||||
@@ -952,7 +952,7 @@ public class BeanDefinitionParserDelegate {
|
||||
* <code><value></code> tag that might be created
|
||||
*/
|
||||
public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
|
||||
if (!isDefaultNamespace(getNamespaceURI(ele))) {
|
||||
if (!isDefaultNamespace(ele)) {
|
||||
return parseNestedCustomElement(ele, bd);
|
||||
}
|
||||
else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
|
||||
@@ -1384,10 +1384,6 @@ public class BeanDefinitionParserDelegate {
|
||||
return originalDef;
|
||||
}
|
||||
|
||||
public boolean isDefaultNamespace(String namespaceUri) {
|
||||
return (!StringUtils.hasLength(namespaceUri) || BEANS_NAMESPACE_URI.equals(namespaceUri));
|
||||
}
|
||||
|
||||
private BeanDefinitionHolder parseNestedCustomElement(Element ele, BeanDefinition containingBd) {
|
||||
BeanDefinition innerDefinition = parseCustomElement(ele, containingBd);
|
||||
if (innerDefinition == null) {
|
||||
@@ -1404,36 +1400,48 @@ public class BeanDefinitionParserDelegate {
|
||||
return new BeanDefinitionHolder(innerDefinition, id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the namespace URI for the supplied node. The default implementation uses {@link Node#getNamespaceURI}.
|
||||
* Get the namespace URI for the supplied node. The default implementation uses {@link Node#getNamespaceURI}.
|
||||
* Subclasses may override the default implementation to provide a different namespace identification mechanism.
|
||||
* @param node the node
|
||||
* @return the namespace URI of the the node.
|
||||
*/
|
||||
public String getNamespaceURI(Node node) {
|
||||
return node.getNamespaceURI();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the name of the supplied node is equal to the supplied name.
|
||||
* The default implementation checks the supplied desired name against both {@link Node#getNodeName)
|
||||
* and {@link #getLoclName}.
|
||||
* Subclasses may override the default implementation to provide a different mechanism for comparing node names.
|
||||
* Ges the local name for the supplied {@link Node}. The default implementation calls {@link Node#getLocalName}.
|
||||
* Subclasses may override the default implementation to provide a different mechanism for getting the local name.
|
||||
* @param node the <code>Node</code>
|
||||
*/
|
||||
public String getLocalName(Node node) {
|
||||
return node.getLocalName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the name of the supplied node is equal to the supplied name.
|
||||
* <p>The default implementation checks the supplied desired name against both
|
||||
* {@link Node#getNodeName()) and {@link Node#getLocalName()}.
|
||||
* <p>Subclasses may override the default implementation to provide a different
|
||||
* mechanism for comparing node names.
|
||||
* @param node the node to compare
|
||||
* @param desiredName the name to check for
|
||||
* @return <code>true</code> if the names are equal otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean nodeNameEquals(Node node, String desiredName) {
|
||||
return desiredName.equals(node.getNodeName()) || desiredName.equals(getLocalName(node));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the local name for the supplied {@link Node}. The default implementation calls {@link Node#getLocalName}.
|
||||
* Subclasses may override the default implementation to provide a different mechanism for getting the local name.
|
||||
* @param node the <code>Node</code>
|
||||
* @return the local name of the supplied <code>Node</code>.
|
||||
*/
|
||||
public String getLocalName(Node node) {
|
||||
return node.getLocalName();
|
||||
public boolean isDefaultNamespace(String namespaceUri) {
|
||||
return (!StringUtils.hasLength(namespaceUri) || BEANS_NAMESPACE_URI.equals(namespaceUri));
|
||||
}
|
||||
|
||||
public boolean isDefaultNamespace(Node node) {
|
||||
return isDefaultNamespace(getNamespaceURI(node));
|
||||
}
|
||||
|
||||
private boolean isCandidateElement(Node node) {
|
||||
return (node instanceof Element && (isDefaultNamespace(node) || !isDefaultNamespace(node.getParentNode())));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -122,14 +122,13 @@ public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocume
|
||||
* @param root the DOM root element of the document
|
||||
*/
|
||||
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
|
||||
if (delegate.isDefaultNamespace(delegate.getNamespaceURI(root))) {
|
||||
if (delegate.isDefaultNamespace(root)) {
|
||||
NodeList nl = root.getChildNodes();
|
||||
for (int i = 0; i < nl.getLength(); i++) {
|
||||
Node node = nl.item(i);
|
||||
if (node instanceof Element) {
|
||||
Element ele = (Element) node;
|
||||
String namespaceUri = delegate.getNamespaceURI(ele);
|
||||
if (delegate.isDefaultNamespace(namespaceUri)) {
|
||||
if (delegate.isDefaultNamespace(ele)) {
|
||||
parseDefaultElement(ele, delegate);
|
||||
}
|
||||
else {
|
||||
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author 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 org.xml.sax.InputSource;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceEditor;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Editor for <code>org.xml.sax.InputSource</code>, converting from a
|
||||
* Spring resource location String to a SAX InputSource object.
|
||||
*
|
||||
* <p>Supports Spring-style URL notation: any fully qualified standard URL
|
||||
* ("file:", "http:", etc) and Spring's special "classpath:" pseudo-URL.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0.3
|
||||
* @see org.xml.sax.InputSource
|
||||
* @see org.springframework.core.io.ResourceEditor
|
||||
* @see org.springframework.core.io.ResourceLoader
|
||||
* @see org.springframework.beans.propertyeditors.URLEditor
|
||||
* @see org.springframework.beans.propertyeditors.FileEditor
|
||||
*/
|
||||
public class InputSourceEditor extends PropertyEditorSupport {
|
||||
|
||||
private final ResourceEditor resourceEditor;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new InputSourceEditor,
|
||||
* using the default ResourceEditor underneath.
|
||||
*/
|
||||
public InputSourceEditor() {
|
||||
this.resourceEditor = new ResourceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new InputSourceEditor,
|
||||
* using the given ResourceEditor underneath.
|
||||
* @param resourceEditor the ResourceEditor to use
|
||||
*/
|
||||
public InputSourceEditor(ResourceEditor resourceEditor) {
|
||||
Assert.notNull(resourceEditor, "ResourceEditor must not be null");
|
||||
this.resourceEditor = resourceEditor;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setAsText(String text) throws IllegalArgumentException {
|
||||
this.resourceEditor.setAsText(text);
|
||||
Resource resource = (Resource) this.resourceEditor.getValue();
|
||||
try {
|
||||
setValue(resource != null ? new InputSource(resource.getURL().toString()) : null);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalArgumentException(
|
||||
"Could not retrieve URL for " + resource + ": " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsText() {
|
||||
InputSource value = (InputSource) getValue();
|
||||
return (value != null ? value.getSystemId() : "");
|
||||
}
|
||||
|
||||
}
|
||||
+4
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.springframework.beans.propertyeditors;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
@@ -25,9 +24,9 @@ import org.springframework.core.io.ResourceEditor;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* One-way PropertyEditor, which can convert from a text string to a
|
||||
* <code>java.io.InputStream</code>, allowing InputStream properties
|
||||
* to be set directly as a text string.
|
||||
* One-way PropertyEditor which can convert from a text String to a
|
||||
* <code>java.io.InputStream</code>, interpreting the given String
|
||||
* as Spring resource location (e.g. a URL String).
|
||||
*
|
||||
* <p>Supports Spring-style URL notation: any fully qualified standard URL
|
||||
* ("file:", "http:", etc) and Spring's special "classpath:" pseudo-URL.
|
||||
|
||||
+9
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -67,7 +67,6 @@ public class URIEditor extends PropertyEditorSupport {
|
||||
/**
|
||||
* Create a new URIEditor, converting "classpath:" locations into
|
||||
* standard URIs (not trying to resolve them into physical resources).
|
||||
*
|
||||
* @param encode indicates whether Strings will be encoded or not
|
||||
*/
|
||||
public URIEditor(boolean encode) {
|
||||
@@ -141,14 +140,16 @@ public class URIEditor extends PropertyEditorSupport {
|
||||
* @throws java.net.URISyntaxException if URI conversion failed
|
||||
*/
|
||||
protected URI createURI(String value) throws URISyntaxException {
|
||||
int idx = value.indexOf(':');
|
||||
if (encode && idx != -1) {
|
||||
String scheme = value.substring(0, idx);
|
||||
String ssp = value.substring(idx + 1);
|
||||
return new URI(scheme, ssp, null);
|
||||
int colonIndex = value.indexOf(':');
|
||||
if (this.encode && colonIndex != -1) {
|
||||
int fragmentIndex = value.indexOf('#', colonIndex + 1);
|
||||
String scheme = value.substring(0, colonIndex);
|
||||
String ssp = value.substring(colonIndex + 1, (fragmentIndex > 0 ? fragmentIndex : value.length()));
|
||||
String fragment = (fragmentIndex > 0 ? value.substring(fragmentIndex + 1) : null);
|
||||
return new URI(scheme, ssp, fragment);
|
||||
}
|
||||
else {
|
||||
// not encoding or the value contains no scheme , fallback to default
|
||||
// not encoding or the value contains no scheme - fallback to default
|
||||
return new URI(value);
|
||||
}
|
||||
}
|
||||
|
||||
+27
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2010 the original author 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,15 +16,20 @@
|
||||
|
||||
package org.springframework.beans.support;
|
||||
|
||||
import java.beans.PropertyEditor;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import org.springframework.beans.PropertyEditorRegistrar;
|
||||
import org.springframework.beans.PropertyEditorRegistry;
|
||||
import org.springframework.beans.PropertyEditorRegistrySupport;
|
||||
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.URIEditor;
|
||||
import org.springframework.beans.propertyeditors.URLEditor;
|
||||
@@ -77,19 +82,33 @@ public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
|
||||
*/
|
||||
public void registerCustomEditors(PropertyEditorRegistry registry) {
|
||||
ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader);
|
||||
registry.registerCustomEditor(Resource.class, baseEditor);
|
||||
registry.registerCustomEditor(InputStream.class, new InputStreamEditor(baseEditor));
|
||||
registry.registerCustomEditor(File.class, new FileEditor(baseEditor));
|
||||
registry.registerCustomEditor(URL.class, new URLEditor(baseEditor));
|
||||
doRegisterEditor(registry, Resource.class, baseEditor);
|
||||
doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
|
||||
doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
|
||||
doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
|
||||
doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));
|
||||
|
||||
ClassLoader classLoader = this.resourceLoader.getClassLoader();
|
||||
registry.registerCustomEditor(Class.class, new ClassEditor(classLoader));
|
||||
registry.registerCustomEditor(URI.class, new URIEditor(classLoader));
|
||||
doRegisterEditor(registry, Class.class, new ClassEditor(classLoader));
|
||||
doRegisterEditor(registry, URI.class, new URIEditor(classLoader));
|
||||
|
||||
if (this.resourceLoader instanceof ResourcePatternResolver) {
|
||||
registry.registerCustomEditor(Resource[].class,
|
||||
doRegisterEditor(registry, Resource[].class,
|
||||
new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override default editor, if possible (since that's what we really mean to do here);
|
||||
* otherwise register as a custom editor.
|
||||
*/
|
||||
private void doRegisterEditor(PropertyEditorRegistry registry, Class requiredType, PropertyEditor editor) {
|
||||
if (registry instanceof PropertyEditorRegistrySupport) {
|
||||
((PropertyEditorRegistrySupport) registry).overrideDefaultEditor(requiredType, editor);
|
||||
}
|
||||
else {
|
||||
registry.registerCustomEditor(requiredType, editor);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+117
-36
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2010 the original author 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,15 +16,6 @@
|
||||
|
||||
package org.springframework.beans.factory;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.MalformedURLException;
|
||||
import java.security.AccessControlContext;
|
||||
@@ -40,12 +31,19 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.security.auth.Subject;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
import test.beans.DerivedTestBean;
|
||||
import test.beans.DummyFactory;
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.LifecycleBean;
|
||||
import test.beans.NestedTestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.NotWritablePropertyException;
|
||||
@@ -61,6 +59,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.config.TypedStringValue;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
@@ -72,6 +71,7 @@ import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.ConstructorDependenciesBean;
|
||||
import org.springframework.beans.factory.xml.DependenciesBean;
|
||||
import org.springframework.beans.propertyeditors.CustomNumberEditor;
|
||||
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||
@@ -80,13 +80,6 @@ import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.util.StopWatch;
|
||||
|
||||
import test.beans.DerivedTestBean;
|
||||
import test.beans.DummyFactory;
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.LifecycleBean;
|
||||
import test.beans.NestedTestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* Tests properties population and autowire behavior.
|
||||
*
|
||||
@@ -96,7 +89,7 @@ import test.beans.TestBean;
|
||||
* @author Sam Brannen
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class DefaultListableBeanFactoryTests {
|
||||
public class DefaultListableBeanFactoryTests {
|
||||
|
||||
private static final Log factoryLog = LogFactory.getLog(DefaultListableBeanFactory.class);
|
||||
|
||||
@@ -730,6 +723,20 @@ public final class DefaultListableBeanFactoryTests {
|
||||
assertTrue("Test bean age is 48", tb.getAge() == 48);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAliasCircle() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
lbf.registerAlias("test", "test2");
|
||||
lbf.registerAlias("test2", "test3");
|
||||
try {
|
||||
lbf.registerAlias("test3", "test");
|
||||
fail("Should have thrown IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBeanDefinitionOverriding() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
@@ -1103,7 +1110,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireWithNoDependencies() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("rod", bd);
|
||||
assertEquals(1, lbf.getBeanDefinitionCount());
|
||||
Object registered = lbf.autowire(NoDependencies.class, AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT, false);
|
||||
@@ -1180,7 +1187,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireConstructor() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("spouse", bd);
|
||||
ConstructorDependenciesBean bean = (ConstructorDependenciesBean)
|
||||
lbf.autowire(ConstructorDependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, true);
|
||||
@@ -1192,7 +1199,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireBeanByName() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("spouse", bd);
|
||||
DependenciesBean bean = (DependenciesBean)
|
||||
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true);
|
||||
@@ -1204,7 +1211,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireBeanByNameWithDependencyCheck() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("spous", bd);
|
||||
try {
|
||||
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true);
|
||||
@@ -1218,17 +1225,49 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireBeanByNameWithNoDependencyCheck() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("spous", bd);
|
||||
DependenciesBean bean = (DependenciesBean)
|
||||
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false);
|
||||
assertNull(bean.getSpouse());
|
||||
}
|
||||
|
||||
@Test(expected=NoSuchBeanDefinitionException.class)
|
||||
public void testGetBeanByTypeWithAmbiguity() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("bd1", bd1);
|
||||
lbf.registerBeanDefinition("bd2", bd2);
|
||||
lbf.getBean(TestBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBeanByTypeFiltersOutNonAutowireCandidates() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
|
||||
RootBeanDefinition na1 = new RootBeanDefinition(TestBean.class);
|
||||
na1.setAutowireCandidate(false);
|
||||
|
||||
lbf.registerBeanDefinition("bd1", bd1);
|
||||
lbf.registerBeanDefinition("na1", na1);
|
||||
TestBean actual = lbf.getBean(TestBean.class); // na1 was filtered
|
||||
assertSame(lbf.getBean("bd1", TestBean.class), actual);
|
||||
|
||||
lbf.registerBeanDefinition("bd2", bd2);
|
||||
try {
|
||||
lbf.getBean(TestBean.class);
|
||||
fail("Should have thrown NoSuchBeanDefinitionException");
|
||||
} catch (NoSuchBeanDefinitionException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutowireBeanByType() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("test", bd);
|
||||
DependenciesBean bean = (DependenciesBean)
|
||||
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
|
||||
@@ -1245,7 +1284,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireBeanWithFactoryBeanByType() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(LazyInitFactory.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(LazyInitFactory.class);
|
||||
lbf.registerBeanDefinition("factoryBean", bd);
|
||||
LazyInitFactory factoryBean = (LazyInitFactory) lbf.getBean("&factoryBean");
|
||||
assertNotNull("The FactoryBean should have been registered.", factoryBean);
|
||||
@@ -1255,6 +1294,15 @@ public final class DefaultListableBeanFactoryTests {
|
||||
factoryBean, bean.getFactoryBean());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTypeForAbstractFactoryBean() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(FactoryBeanThatShouldntBeCalled.class);
|
||||
bd.setAbstract(true);
|
||||
lbf.registerBeanDefinition("factoryBean", bd);
|
||||
assertNull(lbf.getType("factoryBean"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a dependency on a {@link FactoryBean} can <strong>not</strong>
|
||||
* be autowired <em>by name</em>, as & is an illegal character in
|
||||
@@ -1264,7 +1312,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test(expected=TypeMismatchException.class)
|
||||
public void testAutowireBeanWithFactoryBeanByName() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(LazyInitFactory.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(LazyInitFactory.class);
|
||||
lbf.registerBeanDefinition("factoryBean", bd);
|
||||
LazyInitFactory factoryBean = (LazyInitFactory) lbf.getBean("&factoryBean");
|
||||
assertNotNull("The FactoryBean should have been registered.", factoryBean);
|
||||
@@ -1274,10 +1322,10 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireBeanByTypeWithTwoMatches() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("test", bd);
|
||||
lbf.registerBeanDefinition("test2", bd2);
|
||||
lbf.registerBeanDefinition("spouse", bd2);
|
||||
try {
|
||||
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
|
||||
fail("Should have thrown UnsatisfiedDependencyException");
|
||||
@@ -1285,7 +1333,26 @@ public final class DefaultListableBeanFactoryTests {
|
||||
catch (UnsatisfiedDependencyException ex) {
|
||||
// expected
|
||||
assertTrue(ex.getMessage().indexOf("test") != -1);
|
||||
assertTrue(ex.getMessage().indexOf("test2") != -1);
|
||||
assertTrue(ex.getMessage().indexOf("spouse") != -1);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutowireBeanByTypeWithTwoMatchesAndParameterNameDiscovery() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
lbf.setParameterNameDiscoverer(new LocalVariableTableParameterNameDiscoverer());
|
||||
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().indexOf("test") != -1);
|
||||
assertTrue(ex.getMessage().indexOf("spouse") != -1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1312,7 +1379,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireExistingBeanByName() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("spouse", bd);
|
||||
DependenciesBean existingBean = new DependenciesBean();
|
||||
lbf.autowireBeanProperties(existingBean, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true);
|
||||
@@ -1324,7 +1391,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireExistingBeanByNameWithDependencyCheck() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("spous", bd);
|
||||
DependenciesBean existingBean = new DependenciesBean();
|
||||
try {
|
||||
@@ -1339,7 +1406,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireExistingBeanByNameWithNoDependencyCheck() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("spous", bd);
|
||||
DependenciesBean existingBean = new DependenciesBean();
|
||||
lbf.autowireBeanProperties(existingBean, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false);
|
||||
@@ -1349,7 +1416,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireExistingBeanByType() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("test", bd);
|
||||
DependenciesBean existingBean = new DependenciesBean();
|
||||
lbf.autowireBeanProperties(existingBean, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
|
||||
@@ -1431,7 +1498,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testConfigureBeanWithAutowiring() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("spouse", bd);
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
pvs.add("age", "99");
|
||||
@@ -1566,6 +1633,20 @@ public final class DefaultListableBeanFactoryTests {
|
||||
lbf.preInstantiateSingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrototypeStringCreatedRepeatedly() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition stringDef = new RootBeanDefinition(String.class);
|
||||
stringDef.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
stringDef.getConstructorArgumentValues().addGenericArgumentValue(new TypedStringValue("value"));
|
||||
lbf.registerBeanDefinition("string", stringDef);
|
||||
String val1 = lbf.getBean("string", String.class);
|
||||
String val2 = lbf.getBean("string", String.class);
|
||||
assertEquals("value", val1);
|
||||
assertEquals("value", val2);
|
||||
assertNotSame(val1, val2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrototypeWithArrayConversionForConstructor() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
package org.springframework.beans.factory;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
|
||||
/**
|
||||
* SPR-5475 exposed the fact that the error message displayed when incorrectly
|
||||
* invoking a factory method is not instructive to the user and rather misleading.
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class Spr5475Tests {
|
||||
|
||||
@Test
|
||||
public void noArgFactoryMethodInvokedWithOneArg() {
|
||||
assertExceptionMessageForMisconfiguredFactoryMethod(
|
||||
rootBeanDefinition(Foo.class)
|
||||
.setFactoryMethod("noArgFactory")
|
||||
.addConstructorArgValue("bogusArg").getBeanDefinition(),
|
||||
"Error creating bean with name 'foo': No matching factory method found: factory method 'noArgFactory(String)'. " +
|
||||
"Check that a method with the specified name and arguments exists and that it is static.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noArgFactoryMethodInvokedWithTwoArgs() {
|
||||
assertExceptionMessageForMisconfiguredFactoryMethod(
|
||||
rootBeanDefinition(Foo.class)
|
||||
.setFactoryMethod("noArgFactory")
|
||||
.addConstructorArgValue("bogusArg1")
|
||||
.addConstructorArgValue("bogusArg2".getBytes()).getBeanDefinition(),
|
||||
"Error creating bean with name 'foo': No matching factory method found: factory method 'noArgFactory(String,byte[])'. " +
|
||||
"Check that a method with the specified name and arguments exists and that it is static.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noArgFactoryMethodInvokedWithTwoArgsAndTypesSpecified() {
|
||||
RootBeanDefinition def = new RootBeanDefinition(Foo.class);
|
||||
def.setFactoryMethodName("noArgFactory");
|
||||
ConstructorArgumentValues cav = new ConstructorArgumentValues();
|
||||
cav.addIndexedArgumentValue(0, "bogusArg1", CharSequence.class.getName());
|
||||
cav.addIndexedArgumentValue(1, "bogusArg2".getBytes());
|
||||
def.setConstructorArgumentValues(cav);
|
||||
|
||||
assertExceptionMessageForMisconfiguredFactoryMethod(
|
||||
def,
|
||||
"Error creating bean with name 'foo': No matching factory method found: factory method 'noArgFactory(CharSequence,byte[])'. " +
|
||||
"Check that a method with the specified name and arguments exists and that it is static.");
|
||||
}
|
||||
|
||||
private void assertExceptionMessageForMisconfiguredFactoryMethod(BeanDefinition bd, String expectedMessage) {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
factory.registerBeanDefinition("foo", bd);
|
||||
|
||||
try {
|
||||
factory.preInstantiateSingletons();
|
||||
fail("should have failed with BeanCreationException due to incorrectly invoked factory method");
|
||||
} catch (BeanCreationException ex) {
|
||||
assertThat(ex.getMessage(), equalTo(expectedMessage));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleArgFactoryMethodInvokedWithNoArgs() {
|
||||
// calling a factory method that accepts arguments without any arguments emits an exception unlike cases
|
||||
// where a no-arg factory method is called with arguments. Adding this test just to document the difference
|
||||
assertExceptionMessageForMisconfiguredFactoryMethod(
|
||||
rootBeanDefinition(Foo.class)
|
||||
.setFactoryMethod("singleArgFactory").getBeanDefinition(),
|
||||
"Error creating bean with name 'foo': " +
|
||||
"Unsatisfied dependency expressed through constructor argument with index 0 of type [java.lang.String]: " +
|
||||
"Ambiguous factory method argument types - did you specify the correct bean references as factory method arguments?");
|
||||
}
|
||||
|
||||
|
||||
static class Foo {
|
||||
static Foo noArgFactory() {
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
static Foo singleArgFactory(String arg) {
|
||||
return new Foo();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -954,7 +954,7 @@ public final class AutowiredAnnotationBeanPostProcessorTests {
|
||||
public static class ExtendedResourceInjectionBean<T> extends ResourceInjectionBean {
|
||||
|
||||
@Autowired
|
||||
protected ITestBean testBean3;
|
||||
public final ITestBean testBean3 = null;
|
||||
|
||||
private T nestedTestBean;
|
||||
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author 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 static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class DeprecatedBeanWarnerTests {
|
||||
|
||||
private DefaultListableBeanFactory beanFactory;
|
||||
|
||||
private String beanName;
|
||||
|
||||
private BeanDefinition beanDefinition;
|
||||
|
||||
private DeprecatedBeanWarner warner;
|
||||
|
||||
@Test
|
||||
public void postProcess() {
|
||||
beanFactory = new DefaultListableBeanFactory();
|
||||
BeanDefinition def = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(MyDeprecatedBean.class)
|
||||
.getBeanDefinition();
|
||||
String beanName = "deprecated";
|
||||
beanFactory.registerBeanDefinition(beanName, def);
|
||||
|
||||
warner = new MyDeprecatedBeanWarner();
|
||||
warner.postProcessBeanFactory(beanFactory);
|
||||
assertEquals(beanName, this.beanName);
|
||||
assertEquals(def, this.beanDefinition);
|
||||
|
||||
}
|
||||
|
||||
private class MyDeprecatedBeanWarner extends DeprecatedBeanWarner {
|
||||
|
||||
|
||||
@Override
|
||||
protected void logDeprecatedBean(String beanName, BeanDefinition beanDefinition) {
|
||||
DeprecatedBeanWarnerTests.this.beanName = beanName;
|
||||
DeprecatedBeanWarnerTests.this.beanDefinition = beanDefinition;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author 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;
|
||||
|
||||
@Deprecated
|
||||
public class MyDeprecatedBean {
|
||||
|
||||
}
|
||||
+13
-8
@@ -1,19 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<!--
|
||||
Test data for ObjectFactoryCreatingFactoryBeanTests
|
||||
-->
|
||||
<beans>
|
||||
|
||||
<bean id="prototypeTarget" class="java.util.Date" scope="prototype"/>
|
||||
|
||||
<bean id="prototype" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
|
||||
<property name="targetBeanName"><idref local="prototypeTarget"/></property>
|
||||
<bean id="prototypeFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
|
||||
<property name="targetBeanName" value="prototypeTarget"/>
|
||||
</bean>
|
||||
|
||||
<bean id="testBean" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBeanTests$TestBean">
|
||||
<property name="objectFactory"><ref local="prototype"/></property>
|
||||
<bean id="factoryTestBean" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBeanTests$FactoryTestBean">
|
||||
<property name="objectFactory" ref="prototypeFactory"/>
|
||||
</bean>
|
||||
|
||||
|
||||
<bean id="prototypeProvider" class="org.springframework.beans.factory.config.ProviderCreatingFactoryBean">
|
||||
<property name="targetBeanName" value="prototypeTarget"/>
|
||||
</bean>
|
||||
|
||||
<bean id="providerTestBean" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBeanTests$ProviderTestBean">
|
||||
<property name="provider" ref="prototypeProvider"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
||||
+68
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2010 the original author 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,43 +16,49 @@
|
||||
|
||||
package org.springframework.beans.factory.config;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static test.util.TestResourceUtils.qualifiedResource;
|
||||
|
||||
import java.util.Date;
|
||||
import javax.inject.Provider;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
import org.junit.After;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.BeansException;
|
||||
import static test.util.TestResourceUtils.*;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.SerializationTestUtils;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ObjectFactoryCreatingFactoryBean}.
|
||||
*
|
||||
* @author Colin Sampaleanu
|
||||
* @author Juergen Hoeller
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
* @since 2004-05-11
|
||||
*/
|
||||
public final class ObjectFactoryCreatingFactoryBeanTests {
|
||||
public class ObjectFactoryCreatingFactoryBeanTests {
|
||||
|
||||
private static final Resource CONTEXT =
|
||||
qualifiedResource(ObjectFactoryCreatingFactoryBeanTests.class, "context.xml");
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
private XmlBeanFactory beanFactory;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.beanFactory = new XmlBeanFactory(CONTEXT);
|
||||
this.beanFactory.setSerializationId("test");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
this.beanFactory.setSerializationId(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBasicOperation() throws BeansException {
|
||||
TestBean testBean = (TestBean) beanFactory.getBean("testBean");
|
||||
public void testFactoryOperation() throws Exception {
|
||||
FactoryTestBean testBean = beanFactory.getBean("factoryTestBean", FactoryTestBean.class);
|
||||
ObjectFactory<?> objectFactory = testBean.getObjectFactory();
|
||||
|
||||
Date date1 = (Date) objectFactory.getObject();
|
||||
@@ -60,6 +66,40 @@ public final class ObjectFactoryCreatingFactoryBeanTests {
|
||||
assertTrue(date1 != date2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFactorySerialization() throws Exception {
|
||||
FactoryTestBean testBean = beanFactory.getBean("factoryTestBean", FactoryTestBean.class);
|
||||
ObjectFactory<?> objectFactory = testBean.getObjectFactory();
|
||||
|
||||
objectFactory = (ObjectFactory) SerializationTestUtils.serializeAndDeserialize(objectFactory);
|
||||
|
||||
Date date1 = (Date) objectFactory.getObject();
|
||||
Date date2 = (Date) objectFactory.getObject();
|
||||
assertTrue(date1 != date2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProviderOperation() throws Exception {
|
||||
ProviderTestBean testBean = beanFactory.getBean("providerTestBean", ProviderTestBean.class);
|
||||
Provider<?> provider = testBean.getProvider();
|
||||
|
||||
Date date1 = (Date) provider.get();
|
||||
Date date2 = (Date) provider.get();
|
||||
assertTrue(date1 != date2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProviderSerialization() throws Exception {
|
||||
ProviderTestBean testBean = beanFactory.getBean("providerTestBean", ProviderTestBean.class);
|
||||
Provider<?> provider = testBean.getProvider();
|
||||
|
||||
provider = (Provider) SerializationTestUtils.serializeAndDeserialize(provider);
|
||||
|
||||
Date date1 = (Date) provider.get();
|
||||
Date date2 = (Date) provider.get();
|
||||
assertTrue(date1 != date2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoesNotComplainWhenTargetBeanNameRefersToSingleton() throws Exception {
|
||||
final String targetBeanName = "singleton";
|
||||
@@ -78,7 +118,6 @@ public final class ObjectFactoryCreatingFactoryBeanTests {
|
||||
assertSame(expectedSingleton, actualSingleton);
|
||||
|
||||
verify(beanFactory);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -119,10 +158,9 @@ public final class ObjectFactoryCreatingFactoryBeanTests {
|
||||
}
|
||||
|
||||
|
||||
public static class TestBean {
|
||||
|
||||
public ObjectFactory<?> objectFactory;
|
||||
public static class FactoryTestBean {
|
||||
|
||||
private ObjectFactory<?> objectFactory;
|
||||
|
||||
public ObjectFactory<?> getObjectFactory() {
|
||||
return objectFactory;
|
||||
@@ -131,7 +169,20 @@ public final class ObjectFactoryCreatingFactoryBeanTests {
|
||||
public void setObjectFactory(ObjectFactory<?> objectFactory) {
|
||||
this.objectFactory = objectFactory;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ProviderTestBean {
|
||||
|
||||
private Provider<?> provider;
|
||||
|
||||
public Provider<?> getProvider() {
|
||||
return provider;
|
||||
}
|
||||
|
||||
public void setProvider(Provider<?> provider) {
|
||||
this.provider = provider;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -376,6 +376,9 @@ public final class PropertyResourceConfigurerTests {
|
||||
cas.addGenericArgumentValue("${var}name${age}");
|
||||
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
|
||||
pvs.add("stringArray", new String[] {"${os.name}", "${age}"});
|
||||
|
||||
List<Object> friends = new ManagedList<Object>();
|
||||
friends.add("na${age}me");
|
||||
friends.add(new RuntimeBeanReference("${ref}"));
|
||||
@@ -422,6 +425,9 @@ public final class PropertyResourceConfigurerTests {
|
||||
assertEquals(tb2, tb1.getSpouse());
|
||||
assertEquals(1, tb1.getSomeMap().size());
|
||||
assertEquals("myValue", tb1.getSomeMap().get("myKey"));
|
||||
assertEquals(2, tb2.getStringArray().length);
|
||||
assertEquals(System.getProperty("os.name"), tb2.getStringArray()[0]);
|
||||
assertEquals("98", tb2.getStringArray()[1]);
|
||||
assertEquals(2, tb2.getFriends().size());
|
||||
assertEquals("na98me", tb2.getFriends().iterator().next());
|
||||
assertEquals(tb2, tb2.getFriends().toArray()[1]);
|
||||
|
||||
+21
-22
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,24 +30,33 @@ import org.springframework.util.ClassUtils;
|
||||
*/
|
||||
public class URIEditorTests {
|
||||
|
||||
@Test
|
||||
public void standardURI() throws Exception {
|
||||
private void doTestURI(String uriSpec) {
|
||||
PropertyEditor uriEditor = new URIEditor();
|
||||
uriEditor.setAsText("mailto:juergen.hoeller@interface21.com");
|
||||
uriEditor.setAsText(uriSpec);
|
||||
Object value = uriEditor.getValue();
|
||||
assertTrue(value instanceof URI);
|
||||
URI uri = (URI) value;
|
||||
assertEquals(uri.toString(), uriEditor.getAsText());
|
||||
assertEquals(uriSpec, uri.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void standardURI() throws Exception {
|
||||
doTestURI("mailto:juergen.hoeller@interface21.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withNonExistentResource() throws Exception {
|
||||
doTestURI("gonna:/freak/in/the/morning/freak/in/the.evening");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void standardURL() throws Exception {
|
||||
PropertyEditor uriEditor = new URIEditor();
|
||||
uriEditor.setAsText("http://www.springframework.org");
|
||||
Object value = uriEditor.getValue();
|
||||
assertTrue(value instanceof URI);
|
||||
URI uri = (URI) value;
|
||||
assertEquals(uri.toString(), uriEditor.getAsText());
|
||||
doTestURI("http://www.springframework.org");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void standardURLWithFragment() throws Exception {
|
||||
doTestURI("http://www.springframework.org#1");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -57,7 +66,7 @@ public class URIEditorTests {
|
||||
Object value = uriEditor.getValue();
|
||||
assertTrue(value instanceof URI);
|
||||
URI uri = (URI) value;
|
||||
assertEquals(uri.toString(), uriEditor.getAsText());
|
||||
assertEquals("http://www.springframework.org", uri.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -95,16 +104,6 @@ public class URIEditorTests {
|
||||
assertTrue(uri.getScheme().startsWith("classpath"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withNonExistentResource() throws Exception {
|
||||
PropertyEditor uriEditor = new URIEditor();
|
||||
uriEditor.setAsText("gonna:/freak/in/the/morning/freak/in/the.evening");
|
||||
Object value = uriEditor.getValue();
|
||||
assertTrue(value instanceof URI);
|
||||
URI uri = (URI) value;
|
||||
assertEquals(uri.toString(), uriEditor.getAsText());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAsTextWithNull() throws Exception {
|
||||
PropertyEditor uriEditor = new URIEditor();
|
||||
|
||||
@@ -8,8 +8,8 @@ Import-Template:
|
||||
javax.xml.*;version="0";resolution:=optional,
|
||||
net.sf.cglib.*;version="[2.1.3, 3.0.0)";resolution:=optional,
|
||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||
org.springframework.core.*;version="[3.0.0, 3.0.1)",
|
||||
org.springframework.util.*;version="[3.0.0, 3.0.1)",
|
||||
org.springframework.core.*;version=${spring.osgi.range},
|
||||
org.springframework.util.*;version=${spring.osgi.range},
|
||||
org.xml.sax.*;version="0";resolution:=optional,
|
||||
org.w3c.dom.*;version="0";resolution:=optional
|
||||
Ignored-Existing-Headers:
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.1.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.3.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.1.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.3.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
|
||||
|
||||
+28
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2010 the original author 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,6 +55,22 @@ public class MailSendException extends MailException {
|
||||
this.failedMessages = new LinkedHashMap<Object, Exception>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for registration of failed messages, with the
|
||||
* messages that failed as keys, and the thrown exceptions as values.
|
||||
* <p>The messages should be the same that were originally passed
|
||||
* to the invoked send method.
|
||||
* @param msg the detail message
|
||||
* @param cause the root cause from the mail API in use
|
||||
* @param failedMessages Map of failed messages as keys and thrown
|
||||
* exceptions as values
|
||||
*/
|
||||
public MailSendException(String msg, Throwable cause, Map<Object, Exception> failedMessages) {
|
||||
super(msg, cause);
|
||||
this.failedMessages = new LinkedHashMap<Object, Exception>(failedMessages);
|
||||
this.messageExceptions = failedMessages.values().toArray(new Exception[failedMessages.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for registration of failed messages, with the
|
||||
* messages that failed as keys, and the thrown exceptions as values.
|
||||
@@ -64,9 +80,7 @@ public class MailSendException extends MailException {
|
||||
* exceptions as values
|
||||
*/
|
||||
public MailSendException(Map<Object, Exception> failedMessages) {
|
||||
super(null);
|
||||
this.failedMessages = new LinkedHashMap<Object, Exception>(failedMessages);
|
||||
this.messageExceptions = failedMessages.values().toArray(new Exception[failedMessages.size()]);
|
||||
this(null, null, failedMessages);
|
||||
}
|
||||
|
||||
|
||||
@@ -111,7 +125,12 @@ public class MailSendException extends MailException {
|
||||
return super.getMessage();
|
||||
}
|
||||
else {
|
||||
StringBuilder sb = new StringBuilder("Failed messages: ");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String baseMessage = super.getMessage();
|
||||
if (baseMessage != null) {
|
||||
sb.append(baseMessage).append(". ");
|
||||
}
|
||||
sb.append("Failed messages: ");
|
||||
for (int i = 0; i < this.messageExceptions.length; i++) {
|
||||
Exception subEx = this.messageExceptions[i];
|
||||
sb.append(subEx.toString());
|
||||
@@ -129,8 +148,8 @@ public class MailSendException extends MailException {
|
||||
return super.toString();
|
||||
}
|
||||
else {
|
||||
StringBuilder sb = new StringBuilder(getClass().getName());
|
||||
sb.append("; nested exceptions (").append(this.messageExceptions.length).append(") are:");
|
||||
StringBuilder sb = new StringBuilder(super.toString());
|
||||
sb.append("; message exceptions (").append(this.messageExceptions.length).append(") are:");
|
||||
for (int i = 0; i < this.messageExceptions.length; i++) {
|
||||
Exception subEx = this.messageExceptions[i];
|
||||
sb.append('\n').append("Failed message ").append(i + 1).append(": ");
|
||||
@@ -146,7 +165,7 @@ public class MailSendException extends MailException {
|
||||
super.printStackTrace(ps);
|
||||
}
|
||||
else {
|
||||
ps.println(getClass().getName() + "; nested exception details (" +
|
||||
ps.println(super.toString() + "; message exception details (" +
|
||||
this.messageExceptions.length + ") are:");
|
||||
for (int i = 0; i < this.messageExceptions.length; i++) {
|
||||
Exception subEx = this.messageExceptions[i];
|
||||
@@ -162,7 +181,7 @@ public class MailSendException extends MailException {
|
||||
super.printStackTrace(pw);
|
||||
}
|
||||
else {
|
||||
pw.println(getClass().getName() + "; nested exception details (" +
|
||||
pw.println(super.toString() + "; message exception details (" +
|
||||
this.messageExceptions.length + ") are:");
|
||||
for (int i = 0; i < this.messageExceptions.length; i++) {
|
||||
Exception subEx = this.messageExceptions[i];
|
||||
|
||||
+47
-28
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2010 the original author 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,7 +24,6 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.activation.FileTypeMap;
|
||||
import javax.mail.AuthenticationFailedException;
|
||||
import javax.mail.MessagingException;
|
||||
@@ -383,40 +382,60 @@ public class JavaMailSenderImpl implements JavaMailSender {
|
||||
*/
|
||||
protected void doSend(MimeMessage[] mimeMessages, Object[] originalMessages) throws MailException {
|
||||
Map<Object, Exception> failedMessages = new LinkedHashMap<Object, Exception>();
|
||||
|
||||
Transport transport;
|
||||
try {
|
||||
Transport transport = getTransport(getSession());
|
||||
transport = getTransport(getSession());
|
||||
transport.connect(getHost(), getPort(), getUsername(), getPassword());
|
||||
try {
|
||||
for (int i = 0; i < mimeMessages.length; i++) {
|
||||
MimeMessage mimeMessage = mimeMessages[i];
|
||||
try {
|
||||
if (mimeMessage.getSentDate() == null) {
|
||||
mimeMessage.setSentDate(new Date());
|
||||
}
|
||||
String messageId = mimeMessage.getMessageID();
|
||||
mimeMessage.saveChanges();
|
||||
if (messageId != null) {
|
||||
// Preserve explicitly specified message id...
|
||||
mimeMessage.setHeader(HEADER_MESSAGE_ID, messageId);
|
||||
}
|
||||
transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
Object original = (originalMessages != null ? originalMessages[i] : mimeMessage);
|
||||
failedMessages.put(original, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
transport.close();
|
||||
}
|
||||
}
|
||||
catch (AuthenticationFailedException ex) {
|
||||
throw new MailAuthenticationException(ex);
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
throw new MailSendException("Mail server connection failed", ex);
|
||||
// Effectively, all messages failed...
|
||||
for (int i = 0; i < mimeMessages.length; i++) {
|
||||
Object original = (originalMessages != null ? originalMessages[i] : mimeMessages[i]);
|
||||
failedMessages.put(original, ex);
|
||||
}
|
||||
throw new MailSendException("Mail server connection failed", ex, failedMessages);
|
||||
}
|
||||
|
||||
try {
|
||||
for (int i = 0; i < mimeMessages.length; i++) {
|
||||
MimeMessage mimeMessage = mimeMessages[i];
|
||||
try {
|
||||
if (mimeMessage.getSentDate() == null) {
|
||||
mimeMessage.setSentDate(new Date());
|
||||
}
|
||||
String messageId = mimeMessage.getMessageID();
|
||||
mimeMessage.saveChanges();
|
||||
if (messageId != null) {
|
||||
// Preserve explicitly specified message id...
|
||||
mimeMessage.setHeader(HEADER_MESSAGE_ID, messageId);
|
||||
}
|
||||
transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
Object original = (originalMessages != null ? originalMessages[i] : mimeMessage);
|
||||
failedMessages.put(original, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
transport.close();
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
if (!failedMessages.isEmpty()) {
|
||||
throw new MailSendException("Failed to close server connection after message failures", ex,
|
||||
failedMessages);
|
||||
}
|
||||
else {
|
||||
throw new MailSendException("Failed to close server connection after message sending", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!failedMessages.isEmpty()) {
|
||||
throw new MailSendException(failedMessages);
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -286,7 +286,7 @@ public class FreeMarkerConfigurationFactory {
|
||||
}
|
||||
|
||||
if (!CollectionUtils.isEmpty(this.freemarkerVariables)) {
|
||||
config.setAllSharedVariables(new SimpleHash(this.freemarkerVariables));
|
||||
config.setAllSharedVariables(new SimpleHash(this.freemarkerVariables, config.getObjectWrapper()));
|
||||
}
|
||||
|
||||
if (this.defaultEncoding != null) {
|
||||
|
||||
+27
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,7 +22,6 @@ import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.activation.FileTypeMap;
|
||||
import javax.mail.Address;
|
||||
import javax.mail.Message;
|
||||
@@ -381,8 +380,29 @@ public class JavaMailSenderTests extends TestCase {
|
||||
}
|
||||
catch (MailSendException ex) {
|
||||
// expected
|
||||
ex.printStackTrace();
|
||||
assertTrue(ex.getFailedMessages() != null);
|
||||
assertTrue(ex.getFailedMessages().isEmpty());
|
||||
assertEquals(1, ex.getFailedMessages().size());
|
||||
assertSame(simpleMessage1, ex.getFailedMessages().keySet().iterator().next());
|
||||
assertSame(ex.getCause(), ex.getFailedMessages().values().iterator().next());
|
||||
}
|
||||
}
|
||||
|
||||
public void testFailedMailServerClose() throws Exception {
|
||||
MockJavaMailSender sender = new MockJavaMailSender();
|
||||
sender.setHost("");
|
||||
sender.setUsername("username");
|
||||
sender.setPassword("password");
|
||||
SimpleMailMessage simpleMessage1 = new SimpleMailMessage();
|
||||
try {
|
||||
sender.send(simpleMessage1);
|
||||
fail("Should have thrown MailSendException");
|
||||
}
|
||||
catch (MailSendException ex) {
|
||||
// expected
|
||||
ex.printStackTrace();
|
||||
assertTrue(ex.getFailedMessages() != null);
|
||||
assertEquals(0, ex.getFailedMessages().size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -515,6 +535,9 @@ public class JavaMailSenderTests extends TestCase {
|
||||
|
||||
@Override
|
||||
public synchronized void close() throws MessagingException {
|
||||
if ("".equals(connectedHost)) {
|
||||
throw new MessagingException("close failure");
|
||||
}
|
||||
this.closeCalled = true;
|
||||
}
|
||||
|
||||
@@ -531,7 +554,7 @@ public class JavaMailSenderTests extends TestCase {
|
||||
if (message.getSentDate() == null) {
|
||||
throw new MessagingException("No sentDate specified");
|
||||
}
|
||||
if (message.getSubject() != null && message.getSubject().indexOf("custom") != -1) {
|
||||
if (message.getSubject() != null && message.getSubject().contains("custom")) {
|
||||
assertEquals(new Date(2005, 3, 1), message.getSentDate());
|
||||
}
|
||||
this.sentMessages.add(message);
|
||||
|
||||
@@ -10,19 +10,19 @@ Import-Template:
|
||||
javax.naming.*;version="0";resolution:=optional,
|
||||
javax.sql.*;version="0";resolution:=optional,
|
||||
net.sf.ehcache.*;version="[1.3.0, 2.0.0)";resolution:=optional,
|
||||
net.sf.jasperreports.*;version="[2.0.5, 3.0.0)";resolution:=optional,
|
||||
net.sf.jasperreports.*;version="[2.0.5, 4.0.0)";resolution:=optional,
|
||||
org.apache.commons.collections.*;version="[3.2.0, 4.0.0)";resolution:=optional,
|
||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)";resolution:=optional,
|
||||
org.apache.velocity.*;version="[1.5.0, 2.0.0)";resolution:=optional,
|
||||
org.quartz.*;version="[1.6.0, 2.0.0)";resolution:=optional,
|
||||
org.springframework.beans.*;version="[3.0.0, 3.0.1)";resolution:=optional,
|
||||
org.springframework.context.*;version="[3.0.0, 3.0.1)",
|
||||
org.springframework.core.*;version="[3.0.0, 3.0.1)",
|
||||
org.springframework.jdbc.*;version="[3.0.0, 3.0.1)";resolution:=optional,
|
||||
org.springframework.jndi.*;version="[3.0.0, 3.0.1)";resolution:=optional,
|
||||
org.springframework.scheduling.*;version="[3.0.0, 3.0.1)";resolution:=optional,
|
||||
org.springframework.transaction.*;version="[3.0.0, 3.0.1)";resolution:=optional,
|
||||
org.springframework.util.*;version="[3.0.0, 3.0.1)"
|
||||
org.springframework.beans.*;version=${spring.osgi.range};resolution:=optional,
|
||||
org.springframework.context.*;version=${spring.osgi.range},
|
||||
org.springframework.core.*;version=${spring.osgi.range},
|
||||
org.springframework.jdbc.*;version=${spring.osgi.range};resolution:=optional,
|
||||
org.springframework.jndi.*;version=${spring.osgi.range};resolution:=optional,
|
||||
org.springframework.scheduling.*;version=${spring.osgi.range};resolution:=optional,
|
||||
org.springframework.transaction.*;version=${spring.osgi.range};resolution:=optional,
|
||||
org.springframework.util.*;version=${spring.osgi.range}
|
||||
Ignored-Existing-Headers:
|
||||
Bnd-LastModified,
|
||||
Import-Package,
|
||||
|
||||
@@ -1,41 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src/main/java"/>
|
||||
<classpathentry kind="src" path="src/main/resources"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.aop"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.beans"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.core"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.expression"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.instrument"/>
|
||||
<classpathentry kind="lib" path="/org.springframework.asm/target/artifacts/org.springframework.asm.jar" sourcepath="/org.springframework.asm/target/artifacts/org.springframework.asm-sources.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/edu.emory.mathcs.backport/com.springsource.edu.emory.mathcs.backport/3.0.0/com.springsource.edu.emory.mathcs.backport-3.0.0.jar" sourcepath="/IVY_CACHE/edu.emory.mathcs.backport/com.springsource.edu.emory.mathcs.backport/3.0.0/com.springsource.edu.emory.mathcs.backport-sources-3.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.ejb/com.springsource.javax.ejb/3.0.0/com.springsource.javax.ejb-3.0.0.jar" sourcepath="/IVY_CACHE/javax.ejb/com.springsource.javax.ejb/3.0.0/com.springsource.javax.ejb-sources-3.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.inject/com.springsource.javax.inject/1.0.0/com.springsource.javax.inject-1.0.0.jar" sourcepath="/IVY_CACHE/javax.inject/com.springsource.javax.inject/1.0.0/com.springsource.javax.inject-sources-1.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.jms/com.springsource.javax.jms/1.1.0/com.springsource.javax.jms-1.1.0.jar" sourcepath="/IVY_CACHE/javax.jms/com.springsource.javax.jms/1.1.0/com.springsource.javax.jms-sources-1.1.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.persistence/com.springsource.javax.persistence/1.0.0/com.springsource.javax.persistence-1.0.0.jar" sourcepath="/IVY_CACHE/javax.persistence/com.springsource.javax.persistence/1.0.0/com.springsource.javax.persistence-sources-1.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.transaction/com.springsource.javax.transaction/1.1.0/com.springsource.javax.transaction-1.1.0.jar" sourcepath="/IVY_CACHE/javax.transaction/com.springsource.javax.transaction/1.1.0/com.springsource.javax.transaction-sources-1.1.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.validation/com.springsource.javax.validation/1.0.0.GA/com.springsource.javax.validation-1.0.0.GA.jar" sourcepath="/IVY_CACHE/javax.validation/com.springsource.javax.validation/1.0.0/com.springsource.javax.validation-sources-1.0.0.GA.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.xml.rpc/com.springsource.javax.xml.rpc/1.1.0/com.springsource.javax.xml.rpc-1.1.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.2.0/com.springsource.net.sf.cglib-2.2.0.jar" sourcepath="/IVY_CACHE/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.1.3/com.springsource.net.sf.cglib-sources-2.1.3.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-1.0.0.jar" sourcepath="/IVY_CACHE/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-sources-1.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.dbcp/1.2.2.osgi/com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.dbcp/1.2.2.osgi/com.springsource.org.apache.commons.dbcp-sources-1.2.2.osgi.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-sources-1.1.1.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.pool/1.4.0/com.springsource.org.apache.commons.pool-1.4.0.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.pool/1.4.0/com.springsource.org.apache.commons.pool-sources-1.4.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.jar" sourcepath="/IVY_CACHE/org.apache.log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-sources-1.2.15.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.aspectj/com.springsource.org.aspectj.weaver/1.6.8.RELEASE/com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.beanshell/com.springsource.bsh/2.0.0.b4/com.springsource.bsh-2.0.0.b4.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.codehaus.groovy/com.springsource.org.codehaus.groovy/1.6.5/com.springsource.org.codehaus.groovy-1.6.5.jar" sourcepath="/IVY_CACHE/org.codehaus.groovy/com.springsource.org.codehaus.groovy/1.6.5/com.springsource.org.codehaus.groovy-sources-1.6.5.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.easymock/com.springsource.org.easymock/2.5.1/com.springsource.org.easymock-2.5.1.jar" sourcepath="/IVY_CACHE/org.easymock/com.springsource.org.easymock/2.5.1/com.springsource.org.easymock-sources-2.5.1.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.objectweb.asm/com.springsource.org.objectweb.asm/3.1.0/com.springsource.org.objectweb.asm-3.1.0.jar" sourcepath="IVY_CACHE/org.objectweb.asm/com.springsource.org.objectweb.asm/3.1.0/com.springsource.org.objectweb.asm-sources-3.1.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.objectweb.asm/com.springsource.org.objectweb.asm.commons/3.1.0/com.springsource.org.objectweb.asm.commons-3.1.0.jar" sourcepath="IVY_CACHE/org.objectweb.asm/com.springsource.org.objectweb.asm.commons/3.1.0/com.springsource.org.objectweb.asm.commons-sources-3.1.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.hibernate/com.springsource.org.hibernate.validator/4.0.0.GA/com.springsource.org.hibernate.validator-4.0.0.GA.jar" sourcepath="/IVY_CACHE/org.hibernate/com.springsource.org.hibernate.validator/4.0.0.GA/com.springsource.org.hibernate.validator-sources-4.0.0.GA.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.joda/com.springsource.org.joda.time/1.6.0/com.springsource.org.joda.time-1.6.0.jar" sourcepath="/IVY_CACHE/org.joda/com.springsource.org.joda.time/1.6.0/com.springsource.org.joda.time-sources-1.6.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.jruby/com.springsource.org.jruby/1.4.0/com.springsource.org.jruby-1.4.0.jar" sourcepath="/IVY_CACHE/org.jruby/com.springsource.org.jruby/1.4.0/com.springsource.org.jruby-sources-1.4.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-4.7.0.jar" sourcepath="/IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-sources-4.7.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.inject/com.springsource.org.atinject.tck/1.0.0/com.springsource.org.atinject.tck-1.0.0.jar" sourcepath="/IVY_CACHE/javax.inject/com.springsource.org.atinject.tck/1.0.0/com.springsource.org.atinject.tck-sources-1.0.0.jar"/>
|
||||
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src/main/java"/>
|
||||
<classpathentry kind="src" path="src/main/resources"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.aop"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.beans"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.core"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.expression"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.instrument"/>
|
||||
<classpathentry kind="lib" path="/org.springframework.asm/target/artifacts/org.springframework.asm.jar" sourcepath="/org.springframework.asm/target/artifacts/org.springframework.asm-sources.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/edu.emory.mathcs.backport/com.springsource.edu.emory.mathcs.backport/3.0.0/com.springsource.edu.emory.mathcs.backport-3.0.0.jar" sourcepath="/IVY_CACHE/edu.emory.mathcs.backport/com.springsource.edu.emory.mathcs.backport/3.0.0/com.springsource.edu.emory.mathcs.backport-sources-3.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.ejb/com.springsource.javax.ejb/3.0.0/com.springsource.javax.ejb-3.0.0.jar" sourcepath="/IVY_CACHE/javax.ejb/com.springsource.javax.ejb/3.0.0/com.springsource.javax.ejb-sources-3.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.inject/com.springsource.javax.inject/1.0.0/com.springsource.javax.inject-1.0.0.jar" sourcepath="/IVY_CACHE/javax.inject/com.springsource.javax.inject/1.0.0/com.springsource.javax.inject-sources-1.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.jms/com.springsource.javax.jms/1.1.0/com.springsource.javax.jms-1.1.0.jar" sourcepath="/IVY_CACHE/javax.jms/com.springsource.javax.jms/1.1.0/com.springsource.javax.jms-sources-1.1.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.persistence/com.springsource.javax.persistence/1.0.0/com.springsource.javax.persistence-1.0.0.jar" sourcepath="/IVY_CACHE/javax.persistence/com.springsource.javax.persistence/1.0.0/com.springsource.javax.persistence-sources-1.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.transaction/com.springsource.javax.transaction/1.1.0/com.springsource.javax.transaction-1.1.0.jar" sourcepath="/IVY_CACHE/javax.transaction/com.springsource.javax.transaction/1.1.0/com.springsource.javax.transaction-sources-1.1.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.validation/com.springsource.javax.validation/1.0.0.GA/com.springsource.javax.validation-1.0.0.GA.jar" sourcepath="/IVY_CACHE/javax.validation/com.springsource.javax.validation/1.0.0/com.springsource.javax.validation-sources-1.0.0.GA.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.xml.rpc/com.springsource.javax.xml.rpc/1.1.0/com.springsource.javax.xml.rpc-1.1.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.2.0/com.springsource.net.sf.cglib-2.2.0.jar" sourcepath="/IVY_CACHE/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.1.3/com.springsource.net.sf.cglib-sources-2.1.3.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-1.0.0.jar" sourcepath="/IVY_CACHE/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-sources-1.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.dbcp/1.2.2.osgi/com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.dbcp/1.2.2.osgi/com.springsource.org.apache.commons.dbcp-sources-1.2.2.osgi.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-sources-1.1.1.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.pool/1.5.3/com.springsource.org.apache.commons.pool-1.5.3.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.pool/1.5.3/com.springsource.org.apache.commons.pool-sources-1.5.3.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.jar" sourcepath="/IVY_CACHE/org.apache.log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-sources-1.2.15.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.aspectj/com.springsource.org.aspectj.weaver/1.6.8.RELEASE/com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.beanshell/com.springsource.bsh/2.0.0.b4/com.springsource.bsh-2.0.0.b4.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.codehaus.groovy/com.springsource.org.codehaus.groovy/1.6.5/com.springsource.org.codehaus.groovy-1.6.5.jar" sourcepath="/IVY_CACHE/org.codehaus.groovy/com.springsource.org.codehaus.groovy/1.6.5/com.springsource.org.codehaus.groovy-sources-1.6.5.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.easymock/com.springsource.org.easymock/2.5.1/com.springsource.org.easymock-2.5.1.jar" sourcepath="/IVY_CACHE/org.easymock/com.springsource.org.easymock/2.5.1/com.springsource.org.easymock-sources-2.5.1.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.joda/com.springsource.org.joda.time/1.6.0/com.springsource.org.joda.time-1.6.0.jar" sourcepath="/IVY_CACHE/org.joda/com.springsource.org.joda.time/1.6.0/com.springsource.org.joda.time-sources-1.6.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.jruby/com.springsource.org.jruby/1.4.0/com.springsource.org.jruby-1.4.0.jar" sourcepath="/IVY_CACHE/org.jruby/com.springsource.org.jruby/1.4.0/com.springsource.org.jruby-sources-1.4.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-4.7.0.jar" sourcepath="/IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-sources-4.7.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.inject/com.springsource.org.atinject.tck/1.0.0/com.springsource.org.atinject.tck-1.0.0.jar" sourcepath="/IVY_CACHE/javax.inject/com.springsource.org.atinject.tck/1.0.0/com.springsource.org.atinject.tck-sources-1.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.hibernate/com.springsource.org.hibernate.validator/4.0.2.GA/com.springsource.org.hibernate.validator-4.0.2.GA.jar"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.dbcp" rev="1.2.2.osgi" conf="test->runtime"/>
|
||||
<dependency org="org.apache.log4j" name="com.springsource.org.apache.log4j" rev="1.2.15" conf="test->runtime"/>
|
||||
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="2.5.1" conf="test->compile"/>
|
||||
<dependency org="org.hibernate" name="com.springsource.org.hibernate.validator" rev="4.0.0.GA" conf="test->runtime"/>
|
||||
<dependency org="org.hibernate" name="com.springsource.org.hibernate.validator" rev="4.0.2.GA" conf="test->runtime"/>
|
||||
<dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit.version}" conf="test->runtime"/>
|
||||
<dependency org="org.slf4j" name="com.springsource.slf4j.jcl" rev="${slf4j.version}" conf="test->runtime"/>
|
||||
</dependencies>
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.1.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.3.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.1.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.3.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
@@ -191,7 +191,7 @@
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<version>4.0.0.GA</version>
|
||||
<version>4.0.2.GA</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author 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.context;
|
||||
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by any object that wishes to be notified of a
|
||||
* <b>StringValueResolver</b> for the <b> resolution of embedded definition values.
|
||||
*
|
||||
* <p>This is an alternative to a full ConfigurableBeanFactory dependency via the
|
||||
* ApplicationContextAware/BeanFactoryAware interfaces.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0.3
|
||||
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#resolveEmbeddedValue
|
||||
*/
|
||||
public interface EmbeddedValueResolverAware {
|
||||
|
||||
/**
|
||||
* Set the StringValueResolver to use for resolving embedded definition values.
|
||||
*/
|
||||
void setEmbeddedValueResolver(StringValueResolver resolver);
|
||||
|
||||
}
|
||||
+15
@@ -82,6 +82,8 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
|
||||
private boolean postProcessBeanDefinitionRegistryCalled = false;
|
||||
|
||||
private boolean postProcessBeanFactoryCalled = false;
|
||||
|
||||
|
||||
/**
|
||||
* Set the {@link SourceExtractor} to use for generated bean definitions
|
||||
@@ -128,6 +130,14 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
* Derive further bean definitions from the configuration classes in the registry.
|
||||
*/
|
||||
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
|
||||
if (this.postProcessBeanDefinitionRegistryCalled) {
|
||||
throw new IllegalStateException(
|
||||
"postProcessBeanDefinitionRegistry already called for this post-processor");
|
||||
}
|
||||
if (this.postProcessBeanFactoryCalled) {
|
||||
throw new IllegalStateException(
|
||||
"postProcessBeanFactory already called for this post-processor");
|
||||
}
|
||||
this.postProcessBeanDefinitionRegistryCalled = true;
|
||||
processConfigBeanDefinitions(registry);
|
||||
}
|
||||
@@ -137,6 +147,11 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
* by replacing them with CGLIB-enhanced subclasses.
|
||||
*/
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
|
||||
if (this.postProcessBeanFactoryCalled) {
|
||||
throw new IllegalStateException(
|
||||
"postProcessBeanFactory already called for this post-processor");
|
||||
}
|
||||
this.postProcessBeanFactoryCalled = true;
|
||||
if (!this.postProcessBeanDefinitionRegistryCalled) {
|
||||
// BeanDefinitionRegistryPostProcessor hook apparently not supported...
|
||||
// Simply call processConfigBeanDefinitions lazily at this point then.
|
||||
|
||||
+10
-5
@@ -45,12 +45,12 @@ import org.springframework.core.OrderComparator;
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2.3
|
||||
* @see #getApplicationListeners()
|
||||
* @see #getApplicationListeners(ApplicationEvent)
|
||||
* @see SimpleApplicationEventMulticaster
|
||||
*/
|
||||
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanFactoryAware {
|
||||
|
||||
private final ListenerRetriever defaultRetriever = new ListenerRetriever();
|
||||
private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);
|
||||
|
||||
private final Map<ListenerCacheKey, ListenerRetriever> retrieverCache =
|
||||
new ConcurrentHashMap<ListenerCacheKey, ListenerRetriever>();
|
||||
@@ -133,7 +133,7 @@ public abstract class AbstractApplicationEventMulticaster implements Application
|
||||
return retriever.getApplicationListeners();
|
||||
}
|
||||
else {
|
||||
retriever = new ListenerRetriever();
|
||||
retriever = new ListenerRetriever(true);
|
||||
LinkedList<ApplicationListener> allListeners = new LinkedList<ApplicationListener>();
|
||||
synchronized (this.defaultRetriever) {
|
||||
for (ApplicationListener listener : this.defaultRetriever.applicationListeners) {
|
||||
@@ -221,9 +221,12 @@ public abstract class AbstractApplicationEventMulticaster implements Application
|
||||
|
||||
public final Set<String> applicationListenerBeans;
|
||||
|
||||
public ListenerRetriever() {
|
||||
private final boolean preFiltered;
|
||||
|
||||
public ListenerRetriever(boolean preFiltered) {
|
||||
this.applicationListeners = new LinkedHashSet<ApplicationListener>();
|
||||
this.applicationListenerBeans = new LinkedHashSet<String>();
|
||||
this.preFiltered = preFiltered;
|
||||
}
|
||||
|
||||
public Collection<ApplicationListener> getApplicationListeners() {
|
||||
@@ -235,7 +238,9 @@ public abstract class AbstractApplicationEventMulticaster implements Application
|
||||
BeanFactory beanFactory = getBeanFactory();
|
||||
for (String listenerBeanName : this.applicationListenerBeans) {
|
||||
ApplicationListener listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class);
|
||||
allListeners.add(listener);
|
||||
if (!this.preFiltered && !allListeners.contains(listener)) {
|
||||
allListeners.add(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
OrderComparator.sort(allListeners);
|
||||
|
||||
+43
-12
@@ -22,7 +22,9 @@ import java.security.AccessControlException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@@ -571,22 +573,40 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
*/
|
||||
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
|
||||
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
|
||||
Set<String> processedBeans = new HashSet<String>();
|
||||
if (beanFactory instanceof BeanDefinitionRegistry) {
|
||||
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
|
||||
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
|
||||
List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
|
||||
new LinkedList<BeanDefinitionRegistryPostProcessor>();
|
||||
for (BeanFactoryPostProcessor postProcessor : getBeanFactoryPostProcessors()) {
|
||||
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
|
||||
((BeanDefinitionRegistryPostProcessor) postProcessor).postProcessBeanDefinitionRegistry(registry);
|
||||
BeanDefinitionRegistryPostProcessor registryPostProcessor =
|
||||
(BeanDefinitionRegistryPostProcessor) postProcessor;
|
||||
registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
|
||||
registryPostProcessors.add(registryPostProcessor);
|
||||
}
|
||||
else {
|
||||
regularPostProcessors.add(postProcessor);
|
||||
}
|
||||
}
|
||||
Collection<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
|
||||
beanFactory.getBeansOfType(BeanDefinitionRegistryPostProcessor.class, true, false).values();
|
||||
for (BeanDefinitionRegistryPostProcessor postProcessor : registryPostProcessors) {
|
||||
Map<String, BeanDefinitionRegistryPostProcessor> beanMap =
|
||||
beanFactory.getBeansOfType(BeanDefinitionRegistryPostProcessor.class, true, false);
|
||||
List<BeanDefinitionRegistryPostProcessor> registryPostProcessorBeans =
|
||||
new ArrayList<BeanDefinitionRegistryPostProcessor>(beanMap.values());
|
||||
OrderComparator.sort(registryPostProcessorBeans);
|
||||
for (BeanDefinitionRegistryPostProcessor postProcessor : registryPostProcessorBeans) {
|
||||
postProcessor.postProcessBeanDefinitionRegistry(registry);
|
||||
}
|
||||
invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
|
||||
invokeBeanFactoryPostProcessors(registryPostProcessorBeans, beanFactory);
|
||||
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
|
||||
processedBeans.addAll(beanMap.keySet());
|
||||
}
|
||||
else {
|
||||
// Invoke factory processors registered with the context instance.
|
||||
invokeBeanFactoryPostProcessors(getBeanFactoryPostProcessors(), beanFactory);
|
||||
}
|
||||
|
||||
// Invoke factory processors registered with the context instance.
|
||||
invokeBeanFactoryPostProcessors(getBeanFactoryPostProcessors(), beanFactory);
|
||||
|
||||
// Do not initialize FactoryBeans here: We need to leave all regular beans
|
||||
// uninitialized to let the bean factory post-processors apply to them!
|
||||
@@ -599,7 +619,10 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
List<String> orderedPostProcessorNames = new ArrayList<String>();
|
||||
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
|
||||
for (String ppName : postProcessorNames) {
|
||||
if (isTypeMatch(ppName, PriorityOrdered.class)) {
|
||||
if (processedBeans.contains(ppName)) {
|
||||
// skip - already processed in first phase above
|
||||
}
|
||||
else if (isTypeMatch(ppName, PriorityOrdered.class)) {
|
||||
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
|
||||
}
|
||||
else if (isTypeMatch(ppName, Ordered.class)) {
|
||||
@@ -634,7 +657,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
* Invoke the given BeanFactoryPostProcessor beans.
|
||||
*/
|
||||
private void invokeBeanFactoryPostProcessors(
|
||||
List<BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
|
||||
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
|
||||
|
||||
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
|
||||
postProcessor.postProcessBeanFactory(beanFactory);
|
||||
@@ -856,7 +879,8 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
*/
|
||||
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
|
||||
// Initialize conversion service for this context.
|
||||
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME)) {
|
||||
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
|
||||
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
|
||||
beanFactory.setConversionService(
|
||||
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
|
||||
}
|
||||
@@ -983,11 +1007,16 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
publishEvent(new ContextClosedEvent(this));
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.error("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
|
||||
logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
|
||||
}
|
||||
|
||||
// Stop all Lifecycle beans, to avoid delays during individual destruction.
|
||||
getLifecycleProcessor().onClose();
|
||||
try {
|
||||
getLifecycleProcessor().onClose();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
|
||||
}
|
||||
|
||||
// Destroy all cached singletons in the context's BeanFactory.
|
||||
destroyBeans();
|
||||
@@ -995,7 +1024,9 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
// Close the state of this context itself.
|
||||
closeBeanFactory();
|
||||
|
||||
// Let subclasses do some final clean-up if they wish...
|
||||
onClose();
|
||||
|
||||
synchronized (this.activeMonitor) {
|
||||
this.active = false;
|
||||
}
|
||||
|
||||
+21
@@ -22,11 +22,14 @@ import java.security.PrivilegedAction;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.EmbeddedValueResolverAware;
|
||||
import org.springframework.context.MessageSourceAware;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.config.BeanPostProcessor}
|
||||
@@ -86,6 +89,10 @@ class ApplicationContextAwareProcessor implements BeanPostProcessor {
|
||||
}
|
||||
|
||||
private void invokeAwareInterfaces(Object bean) {
|
||||
if (bean instanceof EmbeddedValueResolverAware) {
|
||||
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
|
||||
new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
|
||||
}
|
||||
if (bean instanceof ResourceLoaderAware) {
|
||||
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
|
||||
}
|
||||
@@ -104,4 +111,18 @@ class ApplicationContextAwareProcessor implements BeanPostProcessor {
|
||||
return bean;
|
||||
}
|
||||
|
||||
|
||||
private static class EmbeddedValueResolver implements StringValueResolver {
|
||||
|
||||
private final ConfigurableBeanFactory beanFactory;
|
||||
|
||||
public EmbeddedValueResolver(ConfigurableBeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
public String resolveStringValue(String strVal) {
|
||||
return this.beanFactory.resolveEmbeddedValue(strVal);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+9
-5
@@ -34,6 +34,7 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.context.LifecycleProcessor;
|
||||
import org.springframework.context.Phased;
|
||||
@@ -151,7 +152,7 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
||||
* @param beanName the name of the bean to start
|
||||
*/
|
||||
private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName) {
|
||||
Lifecycle bean = lifecycleBeans.get(beanName);
|
||||
Lifecycle bean = lifecycleBeans.remove(beanName);
|
||||
if (bean != null && !this.equals(bean)) {
|
||||
String[] dependenciesForBean = this.beanFactory.getDependenciesForBean(beanName);
|
||||
for (String dependency : dependenciesForBean) {
|
||||
@@ -161,12 +162,16 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Starting bean '" + beanName + "' of type [" + bean.getClass() + "]");
|
||||
}
|
||||
bean.start();
|
||||
try {
|
||||
bean.start();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new ApplicationContextException("Failed to start bean '" + beanName + "'", ex);
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Successfully started bean '" + beanName + "'");
|
||||
}
|
||||
}
|
||||
lifecycleBeans.remove(beanName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,7 +206,7 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
||||
private void doStop(Map<String, ? extends Lifecycle> lifecycleBeans, final String beanName,
|
||||
final CountDownLatch latch, final Set<String> countDownBeanNames) {
|
||||
|
||||
Lifecycle bean = lifecycleBeans.get(beanName);
|
||||
Lifecycle bean = lifecycleBeans.remove(beanName);
|
||||
if (bean != null) {
|
||||
String[] dependentBeans = this.beanFactory.getDependentBeans(beanName);
|
||||
for (String dependentBean : dependentBeans) {
|
||||
@@ -244,7 +249,6 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
||||
logger.warn("Failed to stop bean '" + beanName + "'", ex);
|
||||
}
|
||||
}
|
||||
lifecycleBeans.remove(beanName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+24
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author 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,12 +31,14 @@ import org.joda.time.ReadableInstant;
|
||||
import org.joda.time.ReadablePartial;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
|
||||
import org.springframework.context.EmbeddedValueResolverAware;
|
||||
import org.springframework.format.AnnotationFormatterFactory;
|
||||
import org.springframework.format.Parser;
|
||||
import org.springframework.format.Printer;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
* Formats fields annotated with the {@link DateTimeFormat} annotation.
|
||||
@@ -46,9 +48,12 @@ import org.springframework.util.StringUtils;
|
||||
* @since 3.0
|
||||
* @see DateTimeFormat
|
||||
*/
|
||||
public final class JodaDateTimeFormatAnnotationFormatterFactory implements AnnotationFormatterFactory<DateTimeFormat> {
|
||||
public class JodaDateTimeFormatAnnotationFormatterFactory
|
||||
implements AnnotationFormatterFactory<DateTimeFormat>, EmbeddedValueResolverAware {
|
||||
|
||||
private final Set<Class<?>> fieldTypes;
|
||||
|
||||
private StringValueResolver embeddedValueResolver;
|
||||
|
||||
|
||||
public JodaDateTimeFormatAnnotationFormatterFactory() {
|
||||
@@ -64,11 +69,20 @@ public final class JodaDateTimeFormatAnnotationFormatterFactory implements Annot
|
||||
this.fieldTypes = Collections.unmodifiableSet(rawFieldTypes);
|
||||
}
|
||||
|
||||
public Set<Class<?>> getFieldTypes() {
|
||||
public final Set<Class<?>> getFieldTypes() {
|
||||
return this.fieldTypes;
|
||||
}
|
||||
|
||||
|
||||
public void setEmbeddedValueResolver(StringValueResolver resolver) {
|
||||
this.embeddedValueResolver = resolver;
|
||||
}
|
||||
|
||||
protected String resolveEmbeddedValue(String value) {
|
||||
return (this.embeddedValueResolver != null ? this.embeddedValueResolver.resolveStringValue(value) : value);
|
||||
}
|
||||
|
||||
|
||||
public Printer<?> getPrinter(DateTimeFormat annotation, Class<?> fieldType) {
|
||||
DateTimeFormatter formatter = configureDateTimeFormatterFrom(annotation);
|
||||
if (ReadableInstant.class.isAssignableFrom(fieldType)) {
|
||||
@@ -92,24 +106,26 @@ public final class JodaDateTimeFormatAnnotationFormatterFactory implements Annot
|
||||
}
|
||||
|
||||
|
||||
// internal helpers
|
||||
|
||||
private DateTimeFormatter configureDateTimeFormatterFrom(DateTimeFormat annotation) {
|
||||
if (StringUtils.hasLength(annotation.pattern())) {
|
||||
return forPattern(annotation.pattern());
|
||||
return forPattern(resolveEmbeddedValue(annotation.pattern()));
|
||||
}
|
||||
else if (annotation.iso() != ISO.NONE) {
|
||||
return forIso(annotation.iso());
|
||||
}
|
||||
else {
|
||||
return forStyle(annotation.style());
|
||||
return forStyle(resolveEmbeddedValue(annotation.style()));
|
||||
}
|
||||
}
|
||||
|
||||
private DateTimeFormatter forPattern(String pattern) {
|
||||
return org.joda.time.format.DateTimeFormat.forPattern(pattern);
|
||||
}
|
||||
|
||||
|
||||
private DateTimeFormatter forStyle(String style) {
|
||||
return org.joda.time.format.DateTimeFormat.forStyle(style);
|
||||
}
|
||||
|
||||
private DateTimeFormatter forIso(ISO iso) {
|
||||
if (iso == ISO.DATE) {
|
||||
return org.joda.time.format.ISODateTimeFormat.date();
|
||||
@@ -122,8 +138,4 @@ public final class JodaDateTimeFormatAnnotationFormatterFactory implements Annot
|
||||
}
|
||||
}
|
||||
|
||||
private DateTimeFormatter forStyle(String style) {
|
||||
return org.joda.time.format.DateTimeFormat.forStyle(style);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,8 +25,8 @@ import org.springframework.core.NamedInheritableThreadLocal;
|
||||
/**
|
||||
* A holder for a thread-local user {@link JodaTimeContext}.
|
||||
*
|
||||
* @since 3.0
|
||||
* @author Keith Donald
|
||||
* @since 3.0
|
||||
*/
|
||||
public final class JodaTimeContextHolder {
|
||||
|
||||
@@ -51,18 +51,18 @@ public final class JodaTimeContextHolder {
|
||||
return jodaTimeContextHolder.get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the Formatter with the user-specific settings applied to thefrom the base <code>formatter</code>.
|
||||
* @param formatter the base formatter that establishes default formatting rules, generally user independent
|
||||
* @param locale the current user locale (may be null if not known)
|
||||
* @return the user's DateTimeFormatter
|
||||
* Obtain a DateTimeFormatter with user-specific settings applied to the given base Formatter.
|
||||
* @param formatter the base formatter that establishes default formatting rules
|
||||
* (generally user independent)
|
||||
* @param locale the current user locale (may be <code>null</code> if not known)
|
||||
* @return the user-specific DateTimeFormatter
|
||||
*/
|
||||
public static DateTimeFormatter getFormatter(DateTimeFormatter formatter, Locale locale) {
|
||||
if (locale != null) {
|
||||
formatter = formatter.withLocale(locale);
|
||||
}
|
||||
DateTimeFormatter formatterToUse = (locale != null ? formatter.withLocale(locale) : formatter);
|
||||
JodaTimeContext context = getJodaTimeContext();
|
||||
return (context != null ? context.getFormatter(formatter) : formatter);
|
||||
return (context != null ? context.getFormatter(formatterToUse) : formatterToUse);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+31
-23
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,6 +22,7 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.context.EmbeddedValueResolverAware;
|
||||
import org.springframework.format.AnnotationFormatterFactory;
|
||||
import org.springframework.format.Formatter;
|
||||
import org.springframework.format.Parser;
|
||||
@@ -29,6 +30,7 @@ import org.springframework.format.Printer;
|
||||
import org.springframework.format.annotation.NumberFormat;
|
||||
import org.springframework.format.annotation.NumberFormat.Style;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
* Formats fields annotated with the {@link NumberFormat} annotation.
|
||||
@@ -37,46 +39,52 @@ import org.springframework.util.StringUtils;
|
||||
* @since 3.0
|
||||
* @see NumberFormat
|
||||
*/
|
||||
public final class NumberFormatAnnotationFormatterFactory implements AnnotationFormatterFactory<NumberFormat> {
|
||||
public class NumberFormatAnnotationFormatterFactory
|
||||
implements AnnotationFormatterFactory<NumberFormat>, EmbeddedValueResolverAware {
|
||||
|
||||
private final Set<Class<?>> fieldTypes;
|
||||
|
||||
private StringValueResolver embeddedValueResolver;
|
||||
|
||||
|
||||
public NumberFormatAnnotationFormatterFactory() {
|
||||
this.fieldTypes = Collections.unmodifiableSet(createFieldTypes());
|
||||
Set<Class<?>> rawFieldTypes = new HashSet<Class<?>>(7);
|
||||
rawFieldTypes.add(Short.class);
|
||||
rawFieldTypes.add(Integer.class);
|
||||
rawFieldTypes.add(Long.class);
|
||||
rawFieldTypes.add(Float.class);
|
||||
rawFieldTypes.add(Double.class);
|
||||
rawFieldTypes.add(BigDecimal.class);
|
||||
rawFieldTypes.add(BigInteger.class);
|
||||
this.fieldTypes = Collections.unmodifiableSet(rawFieldTypes);
|
||||
}
|
||||
|
||||
|
||||
public Set<Class<?>> getFieldTypes() {
|
||||
public final Set<Class<?>> getFieldTypes() {
|
||||
return this.fieldTypes;
|
||||
}
|
||||
|
||||
|
||||
public void setEmbeddedValueResolver(StringValueResolver resolver) {
|
||||
this.embeddedValueResolver = resolver;
|
||||
}
|
||||
|
||||
protected String resolveEmbeddedValue(String value) {
|
||||
return (this.embeddedValueResolver != null ? this.embeddedValueResolver.resolveStringValue(value) : value);
|
||||
}
|
||||
|
||||
|
||||
public Printer<Number> getPrinter(NumberFormat annotation, Class<?> fieldType) {
|
||||
return configureFormatterFrom(annotation, fieldType);
|
||||
return configureFormatterFrom(annotation);
|
||||
}
|
||||
|
||||
public Parser<Number> getParser(NumberFormat annotation, Class<?> fieldType) {
|
||||
return configureFormatterFrom(annotation, fieldType);
|
||||
return configureFormatterFrom(annotation);
|
||||
}
|
||||
|
||||
|
||||
// internal helpers
|
||||
|
||||
private Set<Class<?>> createFieldTypes() {
|
||||
Set<Class<?>> fieldTypes = new HashSet<Class<?>>(7);
|
||||
fieldTypes.add(Short.class);
|
||||
fieldTypes.add(Integer.class);
|
||||
fieldTypes.add(Long.class);
|
||||
fieldTypes.add(Float.class);
|
||||
fieldTypes.add(Double.class);
|
||||
fieldTypes.add(BigDecimal.class);
|
||||
fieldTypes.add(BigInteger.class);
|
||||
return fieldTypes;
|
||||
}
|
||||
|
||||
private Formatter<Number> configureFormatterFrom(NumberFormat annotation, Class<?> fieldType) {
|
||||
private Formatter<Number> configureFormatterFrom(NumberFormat annotation) {
|
||||
if (StringUtils.hasLength(annotation.pattern())) {
|
||||
return new NumberFormatter(annotation.pattern());
|
||||
return new NumberFormatter(resolveEmbeddedValue(annotation.pattern()));
|
||||
}
|
||||
else {
|
||||
Style style = annotation.style();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user