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 ...
随机推荐
- 虚拟树研究-CheckBox初步判断只能在第一列
//虚拟树研究-CheckBox初步判断只能在第一列 procedure TWindowsXPForm.XPTreeInitNode(Sender: TBaseVirtualTree; ParentN ...
- SpringBoot定制错误的Json数据
(1)自定义异常处理&返回定制Json数据 @ControllerAdvice public class MyExceptionHandler { @ResponseBody @Excepti ...
- keras例子-matchnet
2015CVPR:MatchNet_ Unifying Feature and Metric Learning for Patch-Based Matching 主要是基于patch的图像特征匹配,基 ...
- ARMV8 datasheet学习笔记4:AArch64系统级体系结构之存储模型
1.前言 关于存储系统体系架构,可以概述如下: 存储系统体系结构的形式 VMSA 存储属性 2. 存储系统体系结构 2.1. 地址空间 指令地址空间溢出 指令地址计算((address_of ...
- CentOS 6.5环境实现corosync+pacemaker实现DRBD高可用
DRBD (Distributed Replicated Block Device)分布式复制块设备,它是 Linux 平台上的分散式储存系统,通常用于高可用性(high availability, ...
- Linux学习之CentOS(十二)--crontab命令的使用方法
http://www.cnblogs.com/xiaoluo501395377/archive/2013/04/06/3002602.html crontab命令常见于Unix和Linux的操作系统之 ...
- UNIX网络编程读书笔记:I/O模型(阻塞、非阻塞、I/O复用、信号驱动、异步)
I/O模型 UNIX下可用的5种I/O模型: (1)阻塞I/O (2)非阻塞I/O (3)I/O复用(select和poll) (4)信号驱动I/O(SIGIO) (5)异步I/O 对于一个套接口上的 ...
- SKlearn库学习曲线
思想: # 1.现将所有样本用交叉验证方法或者(随机抽样方法) 得到 K对 训练集-验证集# 2.依次对K个训练集,拿出数量不断增加的子集如m个,并在这些K*m个子集上训练模型.# 3.依次在对应训练 ...
- google 与服务器搭建
一.申请账号 二.创建实例 VPN设置 :https://juejin.im/post/5b665a51f265da0f7d4f1ab3
- *****hibernate主键生成
一.主键主键是关系数据库中的一个基本概念,它用来保证记录的唯一性主键都是没有业务含义的,所以开发 者不会.也不需要,显示地设置实体对象的主键值.但是对于数据库来说,主键是必须的 Hibernate内置 ...