想象你是一位快递员,负责给一个大型社区送快递。社区里有几百户人家,但只有特定家庭需要特殊服务:
- 普通快递:直接放快递柜
- 生鲜快递:需要冷藏处理
- 贵重物品:需要本人签收
- 药品快递:需要优先配送
@annotation
就像你手中的智能标签扫描器,它能精准识别每个包裹上的特殊标签,让你只对贴有特定标签的包裹提供特殊服务。
一、核心概念:注解就是快递标签
1. 定义标签(创建注解)
// 生鲜标签
@Target(ElementType.METHOD) // 贴在方法上
@Retention(RetentionPolicy.RUNTIME) // 运行时可见
public @interface FreshDelivery {
int storageTemp() default 4; // 冷藏温度
}
// 贵重物品标签
public @interface ValuableItem {
String signatureRequired() default "yes";
}
2. 贴标签(方法添加注解)
public class DeliveryService {
// 普通快递(无标签)
public void deliverRegular(String address) {
System.out.println("普通快递送到" + address);
}
// 生鲜快递(贴冷藏标签)
@FreshDelivery(storageTemp = 2)
public void deliverFreshFood(String address) {
System.out.println("生鲜送到" + address);
}
// 贵重物品(贴签收标签)
@ValuableItem
public void deliverJewelry(String address) {
System.out.println("珠宝送到" + address);
}
}
三、@annotation
就是你的智能扫描器
@Aspect
@Component
public class DeliveryAspect {
// 扫描生鲜标签
@Before("@annotation(fresh)")
public void handleFresh(FreshDelivery fresh) {
System.out.println("启用冷藏箱,温度设置为: " + fresh.storageTemp() + "℃");
}
// 扫描贵重物品标签
@Around("@annotation(valuable)")
public Object handleValuable(ProceedingJoinPoint pjp, ValuableItem valuable) {
System.out.println("要求收件人出示身份证");
System.out.println("需要签收: " + valuable.signatureRequired());
try {
// 执行配送
return pjp.proceed();
} finally {
System.out.println("已确认签收,拍照存档");
}
}
}
四、工作流程:精准服务
实际配送场景:
public static void main(String[] args) {
DeliveryService service = getDeliveryService(); // 获取代理对象
service.deliverRegular("A栋101"); // 普通快递
// 输出: 普通快递送到A栋101
service.deliverFreshFood("B栋202"); // 生鲜快递
// 输出:
// 启用冷藏箱,温度设置为: 2℃
// 生鲜送到B栋202
service.deliverJewelry("C栋303"); // 贵重物品
// 输出:
// 要求收件人出示身份证
// 需要签收: yes
// 珠宝送到C栋303
// 已确认签收,拍照存档
}
五、为什么需要 @annotation
?
问题 | 无注解的解决方案 | 使用 @annotation 的解决方案 |
---|---|---|
精准定位 | 按地址筛选:"B栋的都冷藏" | 直接扫描包裹标签 |
差异化服务 | 所有生鲜统一4℃冷藏 | 根据标签设置不同温度 |
扩展性 | 新增药品配送需修改筛选规则 | 只需新增药品标签 |
代码耦合 | 配送服务需要知道处理逻辑 | 配送服务只贴标签,不关心处理 |
六、@annotation
的独特优势
精确制导:像激光制导导弹一样精准定位
// 只处理带@MedicalDelivery标签的方法
@Around("@annotation(MedicalDelivery)")
参数传递:读取标签上的参数
@annotation(medical) // 获取注解实例
int priority = medical.priority(); // 读取优先级参数
动态启用:通过标签开关功能
// 只有带@EnableLogging的方法才记录日志
@Before("@annotation(EnableLogging)")
解耦设计:业务代码只需声明需求
// 业务方法只需关注自己需要什么
@FreshDelivery(storageTemp=5)
public void deliverDairy() {...}
七、对比其他定位方式
1. 按楼栋配送(包路径匹配)
// 处理com.delivery.fresh包下所有方法
@Before("execution(* com.delivery.fresh..*(..))")
- 问题:包内可能有不需要冷藏的普通快递
2. 按物品类型配送(接口匹配)
// 处理实现Perishable接口的类
@Before("within(com.delivery.Perishable+)")
3. 智能标签扫描(@annotation
)
// 精确处理贴有@FreshDelivery标签的方法
@Before("@annotation(FreshDelivery)")
八 、为什么它叫 @annotation
?
在Spring AOP中:
@annotation
是一个切点指示符(Pointcut Designator)- 它专门用于匹配带有特定注解的方法
- 语法:
@annotation(annotation-type)
// 扫描带@SpecialService标签的方法 @Before("@annotation(com.example.SpecialService)")
十、总结:@annotation
的本质
它就像快递员的智能标签扫描器:
- 识别需求:扫描方法上的注解标签
- 精准服务:只为带标签的方法提供增强
- 参数读取:获取标签上的配置参数
- 解耦设计:业务代码只需声明需求,不关心实现