Spring的JavaConfig和CustomScopeConfigurer问题

时间:2013-02-18 17:48:22

标签: java spring

我看到一些奇怪的行为,我希望这里有人可以对这个问题有所了解。

首先让我来描述一下我的设置。首先,一个简单的数据对象

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 bean时,conf对象Apple突然变为空。

更奇怪的是,如果我将CustomScopeConfigurer bean移动到TestConfig类,那么它就可以了。

是否有我不了解范围或特别是CustomScopeConfigurer对象的内容?

1 个答案:

答案 0 :(得分:17)

从Spring @Bean javadoc复制:

  

BeanFactoryPostProcessor-返回@Bean方法

     

必须特别考虑返回Spring 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方法引用。提醒一下,将为任何具有可分配给BeanFactoryPostProcessor的返回类型的非静态@Bean方法发出WARN级别的日志消息。