java 在 Spring 上下文中查找方法级别的自定义注释
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27929965/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Find method level custom annotation in a Spring context
提问by kamoor
All I wanted to find out was "all the class/methods in Springbeans which are annotated as @Versioned".
我只想找出“ Springbean 中所有被注释为@Versioned的类/方法”。
I created my custom annotation as,
我创建了我的自定义注释,
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Versioned {
.....
}
This annotation works perfectlywhen I use Java reflection to find methods as:
当我使用 Java 反射来查找方法时,此注释非常有效:
for(Method m: obj.getClass().getMethods()){
if(m.isAnnotationPresent(Versioned.class)){
.... // Do something
}
But it does not work when I access Spring beans and try similar check:
但是当我访问 Spring bean 并尝试类似的检查时它不起作用:
public class VersionScanner implements ApplicationContextAware{
public void setApplicationContext(ApplicationContext applicationContext){
for(String beanName: applicationContext.getBeanDefinitionNames()){
for(Method m: applicationContext.getBean(beanName).getClass().getDeclaredMethods()){
if(m.isAnnotationPresent(Versioned.class){
// This is not WORKING as expected for any beans with method annotated
}
}
}
}
}
In fact, this code does find other annotations such as @RequestMapping. I am not sure what I am doing wrong with my custom annotation.
事实上,这段代码确实找到了其他注解,例如@RequestMapping。我不确定我的自定义注释做错了什么。
回答by owaism
Going through your code, I figured out that you are using Spring AOP with CGLIB Proxying. Due to which your classes (which have methods annotated with @Versioned
) are being proxied.
通过您的代码,我发现您正在使用带有 CGLIB 代理的 Spring AOP。因此,您的类(具有用 注释的方法@Versioned
)被代理。
I have tested this solution with your code base.
我已经用你的代码库测试了这个解决方案。
Use the following code, and it should resolve your issue. Look for more options below the code snippet:
使用以下代码,它应该可以解决您的问题。在代码片段下方寻找更多选项:
@Configuration
public class VersionScanner implements ApplicationContextAware {
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
for (String beanName : applicationContext.getBeanDefinitionNames()) {
Object obj = applicationContext.getBean(beanName);
/*
* As you are using AOP check for AOP proxying. If you are proxying with Spring CGLIB (not via Spring AOP)
* Use org.springframework.cglib.proxy.Proxy#isProxyClass to detect proxy If you are proxying using JDK
* Proxy use java.lang.reflect.Proxy#isProxyClass
*/
Class<?> objClz = obj.getClass();
if (org.springframework.aop.support.AopUtils.isAopProxy(obj)) {
objClz = org.springframework.aop.support.AopUtils.getTargetClass(obj);
}
for (Method m : objClz.getDeclaredMethods()) {
if (m.isAnnotationPresent(Versioned.class)) {
//Should give you expected results
}
}
}
}
}
To detect a proxy class:
检测代理类:
- For Spring AOP proxy using any proxying mechanism use
org.springframework.aop.support.AopUtils#isAoPProxy
- If you are proxying with Spring CGLIB (not via Spring AOP), use
org.springframework.cglib.proxy.Proxy#isProxyClass
- If you are proxying using JDK Proxy, use
java.lang.reflect.Proxy#isProxyClass
- 对于使用任何代理机制的 Spring AOP 代理,请使用
org.springframework.aop.support.AopUtils#isAoPProxy
- 如果您使用 Spring CGLIB(不是通过 Spring AOP)进行代理,请使用
org.springframework.cglib.proxy.Proxy#isProxyClass
- 如果您使用 JDK 代理进行代理,请使用
java.lang.reflect.Proxy#isProxyClass
I have just written one if
condition which is sufficient in your case; but in case multiple proxying utilities are used, multiple if-else
conditions will have to be written based on the information above.
我刚刚写了一个if
条件,对你的情况来说是充分的;但如果使用多个代理实用程序,if-else
则必须根据上述信息编写多个条件。
回答by Angad
applicationContext.getBean(beanName).getClass()
gives you the proxied class that Spring creates around your target class.
applicationContext.getBean(beanName).getClass()
为您提供 Spring 在您的目标类周围创建的代理类。
What you want is to get hold of the target class, if any, from your Spring bean.
您想要的是从 Spring bean 中获取目标类(如果有)。
Spring provides a nice utility class for resolving this called AopUtils.class.
Spring 提供了一个很好的实用程序类来解决这个问题,称为 AopUtils.class。
Below is how you would use it:
以下是您将如何使用它:
for(String beanName: applicationContext.getBeanDefinitionNames()){
Method[] methods = AopUtils.getTargetClass(applicationContext.getBean(beanName)).getDeclaredMethods();
for(Method m: methods){
if(m.isAnnotationPresent(Versioned.class){
}
}
}
Note that you will have to import the spring-aop
Mavendependency to get hold of the AopUtils class:
请注意,您必须导入spring-aop
Maven依赖项才能获取 AopUtils 类:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
回答by AH-64
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
for (String beanName : applicationContext.getBeanDefinitionNames()) {
Object obj = applicationContext.getBean(beanName);
Class<?> objClz = obj.getClass();
if (org.springframework.aop.support.AopUtils.isAopProxy(obj)) {
objClz = org.springframework.aop.support.AopUtils.getTargetClass(obj);
}
for (Method m : objClz.getDeclaredMethods()) {
if (m.isAnnotationPresent(Transactional.class)) {
Transactional transactional = m.getAnnotation(Transactional.class);
Class<? extends Throwable>[] value = transactional.rollbackFor();
if (value == null){
// help !!!
// If value is null, I want to set a value for him like Exception.class How can I modify it?
}
}
}
}
}