Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
.-Smile-.
spring-framework
提交
d5efe4f9
S
spring-framework
项目概览
.-Smile-.
/
spring-framework
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
S
spring-framework
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
d5efe4f9
编写于
11月 09, 2015
作者:
J
Juergen Hoeller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Detect event listener methods behind interface proxies as well
Issue: SPR-13650
上级
bc7bcab5
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
357 addition
and
79 deletion
+357
-79
spring-aop/src/main/java/org/springframework/aop/framework/AbstractAdvisingBeanPostProcessor.java
...work/aop/framework/AbstractAdvisingBeanPostProcessor.java
+37
-4
spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractAutoProxyCreator.java
...ork/aop/framework/autoproxy/AbstractAutoProxyCreator.java
+12
-7
spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractBeanFactoryAwareAdvisingPostProcessor.java
...oproxy/AbstractBeanFactoryAwareAdvisingPostProcessor.java
+64
-0
spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AutoProxyUtils.java
...ringframework/aop/framework/autoproxy/AutoProxyUtils.java
+48
-1
spring-context/src/main/java/org/springframework/context/event/EventListenerMethodProcessor.java
...framework/context/event/EventListenerMethodProcessor.java
+50
-33
spring-context/src/main/java/org/springframework/scheduling/annotation/AsyncAnnotationBeanPostProcessor.java
...heduling/annotation/AsyncAnnotationBeanPostProcessor.java
+4
-3
spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java
...ling/annotation/ScheduledAnnotationBeanPostProcessor.java
+17
-14
spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationPostProcessor.java
...idation/beanvalidation/MethodValidationPostProcessor.java
+3
-2
spring-context/src/test/java/org/springframework/context/event/AnnotationDrivenEventListenerTests.java
...ork/context/event/AnnotationDrivenEventListenerTests.java
+117
-10
spring-tx/src/main/java/org/springframework/dao/annotation/PersistenceExceptionTranslationPostProcessor.java
...otation/PersistenceExceptionTranslationPostProcessor.java
+5
-5
未找到文件。
spring-aop/src/main/java/org/springframework/aop/framework/AbstractAdvisingBeanPostProcessor.java
浏览文件 @
d5efe4f9
/*
* Copyright 2002-201
4
the original author or authors.
* Copyright 2002-201
5
the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
...
...
@@ -81,13 +81,12 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
}
if
(
isEligible
(
bean
,
beanName
))
{
ProxyFactory
proxyFactory
=
new
ProxyFactory
();
proxyFactory
.
copyFrom
(
this
);
proxyFactory
.
setTarget
(
bean
);
ProxyFactory
proxyFactory
=
prepareProxyFactory
(
bean
,
beanName
);
if
(!
proxyFactory
.
isProxyTargetClass
())
{
evaluateProxyInterfaces
(
bean
.
getClass
(),
proxyFactory
);
}
proxyFactory
.
addAdvisor
(
this
.
advisor
);
customizeProxyFactory
(
proxyFactory
);
return
proxyFactory
.
getProxy
(
getProxyClassLoader
());
}
...
...
@@ -131,4 +130,38 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
return
eligible
;
}
/**
* Prepare a {@link ProxyFactory} for the given bean.
* <p>Subclasses may customize the handling of the target instance and in
* particular the exposure of the target class. The default introspection
* of interfaces for non-target-class proxies and the configured advisor
* will be applied afterwards; {@link #customizeProxyFactory} allows for
* late customizations of those parts right before proxy creation.
* @param bean the bean instance to create a proxy for
* @param beanName the corresponding bean name
* @return the ProxyFactory, initialized with this processor's
* {@link ProxyConfig} settings and the specified bean
* @since 4.2.3
* @see #customizeProxyFactory
*/
protected
ProxyFactory
prepareProxyFactory
(
Object
bean
,
String
beanName
)
{
ProxyFactory
proxyFactory
=
new
ProxyFactory
();
proxyFactory
.
copyFrom
(
this
);
proxyFactory
.
setTarget
(
bean
);
return
proxyFactory
;
}
/**
* Subclasses may choose to implement this: for example,
* to change the interfaces exposed.
* <p>The default implementation is empty.
* @param proxyFactory ProxyFactory that is already configured with
* target, advisor and interfaces and will be used to create the proxy
* immediately after this method returns
* @since 4.2.3
* @see #prepareProxyFactory
*/
protected
void
customizeProxyFactory
(
ProxyFactory
proxyFactory
)
{
}
}
spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractAutoProxyCreator.java
浏览文件 @
d5efe4f9
/*
* Copyright 2002-201
4
the original author or authors.
* Copyright 2002-201
5
the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
...
...
@@ -330,7 +330,8 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
Object
[]
specificInterceptors
=
getAdvicesAndAdvisorsForBean
(
bean
.
getClass
(),
beanName
,
null
);
if
(
specificInterceptors
!=
DO_NOT_PROXY
)
{
this
.
advisedBeans
.
put
(
cacheKey
,
Boolean
.
TRUE
);
Object
proxy
=
createProxy
(
bean
.
getClass
(),
beanName
,
specificInterceptors
,
new
SingletonTargetSource
(
bean
));
Object
proxy
=
createProxy
(
bean
.
getClass
(),
beanName
,
specificInterceptors
,
new
SingletonTargetSource
(
bean
));
this
.
proxyTypes
.
put
(
cacheKey
,
proxy
.
getClass
());
return
proxy
;
}
...
...
@@ -419,6 +420,10 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
protected
Object
createProxy
(
Class
<?>
beanClass
,
String
beanName
,
Object
[]
specificInterceptors
,
TargetSource
targetSource
)
{
if
(
beanName
!=
null
&&
this
.
beanFactory
instanceof
ConfigurableListableBeanFactory
)
{
AutoProxyUtils
.
exposeTargetClass
((
ConfigurableListableBeanFactory
)
this
.
beanFactory
,
beanName
,
beanClass
);
}
ProxyFactory
proxyFactory
=
new
ProxyFactory
();
proxyFactory
.
copyFrom
(
this
);
...
...
@@ -490,7 +495,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
List
<
Object
>
allInterceptors
=
new
ArrayList
<
Object
>();
if
(
specificInterceptors
!=
null
)
{
allInterceptors
.
addAll
(
Arrays
.
asList
(
specificInterceptors
));
if
(
commonInterceptors
!=
null
)
{
if
(
commonInterceptors
.
length
>
0
)
{
if
(
this
.
applyCommonInterceptorsFirst
)
{
allInterceptors
.
addAll
(
0
,
Arrays
.
asList
(
commonInterceptors
));
}
...
...
@@ -500,7 +505,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
}
}
if
(
logger
.
isDebugEnabled
())
{
int
nrOfCommonInterceptors
=
(
commonInterceptors
!=
null
?
commonInterceptors
.
length
:
0
)
;
int
nrOfCommonInterceptors
=
commonInterceptors
.
length
;
int
nrOfSpecificInterceptors
=
(
specificInterceptors
!=
null
?
specificInterceptors
.
length
:
0
);
logger
.
debug
(
"Creating implicit proxy for bean '"
+
beanName
+
"' with "
+
nrOfCommonInterceptors
+
" common interceptors and "
+
nrOfSpecificInterceptors
+
" specific interceptors"
);
...
...
@@ -518,8 +523,8 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
* @see #setInterceptorNames
*/
private
Advisor
[]
resolveInterceptorNames
()
{
ConfigurableBeanFactory
cbf
=
(
this
.
beanFactory
instanceof
ConfigurableBeanFactory
)
?
(
ConfigurableBeanFactory
)
this
.
beanFactory
:
null
;
ConfigurableBeanFactory
cbf
=
(
this
.
beanFactory
instanceof
ConfigurableBeanFactory
?
(
ConfigurableBeanFactory
)
this
.
beanFactory
:
null
)
;
List
<
Advisor
>
advisors
=
new
ArrayList
<
Advisor
>();
for
(
String
beanName
:
this
.
interceptorNames
)
{
if
(
cbf
==
null
||
!
cbf
.
isCurrentlyInCreation
(
beanName
))
{
...
...
@@ -536,7 +541,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
* <p>The default implementation is empty.
* @param proxyFactory ProxyFactory that is already configured with
* TargetSource and interfaces and will be used to create the proxy
* immedia
b
ly after this method returns
* immedia
te
ly after this method returns
*/
protected
void
customizeProxyFactory
(
ProxyFactory
proxyFactory
)
{
}
...
...
spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractBeanFactoryAwareAdvisingPostProcessor.java
0 → 100644
浏览文件 @
d5efe4f9
/*
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.springframework.aop.framework.autoproxy
;
import
org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor
;
import
org.springframework.aop.framework.ProxyFactory
;
import
org.springframework.beans.factory.BeanFactory
;
import
org.springframework.beans.factory.BeanFactoryAware
;
import
org.springframework.beans.factory.config.ConfigurableListableBeanFactory
;
/**
* Extension of {@link AbstractAutoProxyCreator} which implements {@link BeanFactoryAware},
* adds exposure of the original target class for each proxied bean
* ({@link AutoProxyUtils#ORIGINAL_TARGET_CLASS_ATTRIBUTE}),
* and participates in an externally enforced target-class mode for any given bean
* ({@link AutoProxyUtils#PRESERVE_TARGET_CLASS_ATTRIBUTE}).
*
* @author Juergen Hoeller
* @since 4.2.3
* @see AutoProxyUtils#shouldProxyTargetClass
* @see AutoProxyUtils#determineTargetClass
*/
@SuppressWarnings
(
"serial"
)
public
abstract
class
AbstractBeanFactoryAwareAdvisingPostProcessor
extends
AbstractAdvisingBeanPostProcessor
implements
BeanFactoryAware
{
private
ConfigurableListableBeanFactory
beanFactory
;
@Override
public
void
setBeanFactory
(
BeanFactory
beanFactory
)
{
this
.
beanFactory
=
(
beanFactory
instanceof
ConfigurableListableBeanFactory
?
(
ConfigurableListableBeanFactory
)
beanFactory
:
null
);
}
@Override
protected
ProxyFactory
prepareProxyFactory
(
Object
bean
,
String
beanName
)
{
if
(
this
.
beanFactory
!=
null
)
{
AutoProxyUtils
.
exposeTargetClass
(
this
.
beanFactory
,
beanName
,
bean
.
getClass
());
}
ProxyFactory
proxyFactory
=
super
.
prepareProxyFactory
(
bean
,
beanName
);
if
(!
proxyFactory
.
isProxyTargetClass
()
&&
this
.
beanFactory
!=
null
&&
AutoProxyUtils
.
shouldProxyTargetClass
(
this
.
beanFactory
,
beanName
))
{
proxyFactory
.
setProxyTargetClass
(
true
);
}
return
proxyFactory
;
}
}
spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AutoProxyUtils.java
浏览文件 @
d5efe4f9
/*
* Copyright 2002-201
2
the original author or authors.
* Copyright 2002-201
5
the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
...
...
@@ -37,10 +37,21 @@ public abstract class AutoProxyUtils {
* <p>Proxy factories can set this attribute if they built a target class proxy
* for a specific bean, and want to enforce that that bean can always be cast
* to its target class (even if AOP advices get applied through auto-proxying).
* @see #shouldProxyTargetClass
*/
public
static
final
String
PRESERVE_TARGET_CLASS_ATTRIBUTE
=
Conventions
.
getQualifiedAttributeName
(
AutoProxyUtils
.
class
,
"preserveTargetClass"
);
/**
* Bean definition attribute that indicates the original target class of an
* auto-proxied bean, e.g. to be used for the introspection of annotations
* on the target class behind an interface-based proxy.
* @since 4.2.3
* @see #determineTargetClass
*/
public
static
final
String
ORIGINAL_TARGET_CLASS_ATTRIBUTE
=
Conventions
.
getQualifiedAttributeName
(
AutoProxyUtils
.
class
,
"originalTargetClass"
);
/**
* Determine whether the given bean should be proxied with its target
...
...
@@ -59,4 +70,40 @@ public abstract class AutoProxyUtils {
return
false
;
}
/**
* Determine the original target class for the specified bean, if possible,
* otherwise falling back to a regular {@code getType} lookup.
* @param beanFactory the containing ConfigurableListableBeanFactory
* @param beanName the name of the bean
* @return the original target class as stored in the bean definition, if any
* @since 4.2.3
* @see org.springframework.beans.factory.BeanFactory#getType(String)
*/
public
static
Class
<?>
determineTargetClass
(
ConfigurableListableBeanFactory
beanFactory
,
String
beanName
)
{
if
(
beanName
==
null
)
{
return
null
;
}
if
(
beanFactory
.
containsBeanDefinition
(
beanName
))
{
BeanDefinition
bd
=
beanFactory
.
getMergedBeanDefinition
(
beanName
);
Class
<?>
targetClass
=
(
Class
<?>)
bd
.
getAttribute
(
ORIGINAL_TARGET_CLASS_ATTRIBUTE
);
if
(
targetClass
!=
null
)
{
return
targetClass
;
}
}
return
beanFactory
.
getType
(
beanName
);
}
/**
* Expose the given target class for the specified bean.
* @param beanFactory the containing ConfigurableListableBeanFactory
* @param beanName the name of the bean
* @param targetClass the corresponding target class
* @since 4.2.3
*/
static
void
exposeTargetClass
(
ConfigurableListableBeanFactory
beanFactory
,
String
beanName
,
Class
<?>
targetClass
)
{
if
(
beanFactory
.
containsBeanDefinition
(
beanName
))
{
beanFactory
.
getMergedBeanDefinition
(
beanName
).
setAttribute
(
ORIGINAL_TARGET_CLASS_ATTRIBUTE
,
targetClass
);
}
}
}
spring-context/src/main/java/org/springframework/context/event/EventListenerMethodProcessor.java
浏览文件 @
d5efe4f9
...
...
@@ -19,7 +19,6 @@ package org.springframework.context.event;
import
java.lang.reflect.Method
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.LinkedHashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
...
...
@@ -28,6 +27,8 @@ import java.util.concurrent.ConcurrentHashMap;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.LogFactory
;
import
org.springframework.aop.framework.autoproxy.AutoProxyUtils
;
import
org.springframework.aop.scope.ScopedObject
;
import
org.springframework.aop.scope.ScopedProxyUtils
;
import
org.springframework.beans.BeansException
;
import
org.springframework.beans.factory.BeanInitializationException
;
...
...
@@ -36,10 +37,10 @@ import org.springframework.context.ApplicationContext;
import
org.springframework.context.ApplicationContextAware
;
import
org.springframework.context.ApplicationListener
;
import
org.springframework.context.ConfigurableApplicationContext
;
import
org.springframework.core.MethodIntrospector
;
import
org.springframework.core.annotation.AnnotationAwareOrderComparator
;
import
org.springframework.core.annotation.AnnotationUtils
;
import
org.springframework.util.Assert
;
import
org.springframework.util.ReflectionUtils
;
/**
* Register {@link EventListener} annotated method as individual {@link ApplicationListener}
...
...
@@ -66,7 +67,6 @@ public class EventListenerMethodProcessor implements SmartInitializingSingleton,
Assert
.
isTrue
(
applicationContext
instanceof
ConfigurableApplicationContext
,
"ApplicationContext does not implement ConfigurableApplicationContext"
);
this
.
applicationContext
=
(
ConfigurableApplicationContext
)
applicationContext
;
}
@Override
...
...
@@ -75,21 +75,36 @@ public class EventListenerMethodProcessor implements SmartInitializingSingleton,
String
[]
allBeanNames
=
this
.
applicationContext
.
getBeanNamesForType
(
Object
.
class
);
for
(
String
beanName
:
allBeanNames
)
{
if
(!
ScopedProxyUtils
.
isScopedTarget
(
beanName
))
{
Class
<?>
type
=
this
.
applicationContext
.
getType
(
beanName
);
try
{
processBean
(
factories
,
beanName
,
type
);
}
catch
(
Throwable
ex
)
{
throw
new
BeanInitializationException
(
"Failed to process @EventListener "
+
"annotation on bean with name '"
+
beanName
+
"'"
,
ex
);
Class
<?>
type
=
AutoProxyUtils
.
determineTargetClass
(
this
.
applicationContext
.
getBeanFactory
(),
beanName
);
if
(
type
!=
null
)
{
if
(
ScopedObject
.
class
.
isAssignableFrom
(
type
))
{
try
{
type
=
AutoProxyUtils
.
determineTargetClass
(
this
.
applicationContext
.
getBeanFactory
(),
ScopedProxyUtils
.
getTargetBeanName
(
beanName
));
}
catch
(
Throwable
ex
)
{
// An invalid scoped proxy arrangement - let's ignore it.
if
(
logger
.
isDebugEnabled
())
{
logger
.
debug
(
"Could not resolve target bean for scoped proxy '"
+
beanName
+
"'"
,
ex
);
}
}
}
try
{
processBean
(
factories
,
beanName
,
type
);
}
catch
(
Throwable
ex
)
{
throw
new
BeanInitializationException
(
"Failed to process @EventListener "
+
"annotation on bean with name '"
+
beanName
+
"'"
,
ex
);
}
}
}
}
}
/**
* Return the {@link EventListenerFactory} instances to use to handle
{@link EventListener}
* annotated methods.
* Return the {@link EventListenerFactory} instances to use to handle
*
{@link EventListener}
annotated methods.
*/
protected
List
<
EventListenerFactory
>
getEventListenerFactories
()
{
Map
<
String
,
EventListenerFactory
>
beans
=
...
...
@@ -99,29 +114,15 @@ public class EventListenerMethodProcessor implements SmartInitializingSingleton,
return
allFactories
;
}
protected
void
processBean
(
List
<
EventListenerFactory
>
factories
,
String
beanName
,
final
Class
<?>
targetType
)
{
protected
void
processBean
(
final
List
<
EventListenerFactory
>
factories
,
final
String
beanName
,
final
Class
<?>
targetType
)
{
if
(!
this
.
nonAnnotatedClasses
.
contains
(
targetType
))
{
final
Set
<
Method
>
annotatedMethods
=
new
LinkedHashSet
<
Method
>(
1
);
Method
[]
methods
=
ReflectionUtils
.
getUniqueDeclaredMethods
(
targetType
);
for
(
Method
method
:
methods
)
{
EventListener
eventListener
=
AnnotationUtils
.
findAnnotation
(
method
,
EventListener
.
class
);
if
(
eventListener
==
null
)
{
continue
;
}
for
(
EventListenerFactory
factory
:
factories
)
{
if
(
factory
.
supportsMethod
(
method
))
{
ApplicationListener
<?>
applicationListener
=
factory
.
createApplicationListener
(
beanName
,
targetType
,
method
);
if
(
applicationListener
instanceof
ApplicationListenerMethodAdapter
)
{
((
ApplicationListenerMethodAdapter
)
applicationListener
)
.
init
(
this
.
applicationContext
,
this
.
evaluator
);
Map
<
Method
,
EventListener
>
annotatedMethods
=
MethodIntrospector
.
selectMethods
(
targetType
,
new
MethodIntrospector
.
MetadataLookup
<
EventListener
>()
{
@Override
public
EventListener
inspect
(
Method
method
)
{
return
AnnotationUtils
.
findAnnotation
(
method
,
EventListener
.
class
);
}
this
.
applicationContext
.
addApplicationListener
(
applicationListener
);
annotatedMethods
.
add
(
method
);
break
;
}
}
}
});
if
(
annotatedMethods
.
isEmpty
())
{
this
.
nonAnnotatedClasses
.
add
(
targetType
);
if
(
logger
.
isTraceEnabled
())
{
...
...
@@ -130,6 +131,22 @@ public class EventListenerMethodProcessor implements SmartInitializingSingleton,
}
else
{
// Non-empty set of methods
for
(
Method
method
:
annotatedMethods
.
keySet
())
{
for
(
EventListenerFactory
factory
:
factories
)
{
if
(
factory
.
supportsMethod
(
method
))
{
Method
methodToUse
=
MethodIntrospector
.
selectInvocableMethod
(
method
,
this
.
applicationContext
.
getType
(
beanName
));
ApplicationListener
<?>
applicationListener
=
factory
.
createApplicationListener
(
beanName
,
targetType
,
methodToUse
);
if
(
applicationListener
instanceof
ApplicationListenerMethodAdapter
)
{
((
ApplicationListenerMethodAdapter
)
applicationListener
)
.
init
(
this
.
applicationContext
,
this
.
evaluator
);
}
this
.
applicationContext
.
addApplicationListener
(
applicationListener
);
break
;
}
}
}
if
(
logger
.
isDebugEnabled
())
{
logger
.
debug
(
annotatedMethods
.
size
()
+
" @EventListener methods processed on bean '"
+
beanName
+
"': "
+
annotatedMethods
);
...
...
spring-context/src/main/java/org/springframework/scheduling/annotation/AsyncAnnotationBeanPostProcessor.java
浏览文件 @
d5efe4f9
...
...
@@ -22,10 +22,9 @@ import java.util.concurrent.Executor;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.LogFactory
;
import
org.springframework.aop.framework.
AbstractAdvisingBean
PostProcessor
;
import
org.springframework.aop.framework.
autoproxy.AbstractBeanFactoryAwareAdvising
PostProcessor
;
import
org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler
;
import
org.springframework.beans.factory.BeanFactory
;
import
org.springframework.beans.factory.BeanFactoryAware
;
import
org.springframework.beans.factory.NoSuchBeanDefinitionException
;
import
org.springframework.beans.factory.NoUniqueBeanDefinitionException
;
import
org.springframework.core.task.TaskExecutor
;
...
...
@@ -62,7 +61,7 @@ import org.springframework.util.Assert;
* @see ScheduledAnnotationBeanPostProcessor
*/
@SuppressWarnings
(
"serial"
)
public
class
AsyncAnnotationBeanPostProcessor
extends
Abstract
AdvisingBeanPostProcessor
implements
BeanFactoryAware
{
public
class
AsyncAnnotationBeanPostProcessor
extends
Abstract
BeanFactoryAwareAdvisingPostProcessor
{
/**
* The default name of the {@link TaskExecutor} bean to pick up: "taskExecutor".
...
...
@@ -119,6 +118,8 @@ public class AsyncAnnotationBeanPostProcessor extends AbstractAdvisingBeanPostPr
@Override
public
void
setBeanFactory
(
BeanFactory
beanFactory
)
{
super
.
setBeanFactory
(
beanFactory
);
Executor
executorToUse
=
this
.
executor
;
if
(
executorToUse
==
null
)
{
try
{
...
...
spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java
浏览文件 @
d5efe4f9
...
...
@@ -19,7 +19,6 @@ package org.springframework.scheduling.annotation;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Modifier
;
import
java.util.Collections
;
import
java.util.LinkedHashSet
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.TimeZone
;
...
...
@@ -43,6 +42,7 @@ import org.springframework.context.ApplicationContextAware;
import
org.springframework.context.ApplicationListener
;
import
org.springframework.context.EmbeddedValueResolverAware
;
import
org.springframework.context.event.ContextRefreshedEvent
;
import
org.springframework.core.MethodIntrospector
;
import
org.springframework.core.Ordered
;
import
org.springframework.core.annotation.AnnotationUtils
;
import
org.springframework.scheduling.TaskScheduler
;
...
...
@@ -54,7 +54,6 @@ import org.springframework.scheduling.support.CronTrigger;
import
org.springframework.scheduling.support.ScheduledMethodRunnable
;
import
org.springframework.util.Assert
;
import
org.springframework.util.ReflectionUtils
;
import
org.springframework.util.ReflectionUtils.MethodCallback
;
import
org.springframework.util.StringUtils
;
import
org.springframework.util.StringValueResolver
;
...
...
@@ -236,17 +235,15 @@ public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor,
public
Object
postProcessAfterInitialization
(
final
Object
bean
,
String
beanName
)
{
Class
<?>
targetClass
=
AopUtils
.
getTargetClass
(
bean
);
if
(!
this
.
nonAnnotatedClasses
.
contains
(
targetClass
))
{
final
Set
<
Method
>
annotatedMethods
=
new
LinkedHashSet
<
Method
>(
1
);
ReflectionUtils
.
doWithMethods
(
targetClass
,
new
MethodCallback
()
{
@Override
public
void
doWith
(
Method
method
)
throws
IllegalArgumentException
,
IllegalAccessException
{
for
(
Scheduled
scheduled
:
AnnotationUtils
.
getRepeatableAnnotations
(
method
,
Scheduled
.
class
,
Schedules
.
class
))
{
processScheduled
(
scheduled
,
method
,
bean
);
annotatedMethods
.
add
(
method
);
}
}
});
Map
<
Method
,
Set
<
Scheduled
>>
annotatedMethods
=
MethodIntrospector
.
selectMethods
(
targetClass
,
new
MethodIntrospector
.
MetadataLookup
<
Set
<
Scheduled
>>()
{
@Override
public
Set
<
Scheduled
>
inspect
(
Method
method
)
{
Set
<
Scheduled
>
scheduledMethods
=
AnnotationUtils
.
getRepeatableAnnotations
(
method
,
Scheduled
.
class
,
Schedules
.
class
);
return
(!
scheduledMethods
.
isEmpty
()
?
scheduledMethods
:
null
);
}
});
if
(
annotatedMethods
.
isEmpty
())
{
this
.
nonAnnotatedClasses
.
add
(
targetClass
);
if
(
logger
.
isTraceEnabled
())
{
...
...
@@ -255,6 +252,12 @@ public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor,
}
else
{
// Non-empty set of methods
for
(
Map
.
Entry
<
Method
,
Set
<
Scheduled
>>
entry
:
annotatedMethods
.
entrySet
())
{
Method
method
=
entry
.
getKey
();
for
(
Scheduled
scheduled
:
entry
.
getValue
())
{
processScheduled
(
scheduled
,
method
,
bean
);
}
}
if
(
logger
.
isDebugEnabled
())
{
logger
.
debug
(
annotatedMethods
.
size
()
+
" @Scheduled methods processed on bean '"
+
beanName
+
"': "
+
annotatedMethods
);
...
...
@@ -285,7 +288,7 @@ public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor,
"@Scheduled method '%s' found on bean target class '%s' but not "
+
"found in any interface(s) for a dynamic proxy. Either pull the "
+
"method up to a declared interface or switch to subclass (CGLIB) "
+
"proxies by setting proxy-target-class/proxyTargetClass to 'true'"
,
"proxies by setting proxy-target-class/proxyTargetClass to 'true'
.
"
,
method
.
getName
(),
method
.
getDeclaringClass
().
getSimpleName
()));
}
}
...
...
spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationPostProcessor.java
浏览文件 @
d5efe4f9
...
...
@@ -23,7 +23,7 @@ import javax.validation.ValidatorFactory;
import
org.aopalliance.aop.Advice
;
import
org.springframework.aop.Pointcut
;
import
org.springframework.aop.framework.
AbstractAdvisingBean
PostProcessor
;
import
org.springframework.aop.framework.
autoproxy.AbstractBeanFactoryAwareAdvising
PostProcessor
;
import
org.springframework.aop.support.DefaultPointcutAdvisor
;
import
org.springframework.aop.support.annotation.AnnotationMatchingPointcut
;
import
org.springframework.beans.factory.InitializingBean
;
...
...
@@ -58,7 +58,8 @@ import org.springframework.validation.annotation.Validated;
* @see org.hibernate.validator.method.MethodValidator
*/
@SuppressWarnings
(
"serial"
)
public
class
MethodValidationPostProcessor
extends
AbstractAdvisingBeanPostProcessor
implements
InitializingBean
{
public
class
MethodValidationPostProcessor
extends
AbstractBeanFactoryAwareAdvisingPostProcessor
implements
InitializingBean
{
private
Class
<?
extends
Annotation
>
validatedAnnotationType
=
Validated
.
class
;
...
...
spring-context/src/test/java/org/springframework/context/event/AnnotationDrivenEventListenerTests.java
浏览文件 @
d5efe4f9
...
...
@@ -61,6 +61,7 @@ import static org.junit.Assert.*;
/**
* @author Stephane Nicoll
* @author Juergen Hoeller
*/
public
class
AnnotationDrivenEventListenerTests
{
...
...
@@ -230,8 +231,8 @@ public class AnnotationDrivenEventListenerTests {
}
@Test
public
void
eventListenerWorksWithInterfaceProxy
()
throws
Exception
{
load
(
ProxyTestBean
.
class
);
public
void
eventListenerWorksWith
Simple
InterfaceProxy
()
throws
Exception
{
load
(
Scoped
ProxyTestBean
.
class
);
SimpleService
proxy
=
this
.
context
.
getBean
(
SimpleService
.
class
);
assertTrue
(
"bean should be a proxy"
,
proxy
instanceof
Advised
);
...
...
@@ -243,6 +244,20 @@ public class AnnotationDrivenEventListenerTests {
this
.
eventCollector
.
assertTotalEventsCount
(
1
);
}
@Test
public
void
eventListenerWorksWithAnnotatedInterfaceProxy
()
throws
Exception
{
load
(
AnnotatedProxyTestBean
.
class
);
AnnotatedSimpleService
proxy
=
this
.
context
.
getBean
(
AnnotatedSimpleService
.
class
);
assertTrue
(
"bean should be a proxy"
,
proxy
instanceof
Advised
);
this
.
eventCollector
.
assertNoEventReceived
(
proxy
.
getId
());
TestEvent
event
=
new
TestEvent
();
this
.
context
.
publishEvent
(
event
);
this
.
eventCollector
.
assertEvent
(
proxy
.
getId
(),
event
);
this
.
eventCollector
.
assertTotalEventsCount
(
1
);
}
@Test
public
void
eventListenerWorksWithCglibProxy
()
throws
Exception
{
load
(
CglibProxyTestBean
.
class
);
...
...
@@ -260,13 +275,43 @@ public class AnnotationDrivenEventListenerTests {
@Test
public
void
asyncProcessingApplied
()
throws
InterruptedException
{
loadAsync
(
AsyncEventListener
.
class
);
String
threadName
=
Thread
.
currentThread
().
getName
();
AnotherTestEvent
event
=
new
AnotherTestEvent
(
this
,
threadName
);
AsyncEventListener
listener
=
this
.
context
.
getBean
(
AsyncEventListener
.
class
);
this
.
eventCollector
.
assertNoEventReceived
(
listener
);
this
.
context
.
publishEvent
(
event
);
countDownLatch
.
await
(
2
,
TimeUnit
.
SECONDS
);
this
.
eventCollector
.
assertEvent
(
listener
,
event
);
this
.
eventCollector
.
assertTotalEventsCount
(
1
);
}
@Test
public
void
asyncProcessingAppliedWithInterfaceProxy
()
throws
InterruptedException
{
doLoad
(
AsyncConfigurationWithInterfaces
.
class
,
SimpleProxyTestBean
.
class
);
String
threadName
=
Thread
.
currentThread
().
getName
();
AnotherTestEvent
event
=
new
AnotherTestEvent
(
this
,
threadName
);
SimpleService
listener
=
this
.
context
.
getBean
(
SimpleService
.
class
);
this
.
eventCollector
.
assertNoEventReceived
(
listener
);
this
.
context
.
publishEvent
(
event
);
countDownLatch
.
await
(
2
,
TimeUnit
.
SECONDS
);
this
.
eventCollector
.
assertEvent
(
listener
,
event
);
this
.
eventCollector
.
assertTotalEventsCount
(
1
);
}
@Test
public
void
asyncProcessingAppliedWithScopedProxy
()
throws
InterruptedException
{
doLoad
(
AsyncConfigurationWithInterfaces
.
class
,
ScopedProxyTestBean
.
class
);
String
threadName
=
Thread
.
currentThread
().
getName
();
AnotherTestEvent
event
=
new
AnotherTestEvent
(
this
,
threadName
);
SimpleService
listener
=
this
.
context
.
getBean
(
SimpleService
.
class
);
this
.
eventCollector
.
assertNoEventReceived
(
listener
);
this
.
context
.
publishEvent
(
event
);
countDownLatch
.
await
(
2
,
TimeUnit
.
SECONDS
);
this
.
eventCollector
.
assertEvent
(
listener
,
event
);
this
.
eventCollector
.
assertTotalEventsCount
(
1
);
...
...
@@ -443,7 +488,6 @@ public class AnnotationDrivenEventListenerTests {
public
CountDownLatch
testCountDownLatch
()
{
return
new
CountDownLatch
(
1
);
}
}
...
...
@@ -530,7 +574,6 @@ public class AnnotationDrivenEventListenerTests {
}
return
event
.
content
;
}
}
...
...
@@ -560,6 +603,22 @@ public class AnnotationDrivenEventListenerTests {
}
@Component
static
class
AsyncEventListener
extends
AbstractTestEventListener
{
@Autowired
private
CountDownLatch
countDownLatch
;
@EventListener
@Async
public
void
handleAsync
(
AnotherTestEvent
event
)
{
assertTrue
(!
Thread
.
currentThread
().
getName
().
equals
(
event
.
content
));
collectEvent
(
event
);
countDownLatch
.
countDown
();
}
}
@Configuration
@Import
(
BasicConfiguration
.
class
)
@EnableAsync
(
proxyTargetClass
=
true
)
...
...
@@ -567,33 +626,82 @@ public class AnnotationDrivenEventListenerTests {
}
@Configuration
@Import
(
BasicConfiguration
.
class
)
@EnableAsync
(
proxyTargetClass
=
false
)
static
class
AsyncConfigurationWithInterfaces
{
}
interface
SimpleService
extends
Identifiable
{
void
handleIt
(
TestEvent
event
);
void
handleAsync
(
AnotherTestEvent
event
);
}
@Component
static
class
AsyncEventListener
extends
AbstractTestEventListener
{
static
class
SimpleProxyTestBean
extends
AbstractIdentifiable
implements
SimpleService
{
@Autowired
private
EventCollector
eventCollector
;
@Autowired
private
CountDownLatch
countDownLatch
;
@EventListener
@Override
public
void
handleIt
(
TestEvent
event
)
{
eventCollector
.
addEvent
(
this
,
event
);
}
@EventListener
@Async
public
void
handleAsync
(
AnotherTestEvent
event
)
{
assertTrue
(!
Thread
.
currentThread
().
getName
().
equals
(
event
.
content
));
collectEvent
(
event
);
eventCollector
.
addEvent
(
this
,
event
);
countDownLatch
.
countDown
();
}
}
interface
SimpleService
extends
Identifiable
{
@Component
@Scope
(
proxyMode
=
ScopedProxyMode
.
INTERFACES
)
static
class
ScopedProxyTestBean
extends
AbstractIdentifiable
implements
SimpleService
{
@Autowired
private
EventCollector
eventCollector
;
@Autowired
private
CountDownLatch
countDownLatch
;
@EventListener
void
handleIt
(
TestEvent
event
);
@Override
public
void
handleIt
(
TestEvent
event
)
{
eventCollector
.
addEvent
(
this
,
event
);
}
@EventListener
@Async
public
void
handleAsync
(
AnotherTestEvent
event
)
{
assertTrue
(!
Thread
.
currentThread
().
getName
().
equals
(
event
.
content
));
eventCollector
.
addEvent
(
this
,
event
);
countDownLatch
.
countDown
();
}
}
interface
AnnotatedSimpleService
extends
Identifiable
{
@EventListener
void
handleIt
(
TestEvent
event
);
}
@Component
@Scope
(
proxyMode
=
ScopedProxyMode
.
INTERFACES
)
static
class
ProxyTestBean
extends
AbstractIdentifiable
implements
SimpleService
{
static
class
AnnotatedProxyTestBean
extends
AbstractIdentifiable
implements
Annotated
SimpleService
{
@Autowired
private
EventCollector
eventCollector
;
...
...
@@ -645,7 +753,6 @@ public class AnnotationDrivenEventListenerTests {
public
void
handleTimestamp
(
Long
timestamp
)
{
collectEvent
(
timestamp
);
}
}
...
...
spring-tx/src/main/java/org/springframework/dao/annotation/PersistenceExceptionTranslationPostProcessor.java
浏览文件 @
d5efe4f9
/*
* Copyright 2002-201
4
the original author or authors.
* Copyright 2002-201
5
the original author 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,9 +18,8 @@ package org.springframework.dao.annotation;
import
java.lang.annotation.Annotation
;
import
org.springframework.aop.framework.
AbstractAdvisingBean
PostProcessor
;
import
org.springframework.aop.framework.
autoproxy.AbstractBeanFactoryAwareAdvising
PostProcessor
;
import
org.springframework.beans.factory.BeanFactory
;
import
org.springframework.beans.factory.BeanFactoryAware
;
import
org.springframework.beans.factory.ListableBeanFactory
;
import
org.springframework.stereotype.Repository
;
import
org.springframework.util.Assert
;
...
...
@@ -57,8 +56,7 @@ import org.springframework.util.Assert;
* @see org.springframework.dao.support.PersistenceExceptionTranslator
*/
@SuppressWarnings
(
"serial"
)
public
class
PersistenceExceptionTranslationPostProcessor
extends
AbstractAdvisingBeanPostProcessor
implements
BeanFactoryAware
{
public
class
PersistenceExceptionTranslationPostProcessor
extends
AbstractBeanFactoryAwareAdvisingPostProcessor
{
private
Class
<?
extends
Annotation
>
repositoryAnnotationType
=
Repository
.
class
;
...
...
@@ -78,6 +76,8 @@ public class PersistenceExceptionTranslationPostProcessor extends AbstractAdvisi
@Override
public
void
setBeanFactory
(
BeanFactory
beanFactory
)
{
super
.
setBeanFactory
(
beanFactory
);
if
(!(
beanFactory
instanceof
ListableBeanFactory
))
{
throw
new
IllegalArgumentException
(
"Cannot use PersistenceExceptionTranslator autodetection without ListableBeanFactory"
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录