注解本身不是代理,而是运行时可读的元数据标记;jdk通过proxy.newproxyinstance()为注解接口自动生成代理实例,其invocationhandler为annotationinvocationhandler;框架则基于注解信息主动创建业务代理以实现增强逻辑。

注解本身不是代理,也不直接生成代理类;它只是元数据标记。真正把注解和动态代理联系起来的,是“在运行时读取注解 + 主动创建代理”这一整套协作机制。
注解是触发代理的“开关”
Java 注解(尤其是 @Retention(RetentionPolicy.RUNTIME) 的)会被保留在字节码中,运行时可通过反射获取。但仅靠 getAnnotation() 并不会自动产生代理对象——它只返回一个注解接口的实例。
这个实例其实是 JDK 用动态代理悄悄造出来的:
- JVM 不允许直接 new 一个注解接口,所以当你调用
clazz.getAnnotation(XXX.class),底层会通过Proxy.newProxyInstance()创建一个实现了该注解接口的代理对象 - 这个代理对象的
InvocationHandler是 JDK 内置的AnnotationInvocationHandler,它把方法调用(比如say())转为从内部的memberValuesMap 中取值 - 也就是说:你看到的注解对象,本身就是个动态代理实例
注解驱动外部代理的典型流程
在框架(如 Spring AOP、MyBatis)中,注解更多是“配置信号”,真正干活的是开发者或框架写的代理逻辑:
- 扫描类/方法上的注解(如
@Transactional、@Cacheable) - 根据注解存在与否、属性值等条件,决定是否要为目标对象创建代理(JDK 或 CGLIB)
- 把注解信息传给
InvocationHandler或MethodInterceptor,在invoke()中做相应增强(如开启事务、查缓存)
例如:@Transactional 不会自己开启事务,而是告诉 Spring:“请为这个 Bean 创建一个事务代理,并在方法执行前后管理数据库连接和提交回滚”。
关键区别:两类代理,不同层级
需要分清两个层次的代理:
- 注解接口的代理:JDK 自动为你生成,不可见、不可控,只为让注解“看起来像一个真实对象”
-
业务对象的代理:你(或框架)主动调用
Proxy.newProxyInstance()或 CGLIB 创建,用于增强目标类行为,注解只是它的决策依据之一
二者没有继承或嵌套关系,只是共用了动态代理技术,在不同环节发挥作用。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











