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和动态代理
cglib动态代理导致注解丢失问题及如何修改注解允许被继承的更多相关文章
- 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。
基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...
- Spring -- <tx:annotation-driven>注解基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)的区别。
借鉴:http://jinnianshilongnian.iteye.com/blog/1508018 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional ...
- Spring <tx:annotation-driven>注解 JDK动态代理和CGLIB动态代理 区别。
基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...
- 【Java EE 学习 51】【Spring学习第三天】【cglib动态代理】【AOP和动态代理】【切入点表达式】
一.cglib动态代理 1.简介 (1)CGlib是一个强大的,高性能,高质量的Code生成类库.它可以在运行期扩展Java类与实现Java接口. (2) 用CGlib生成代理类是目标类的子类. (3 ...
- Atitit 代理CGLIB 动态代理 AspectJ静态代理区别
Atitit 代理CGLIB 动态代理 AspectJ静态代理区别 1.1. AOP 代理主要分为静态代理和动态代理两大类,静态代理以 AspectJ 为代表:而动态代理则以 spring AOP 为 ...
- Java Proxy和CGLIB动态代理原理
动态代理在Java中有着广泛的应用,比如Spring AOP,Hibernate数据查询.测试框架的后端mock.RPC,Java注解对象获取等.静态代理的代理关系在编译时就确定了,而动态代理的代理关 ...
- 动态代理的两种方式,以及区别(静态代理、JDK与CGLIB动态代理、AOP+IoC)
Spring学习总结(二)——静态代理.JDK与CGLIB动态代理.AOP+IoC 目录 一.为什么需要代理模式 二.静态代理 三.动态代理,使用JDK内置的Proxy实现 四.动态代理,使用cg ...
- Java之代理(jdk静态代理,jdk动态代理,cglib动态代理,aop,aspectj)
一.概念 代理是什么呢?举个例子,一个公司是卖摄像头的,但公司不直接跟用户打交道,而是通过代理商跟用户打交道.如果:公司接口中有一个卖产品的方法,那么公司需要实现这个方法,而代理商也必须实现这个方法. ...
- Spring源码剖析5:JDK和cglib动态代理原理详解
AOP的基础是Java动态代理,了解和使用两种动态代理能让我们更好地理解 AOP,在讲解AOP之前,让我们先来看看Java动态代理的使用方式以及底层实现原理. 转自https://www.jiansh ...
随机推荐
- 数据库运维平台~inception回滚功能
一 简介:inception的另一个激动人心的功能,很强大.二 功能简介: inception会针对已经执行sql语句进行1 记录 2 生成回滚语句三 备份: 1 启用远程备份机制(强烈建议一台单 ...
- 解决Centos下yum无法更新
问题: http://mirrors.cloud.aliyuncs.com/epel/6/x86_64/repodata/repomd.xml: [Errno 14] PYCURL ERROR 6 - ...
- ARMV8 datasheet学习笔记3:AArch64应用级体系结构
1.前言 本文主要从应用的角度介绍ARMV8的编程模型和存储模型 2. AArch64应用级编程模型 从应用的角度看到的ARM处理器元素: 可见的元素(寄存器/指令) 说明 可见的寄存器 R0-R30 ...
- Delphi中的动态包,有详细建立包的步骤(答案很简单:因为包的功能强大)
为什么要使用包? 答案很简单:因为包的功能强大.设计期包(design-time package)简化了自定义组件的发布和安装:而运行期包(run-time package)则更是给传统的程序设计注入 ...
- Python3学习笔记21-实例属性和类属性
由于Python是动态语言,根据类创建的实例可以任意绑定属性. 给实例绑定属性的方法是通过实例变量,或者通过self变量: class Student(object): def __init__(se ...
- linux 内核是什么?
一:linux系统如何构成的?User space:User Applications and GNU C library (glibc)kernel space:System Call interf ...
- centos6.5环境openldap实战之ldap配置详解及web管理工具lam(ldap-account-manager)使用详解
ldap常用名称解释 1.环境搭建 操作系统:centos6.5 x86_64 关闭防火墙.selinux 开启时间同步 # crontab -e 加入 # time sync */5 * * * * ...
- Ex 6_16 旧货销售问题_第七次作业
即可 子问题定义:定义数组B(S,j),其中 B(S,j)表示在子集S中结束位置为j的子问题的最大收益值,其中j的前一个地点有两种情况,第一种情况是某个拍卖会 另一种情况是从家里出发. 递归关系: 初 ...
- 常用的Unicode值范围
汉字:[0x4e00,0x9fa5](或十进制[19968,40869])数字:[0x30,0x39](或十进制[48, 57])小写字母:[0x61,0x7a](或十进制[97, 122])大写字母 ...
- 2017-2018-2 20155309南皓芯 Exp8 WEB基础实践
基础问题回答 (1)什么是表单 表单在网页中主要负责数据采集功能.一个表单有三个基本组成部分: 表单标签:这里面包含了处理表单数据所用CGI程序的URL以及数据提交到服务器的方法. 表单域:包含了文本 ...