知識庫 / Spring RSS 訂閱

解決 Spring “未自動代理” 警告

Spring
HongKong
3
12:35 PM · Dec 06 ,2025

1. 概述

在本簡短教程中,我們將學習如何追蹤 Spring 中“未符合自動代理資格”消息的原因,以及如何解決它。  

首先,我們將創建一個簡單的實際應用代碼示例,該示例在應用程序啓動期間會導致該消息出現。 然後,我們將解釋為什麼會發生這種情況。

最後,我們將通過展示一個可工作的代碼示例,來提供該問題的解決方案。

2. “未符合自動代理”消息的原因

2.1. 示例配置

在解釋消息的原因之前,我們先構建一個示例,導致應用程序啓動期間出現該消息。

首先,我們將創建一個自定義 <em >RandomInt</em> 註解。我們將使用它來註解那些應在指定範圍內插入隨機整數的字段:

@Retention(RetentionPolicy.RUNTIME)
public @interface RandomInt {
    int min();

    int max();
}

第二,讓我們創建一個 <em >DataCache</em> 類,它是一個簡單的 Spring 組件。我們希望將緩存分配給一個隨機組,用於支持分片等,為此,我們將使用自定義註解對該字段進行標註:

@Component
public class DataCache {
    @RandomInt(min = 2, max = 10)
    private int group;
    private String name;
}

現在,讓我們來查看 RandomIntGenerator 類。它是一個 Spring 組件,我們將使用它來將隨機 int 值插入到由 RandomInt 註解標記的字段中:

@Component
public class RandomIntGenerator {
    private Random random = new Random();
    private DataCache dataCache;

    public RandomIntGenerator(DataCache dataCache) {
        this.dataCache = dataCache;
    }

    public int generate(int min, int max) {
        return random.nextInt(max - min) + min;
    }
}

需要注意的是,我們通過構造器注入將 DataCache 類自動注入到 RandomIntGenerator 中。

最後,我們創建一個 RandomIntProcessor 類,該類負責查找帶有 RandomInt 註解的字段,並將隨機值插入到這些字段中:

public class RandomIntProcessor implements BeanPostProcessor {
    private final RandomIntGenerator randomIntGenerator;

    public RandomIntProcessor(RandomIntGenerator randomIntGenerator) {
        this.randomIntGenerator = randomIntGenerator;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        Field[] fields = bean.getClass().getDeclaredFields();
        for (Field field : fields) {
            RandomInt injectRandomInt = field.getAnnotation(RandomInt.class);
            if (injectRandomInt != null) {
                int min = injectRandomInt.min();
                int max = injectRandomInt.max();
                int randomValue = randomIntGenerator.generate(min, max);
                field.setAccessible(true);
                ReflectionUtils.setField(field, bean, randomValue);
            }
        }
        return bean;
    }
}

它使用 org.springframework.beans.factory.config.BeanPostProcessor 接口來在類初始化之前訪問帶有註解的字段。

2.2. 測試我們的示例

即使一切編譯成功,當我們運行 Spring 應用程序並查看其日誌時,我們將會看到 Spring 的 BeanPostProcessorChecker 類生成的 “未符合自動代理” 消息:

INFO org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'randomIntGenerator' of type [com.baeldung.autoproxying.RandomIntGenerator] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

此外,我們發現依賴該機制的DataCache Bean 沒有按照我們預期的方式進行初始化:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {RandomIntProcessor.class, DataCache.class, RandomIntGenerator.class})
public class NotEligibleForAutoProxyingIntegrationTest {

    private RandomIntProcessor randomIntProcessor;

    @Autowired
    private DataCache dataCache;

    @Test
    public void givenAutowireInBeanPostProcessor_whenSpringContextInitialize_thenNotEligibleLogShouldShow() {
        assertEquals(0, dataCache.getGroup());
    }
}

儘管消息顯示,但應用程序並未崩潰。

2.3. 查找原因

警告是由 <em>RandomIntProcessor</em> 類及其自動注入的依賴項引起的。實現 <em>BeanPostProcessor</em> 接口的類在 <em>ApplicationContext</em> 的特殊啓動階段實例化,在任何其他 Bean 初始化之前。

此外,AOP 自動代理機制也是一個 <em>BeanPostProcessor</em> 接口的實現。因此,<em>BeanPostProcessor</em> 實現以及它們引用的 Bean 都不能直接進行自動代理。這意味着使用 AOP 的 Spring 功能(如自動注入、安全或事務註解)在這些類中可能無法按預期工作。

在我們的例子中,我們能夠將 <em>DataCache</em> 實例自動注入到 <em>RandomIntGenerator</em> 類中,而無需任何問題。但是,組字段未填充隨機整數。

3. 如何解決錯誤

為了消除“未符合自動代理資格”消息,我們需要打破BeanPostProcessor實現與其 Bean 依賴之間的循環。 在我們的情況下,我們需要告訴 IoC 容器延遲初始化 RandomIntGenerator Bean。我們可以使用 Spring 的 Lazy 註解:

public class RandomIntProcessor implements BeanPostProcessor {
    private final RandomIntGenerator randomIntGenerator;

    @Lazy
    public RandomIntProcessor(RandomIntGenerator randomIntGenerator) {
        this.randomIntGenerator = randomIntGenerator;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        //...
    }
}

Spring 在 postProcessBeforeInitialization 方法中,當 RandomIntProcessor 請求它時,會初始化 RandomIntGenerator bean。 此時,Spring 的 IoC 容器會實例化所有也符合自動代理資格的現有 Bean。

實際上,如果運行我們的應用程序,我們不會在日誌中看到 “not eligible for auto proxying” 消息。 此外,DataCache bean 的 group 字段將被隨機整數填充:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {RandomIntProcessor.class, DataCache.class, RandomIntGenerator.class})
public class NotEligibleForAutoProxyingIntegrationTest {

    private RandomIntProcessor randomIntProcessor;

    @Autowired
    private DataCache dataCache;

    @Test
    public void givenAutowireInBeanPostProcessor_whenSpringContextInitialize_thenGroupFieldShouldBePopulated() {
        assertNotEquals(0, dataCache.getGroup());
    }
}

4. 結論

在本文中,我們學習瞭如何追蹤並修復 Spring 中“未符合自動代理”消息的原因。懶加載在 Bean 構造過程中打破了依賴循環。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.