如何获取方法上声明的注解

   开发过程当中部分场景需要获取到方法或类上的注解,但是经常会有无法渠道注解的情况,这种情况很可能是该注解所在的类是一个代理类,比如被AOP动态代理【注意:通过】。本文以CGLIB为例,说明为什么无法取到方法或类上的注解,还有如何取到注解。

      如果是增强的对象,比如JDK动态代理和CGLIB动态代理。因为CGLIB动态代理生成了一个新的继承了动态

原因是:

1.被增强的类

   

package com.changshin.annotation;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface WhiteList {
}
package com.changshin.component;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component
@Aspect
@Slf4j
public class WhiteListAspect {

    @Pointcut("@annotation(com.changshin.annotation.WhiteList)")
    public void whiteList(){
        log.info("空实现");
    }

    @Before("whiteList()")
    public void start(){
        log.info("对客户白名单进行校验1");
    }

    @AfterReturning("whiteList()")
    public void end(){
        log.info("对客户白名单进行校验2");
    }

}

package com.changshin.web;

import com.changshin.annotation.WhiteList;
import com.changshin.entity.dto.request.UserInfoRequest;
import com.changshin.entity.dto.response.UserInfoResponse;
import com.changshin.lock.BsnService;
import com.changshin.lock.BusinessLockEnum;
import com.changshin.lock.BusinessLockVO;
import com.changshin.lock.LockService;
import com.changshin.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.util.ClassUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

@RestController
public class UserApi {
    private static final Logger log = LoggerFactory.getLogger(UserApi.class);

    @Autowired
    private UserService userService;

    @Autowired
    private LockService lockService;

    @Autowired
    private BsnService bsnService;

    @Autowired
    private ApplicationContext applicationContext;

    @PostMapping(value = "user/queryUserName")
    public UserInfoResponse queryUserNameById(@RequestBody UserInfoRequest request){
        log.info("查询用户姓名请求参数",request);
        String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext,UserService.class);
        Class userServiceBean = applicationContext.getType(beanNames[0]);
        Method[] method1s = userServiceBean.getMethods();
        for (Method method:method1s) {
            if (method.isAnnotationPresent(WhiteList.class)){
                System.out.println("userServiceBean111");
            }
        }
        Class userServiceBeanTarget = null;
        //获取代理类代理的目标类
        if(!Proxy.isProxyClass(userServiceBean)){
            userServiceBeanTarget = ClassUtils.getUserClass(userServiceBean);
        }
        Method[] method2s = userServiceBeanTarget.getMethods();
        for (Method method:method2s) {
            if (method.isAnnotationPresent(WhiteList.class)){
                System.out.println("userServiceBeanTarget222");
            }
        }
        return null;
    }
}

 发现:

1.userServiceBean是userService进行CGLIB增强后的实例,非userService类型的

2.userServiceBeanTarget是userService类型的实例。

如何获取方法上声明的注解_第1张图片

 执行API请求代码,发现打印了userServiceBeanTarget222没有打印userServiceBean111。说明

userServiceBean没有获取到注解信息,userServiceBeanTarget获取到了注解信息。

也就是说增强类方法列表中没有获取到注解信息,增强类的目标类的方法列表中得到了注解信息。

如何获取方法上声明的注解_第2张图片

 此时userServiceBean.getMethods()实际上调用的是增强类的getMethods方法。对于CGLIB增强的类,需要先获取获取到增强类的目标类,获取到目标类后就可以通过getMethods方法获取到方法,通过获取方法上的注解方法最终获取到方法上的注解。

你可能感兴趣的:(spring,spring,boot,mybatis)