在Spring Javaconfig中,如何初始化@bean取决于@Service



我已将基于弹簧的项目从XML转换为Javaconfig。

初始化时,我的一个豆子需要访问Hibernate,以通过Spring @Service(buildingService)从DB中获取一些config-data。豆初始化看起来像这样:

@Bean
@DependsOn({ "transactionManager", "webSocketHandler", "buildingService" })
Smarty smarty() {
    Smarty bean = new Smarty();
    bean.init(); // I also tried @Bean(initMethod = "init") with no difference
    return bean;
}

问题在于,在bean.init()中,访问了该服务,而使用NullPointerException

失败。

我向@DependsOn添加了buildingService,但没有帮助。

可能在@Bean之后处理@Service通知类!?

我可以预先初始化 @Service宣布的课程吗?

编辑1

感谢到目前为止的所有反馈!

我需要添加一些详细信息:

BuildingService不是@Bean,它是@Service,看起来像这样:

@Service("buildingService")
@Transactional
public class BuildingService {
...
    public List<Building> getAll() {
        final Session session = sessionFactory.getCurrentSession();
        final Query query = session.createQuery("from Building order by name");
        return query.list();
    }
...
}

smarty是弹簧托管的bean,并在@Configuration宣布的类中进行初始化,该类正在执行root -context的初始化。

Smarty对建筑物的服务有直接的依赖,例如:

@Resource(name = "buildingService")
private BuildingService     buildingService;

我尝试使用@PostConstruct注释Smarty.init(),但这并没有更改任何内容。

请注意,Smarty.init()的第一件事是调用buildingService.getAll();

您对豆的生命周期感到困惑。弹簧必须首先创建bean才能注入任何东西。在您的@Bean方法中,您创建了bean

Smarty bean = new Smarty(); 

然后立即称为其方法之一

bean.init();

似乎取决于注入的字段。

这两个电话之间没有什么。您期望春天做什么?

相反,您可以使用@PostConstruct注释init()方法。春季完成初始化的豆子,即。当您的@Bean方法返回并弹簧注入所有对象的注入目标时,它将自动调用该方法。

@DependsOn在这里不需要。

@Sevice带注释的豆是自动发现的,并通过组件扫描初始化,以启用此spring配置上的@ComponentScan

@ComponentScan

配置用于与@Configuration类一起使用的组件扫描指令。

@Bean用于手动创建豆类,而无需使用诸如@Service或组件扫描的特殊注释。

@Bean

表明一种方法会产生由弹簧容器管理的bean。(...) 通常,@BEAN方法在@configuration类中声明。在这种情况下,BEAN方法可以通过将其调用直接

来引用同一类中的其他@bean方法。

上下文配置

@Autowired
EntityManager entityManager; //needs to access Hibernate
@Bean
Smarty smarty() {
   return = new Smarty(entityManager);
}

和您的Smarty bean

public Smarty {
   final EntityManager entityManager;
   public Smarty(EntityManager entityManager){
      this.entityManager = entityManager;
   }
}

您不需要@DependsOn注释,因为您聪明的Bean具有(或应该)对建筑物的直接依赖性。有关何时使用的更多信息,请参见@DependsOn Javadoc。

以下示例演示了如何解决问题:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SmartyTest.TestConfig.class)
public class SmartyTest {
@Autowired
Smarty1 smarty1;
@Autowired
Smarty2 smarty2;
@Test
public void testSmarty() throws Exception {
}
@Configuration
static class TestConfig {
    @Bean
    public BuildingService buildingService() {
        return new BuildingService();
    }
    @Bean
    public Smarty1 smarty1(BuildingService buildingService) {
        Smarty1 smarty = new Smarty1(buildingService);
        smarty.init();
        return smarty; // manually inject dependencies & handle initialisation
    }
    @Bean
    public Smarty2 smarty2() {
        // injecting the building service & initialising the component is handled by spring
        // by using @Autowired & @PostConstruct(-> alternative to @Bean(initMethod="init"))
        return new Smarty2();
    }
}

static class BuildingService {
    public void buildSomething() {
        System.out.println("BuildingService: I am building something!");
    }
}

static class Smarty1 {
    BuildingService buildingService;
    Smarty1(BuildingService buildingService) {
        this.buildingService = buildingService;
    }
    public void init() {
        System.out.println("Smarty 1: initialising ...");
        buildingService.buildSomething();
    }
}
static class Smarty2 {
    @Autowired
    BuildingService buildingService;
    @PostConstruct
    public void init() {
        System.out.println("Smarty 2: initialising ...");
        buildingService.buildSomething();
    }
}
}

最新更新