2013-02-18 63 views
8

我看到一些奇怪的行爲,我希望有人能在這個問題上發光。Spring的JavaConfig和CustomScopeConfigurer問題

讓我從描述我的設置開始。首先,一個簡單的數據對象

public class Apple { 
    private String name; 
    public Apple withName(String name) { 
     this.name = name; 
     return this; 
    } 
    public String getName() { 
     return name; 
    } 
} 

和測試類..

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes={TestConfig.class}) 
public class AppleTest { 
    @Autowired private Apple apples; 

    @Test 
    public void simpleTest() { 
     System.out.println("OBJ: "+apples); 
    } 
} 

在配置被如下

@Configuration 
public interface ConfigInterface { 
    public Apple getApple(); 
} 

隨着實現類

@Configuration 
@Import(AbstractTestConfig.class) 
public class TestConfig implements ConfigInterface { 
    public Apple getApple() { 
     return new Apple().withName("Granny apples"); 
    } 
} 

隨着配置依賴...

@Configuration 
public class AbstractTestConfig { 
    @Autowired ConfigInterface conf; 

    @Bean Apple myTestApple() { 
     return conf.getApple(); 
    } 
} 

這一切都很好。我運行測試,我看到了我期望的輸出。但後來我把一個扳手放在車輪上,並修改了AbstractTestConfig,如下所示。

@Configuration 
public class AbstractTestConfig { 
    @Autowired ConfigInterface conf; 

    @Bean Apple myTestApple() { 
     return conf.getApple(); 
    } 

    // NEW CODE 
    @Bean CustomScopeConfigurer scopeConfigurer() { 
     return new CustomScopeConfigurer(); 
    } 
} 

而且一下子@Autowired對象conf的當需要構建Apple豆爲空。

更奇怪的是,如果我將CustomScopeConfigurer bean移動到TestConfig類,那麼它就起作用了。

有什麼我不知道的範圍或特別是CustomScopeConfigurer對象?

回答

16

從春天@Bean javadoc複製:

的BeanFactoryPostProcessor返流@Bean方法

特別考慮必須採取的是回位彈簧的BeanFactoryPostProcessor(BFPP)類型@Bean方法。因爲BFPP對象必須在容器生命週期的早期實例化,所以它們可能會干擾@Configuration類中的@Autowired,@Value和@PostConstruct之類的註釋處理。爲避免這些生命週期問題,請將BFPP返回的@Bean方法標記爲靜態。例如:

@Bean 
public static PropertyPlaceholderConfigurer ppc() { 
    // instantiate, configure and return ppc ... 
} 

通過標記該方法爲靜態,它可以在不引起其聲明@Configuration類的實例化被調用,從而避免了上述的生命週期的衝突。但是請注意,如上所述,靜態@Bean方法不會被增強用於範圍檢查和AOP語義。這可以在BFPP的情況下解決,因爲它們通常不被其他@Bean方法引用。提醒一下,WARN級別的日誌消息將針對任何具有可分配給BeanFactoryPostProcessor的返回類型的非靜態@Bean方法發佈。

0

仔細審閱春天日誌輸出後,我來到這個小救星:

[junit] 1141 [main] WARN org.springframework.context.annotation.ConfigurationClassEnhancer - @Bean method AbstractTestConfig.scopeConfigurer is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean Javadoc for complete details 

我真的不明白,爲什麼有它作爲靜態有差別,但。

相關問題