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和動態代理


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM