中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

springboot~獲取原注解的方法findMergedAnnotation使用場景(jing)

一 重要知識點

在Spring框架中,AnnotationUtils.findAnnotation()AnnotatedElementUtils.findMergedAnnotation()是兩(liang)種不(bu)同的(de)注解查找方(fang)式(shi),主要區別如下:

1. AnnotationUtils.findAnnotation()

  • 特點:直接查找原始注解
  • 局限性
    • 無法獲取被元注解(如@AliasFor)覆蓋的屬性值
    • 無法處理注解屬性覆蓋(Annotation Attribute Overrides)場景
    • 若注解是通過元注解(如@Component派生出的@Service)間接存在,可能無法正確獲取屬性值

2. AnnotatedElementUtils.findMergedAnnotation()

  • 特點:查找"合并后的"注解
  • 優勢
    • 支持Spring的注解屬性覆蓋機制(通過@AliasFor
    • 會遞歸處理元注解,合并屬性值
    • 能正確獲取經過覆蓋后的最終屬性值
    • 支持查找接口/父類上的注解(通過@Inherited

示例場景差異

@Spec(name = "defaultName") // 元注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Spec {
    String name() default "";
}

@Spec(name = "customName") // 實際使用的注解
public void someMethod() {}

// 測試結果:
AnnotationUtils.findAnnotation() -> 可能返回原始元注解的name="defaultName"
AnnotatedElementUtils.findMergedAnnotation() -> 會返回合并后的name="customName"

何時使用?

  • 需要原始注解時 → AnnotationUtils
  • 需要實際生效的注解屬性時 → AnnotatedElementUtils
  • Spring注解處理(如@Transactional等組合注解) → 優先使用AnnotatedElementUtils

建議在Spring環境下優先使用AnnotatedElementUtils,除(chu)非明確需要訪問(wen)未(wei)經處理(li)的原始注解。

二 Spring的注解屬性別名的應用

當你在自定義注解中使用@AliasFor@JmsListener的destination屬性賦值(zhi)時,Spring通過以下步驟處理:

1. 注解處理流程

// 你的自定義注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@JmsListener
public @interface MyCustomJmsListener {
    
    @AliasFor(annotation = JmsListener.class, attribute = "destination")
    String value() default "";
    
    // 其他屬性...
}

2. Spring JMS的內部處理機制

JmsListenerAnnotationBeanPostProcessor是處理@JmsListener的核心類:

// 簡化的處理邏輯
public class JmsListenerAnnotationBeanPostProcessor implements BeanPostProcessor {
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        // 掃描bean的方法,查找JmsListener注解
        for (Method method : bean.getClass().getMethods()) {
            // 這里會使用Spring的AnnotationUtils找到注解
            JmsListener jmsListener = AnnotatedElementUtils.findMergedAnnotation(
                method, JmsListener.class);
            
            if (jmsListener != null) {
                processJmsListener(jmsListener, method, bean);
            }
        }
        return bean;
    }
    
    private void processJmsListener(JmsListener jmsListener, Method method, Object bean) {
        // 獲取destination值
        String destination = jmsListener.destination();
        // 創建監聽器容器...
    }
}

3. 關鍵方法:AnnotatedElementUtils.findMergedAnnotation()

這是Spring處理注(zhu)解屬性的核心(xin)方法:

// Spring內部的處理邏輯
public static <A extends Annotation> A findMergedAnnotation(
        AnnotatedElement element, Class<A> annotationType) {
    
    // 1. 查找直接或元注解
    Annotation[] annotations = element.getAnnotations();
    
    for (Annotation ann : annotations) {
        // 2. 如果是目標注解直接返回
        if (annotationType.isInstance(ann)) {
            return (A) ann;
        }
        
        // 3. 遞歸處理元注解
        Annotation[] metaAnnotations = ann.annotationType().getAnnotations();
        for (Annotation metaAnn : metaAnnotations) {
            if (annotationType.isInstance(metaAnn)) {
                // 4. 處理屬性別名映射
                return synthesizeAnnotation(ann, metaAnn, element);
            }
        }
    }
    return null;
}

4. 屬性別名解析過程

private static <A extends Annotation> A synthesizeAnnotation(
        Annotation sourceAnnotation, 
        Annotation metaAnnotation, 
        AnnotatedElement element) {
    
    Map<String, Object> attributeMap = new HashMap<>();
    
    // 獲取元注解的屬性
    Method[] metaMethods = metaAnnotation.annotationType().getDeclaredMethods();
    for (Method metaMethod : metaMethods) {
        String attributeName = metaMethod.getName();
        
        // 檢查源注解是否有對應的別名屬性
        Method sourceMethod = findAliasMethod(sourceAnnotation, attributeName);
        if (sourceMethod != null) {
            // 使用源注解的值覆蓋元注解的值
            Object value = invokeMethod(sourceMethod, sourceAnnotation);
            attributeMap.put(attributeName, value);
        } else {
            // 使用元注解的默認值
            Object value = invokeMethod(metaMethod, metaAnnotation);
            attributeMap.put(attributeName, value);
        }
    }
    
    // 創建合成注解
    return AnnotationUtils.synthesizeAnnotation(attributeMap, 
        metaAnnotation.annotationType(), element);
}

5. 實際示例

假設你的(de)使用方式如(ru)下:

@Component
public class MyMessageListener {
    
    @MyCustomJmsListener("my-queue")
    public void handleMessage(String message) {
        // 處理消息
    }
}

三(san) Spring JMS的(de)處(chu)理過程:

  1. 發現注解:掃描到@MyCustomJmsListener注解
  2. 識別元注解:發現@MyCustomJmsListener@JmsListener元注解標記
  3. 屬性合并:通過@AliasForvalue="my-queue"映射到destination屬性
  4. 創建監聽器:使用合成后的@JmsListener(destination = "my-queue")創建JMS監聽容器

驗證方法

你可以通(tong)過(guo)以下方式驗(yan)證(zheng)這個(ge)機(ji)制:

@SpringBootTest
class JmsListenerTest {
    
    @Autowired
    private JmsListenerEndpointRegistry endpointRegistry;
    
    @Test
    void testCustomAnnotation() {
        // 檢查監聽器容器是否創建成功
        Collection<MessageListenerContainer> containers = 
            endpointRegistry.getListenerContainers();
        
        for (MessageListenerContainer container : containers) {
            if (container instanceof JmsListenerEndpointRegistry) {
                // 驗證destination是否正確設置
                String destination = ((AbstractJmsListenerContainer) container)
                    .getDestination();
                System.out.println("監聽的destination: " + destination);
            }
        }
    }
}

四 總結

Spring通過AnnotatedElementUtils和注解屬性別名機制,能夠正確識別你自定義注解中通過@AliasFor映射的屬(shu)性值。這種設計(ji)使得(de)注解組合和(he)自(zi)定(ding)義變得(de)非常靈(ling)活,是Spring框(kuang)架(jia)強大(da)的元編程能力的體現。

posted @ 2025-09-23 17:40  張占嶺  閱讀(64)  評論(0)    收藏  舉報