簡體   English   中英

在Spring javaconfig中,如何初始化依賴於@Service的@Bean

[英]In Spring javaconfig, how to initialize a @Bean which depends on a @Service

我已經將基於Spring 4.0的項目從xml轉換為javaconfig。

在初始化時,我的一個bean需要通過Spring @Service( buildingService )訪問Hibernate以從DB獲取一些配置數據。 bean初始化如下所示:

@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而失敗。

我將buildingService添加到@DependsOn但它沒有幫助。

可能在@Bean之后處理@Service -annotated類!?

我可以自己初始化@Service -annotated類嗎?

編輯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是一個Spring托管Bean,並在@Configuration -annotated類中初始化,該類正在進行根上下文的初始化。

Smarty直接依賴於buildingService,如下所示:

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

我嘗試使用@PostConstruct注釋Smarty.init() ,但這並沒有改變任何東西。

請注意, Smarty.init()所做的第一件事是調用buildingService.getAll();

你對bean的生命周期感到困惑。 Spring必須首先創建bean才能注入任何東西。 在你的@Bean方法中,你已經創建了你的bean

Smarty bean = new Smarty(); 

然后立即調用其中一種方法

bean.init();

這似乎取決於注入的領域。

這兩個電話之間沒有任何內容。 你怎么期望Spring做任何事情?

相反,您可以使用@PostConstruct注釋您的init()方法。 一旦Spring完成初始化你的bean,即。 當你的@Bean方法返回並且Spring注入所有對象的注入目標時,它將自動調用該方法。

這里不需要@DependsOn

@Sevice注釋bean被自動發現並通過組件掃描進行初始化,以便在Spring Configuration上使用@ComponentScan

@ComponentScan

配置組件掃描指令以與@Configuration類一起使用。

@Bean用於手動創建bean,而不使用@Service或組件掃描等特殊注釋。

@Bean

表示方法生成由Spring容器管理的bean。 (...)通常,@ Node方法在@Configuration類中聲明。 在這種情況下,bean方法可以通過直接調用它們來引用同一個類中的其他@Bean方法。


上下文配置

@Autowired
EntityManager entityManager; //needs to access Hibernate

@Bean
Smarty smarty() {
   return = new Smarty(entityManager);
}

還有你的Smarty豆子

public Smarty {

   final EntityManager entityManager;

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

您不需要@DependsOn注釋,因為Smarty bean已經(或應該)直接依賴於BuildingService。 有關何時使用它的更多信息,請參閱@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();
    }
}
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM