zoukankan      html  css  js  c++  java
  • cglib动态代理导致注解丢失问题及如何修改注解允许被继承

    现象

      SOAService这个bean先后经过两个BeanPostProcessor,会发现代理之后注解就丢失了。

      

        

    开启了cglib代理

    @SpringBootApplication
    @EnableAspectJAutoProxy(proxyTargetClass = true)
    public class Application {
        public static void main(String[] args) {
            SpringApplication app = new SpringApplication(Application.class);
            app.run(args);
        }
    }

    为什么开启这个代理模式呢

      http://www.cnblogs.com/hujunzheng/p/8428422.html 

    如何解决这个问题

      在自定义注解上添加@Inherited。如果是第三方的注解,调整项目接口层或者拿到这个注解通过代码方式加上@Inherited注解, 或者如下图所示。

      

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        Service anon = bean.getClass().getAnnotation(Service.class);
        if (anon != null) {
            try {
                InvocationHandler h = Proxy.getInvocationHandler(anon);
    
                //设置@Service注解支持继承,应对动态代理导致类上的@Service注解丢失
                Field typeField = h.getClass().getDeclaredField("type");
                typeField.setAccessible(true);
                Field annotationTypeField = Class.class.getDeclaredField("annotationType");
                annotationTypeField.setAccessible(true);
                AnnotationType annotationType = (AnnotationType) annotationTypeField.get(typeField.get(h));
                Field inheritedField = AnnotationType.class.getDeclaredField("inherited");
                this.updateFinalModifiers(inheritedField);
                inheritedField.set(annotationType, true);
    
                // 获取 AnnotationInvocationHandler 的 memberValues 字段
                Field memberValuesField = h.getClass().getDeclaredField("memberValues");
                // 因为这个字段事 private final 修饰,所以要打开权限
                memberValuesField.setAccessible(true);
                // 获取 memberValues
                Map memberValues = (Map) memberValuesField.get(h);
    
                Service service = Stream.of(bean.getClass().getInterfaces())
                        .filter(iface -> iface.getAnnotation(Service.class) != null)
                        .collect(Collectors.toList())
                        .get(0)
                        .getAnnotation(Service.class);
    
                memberValues.put("version", service.version());
                memberValues.put("group", service.group());
            } catch (Exception e) {
                throw new BeanCreationException(String.format("%s %s %s %s %s"
                            , "修改"
                            , ClassUtils.getQualifiedName(bean.getClass())
                            , "的注解"
                            , ClassUtils.getQualifiedName(Service.class)
                            , "的 group值和version值出错")
                        , e);
            }
        }
        return bean;
    }

      参考链接:Annotation和动态代理

  • 相关阅读:
    怎么查看京东店铺的品牌ID
    PPT编辑的时候很卡,放映的时候不卡,咋回事?
    codevs 1702素数判定2
    codevs 2530大质数
    codevs 1488GangGang的烦恼
    codevs 2851 菜菜买气球
    hdu 5653 Bomber Man wants to bomb an Array
    poj 3661 Running
    poj 1651 Multiplication Puzzle
    hdu 2476 String Painter
  • 原文地址:https://www.cnblogs.com/hujunzheng/p/8433980.html
Copyright © 2011-2022 走看看