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和动态代理

posted @ 2018-02-09 00:56  胡峻峥  阅读(3375)  评论(0编辑  收藏