web-dev-qa-db-ja.com

Spring javaconfigで、@ Serviceに依存する@Beanを初期化する方法

Spring 4.0ベースのプロジェクトをxmlからjavaconfigに変換しました。

初期化時に、Beanの1つがHibernateにアクセスして、Spring @Service(buildingService)を介して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に追加しましたが、役に立ちませんでした。

おそらく@Service- annotatedクラスは@Bean!?の後に処理されます

@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;

@PostConstructSmarty.init()に注釈を付けてみましたが、これは何も変更しませんでした。

Smarty.init()が最初に行うことは、buildingService.getAll();を呼び出すことです。

16
yglodt

Beanのライフサイクルについて混乱しています。 Springは、何かを注入する前に、まずBeanを作成する必要があります。 _@Bean_メソッドで、Beanを作成しました

_Smarty bean = new Smarty(); 
_

その後、すぐにそのメソッドの1つを呼び出しました

_bean.init();
_

注入されるフィールドに依存しているようです。

これらの2つの呼び出しの間には何もありません。 Springに何かを期待しますか?

代わりに、init()メソッドに_@PostConstruct_の注釈を付けることができます。 SpringがBeanの初期化を完了すると、つまり_@Bean_メソッドが戻り、Springがオブジェクトのすべてのインジェクションターゲットをインジェクトすると、メソッドが自動的に呼び出されます。

ここでは_@DependsOn_は不要です。

19

@Sevice注釈付きBeanは、コンポーネントのスキャンを介して自動検出および初期化され、Spring構成で@ComponentScanを使用できるようにします。

@ComponentScan

@Configurationクラスで使用するコンポーネントスキャンディレクティブを設定します。

@Beanは、@Serviceやコンポーネントスキャンなどの特別な注釈を使用せずに、Beanを手動で作成するために使用されます。

@Bean

メソッドがSpringコンテナによって管理されるBeanを生成することを示します。 (...)通常、@ Beanメソッドは@Configurationクラス内で宣言されます。この場合、Beanメソッドは、directlyを呼び出すことにより、同じクラス内の他の@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;
   }
}
3
MariuszS

Smarty Beanは、BuildingServiceに直接依存している(または持っている必要がある)ので、@DependsOn注釈は必要ありません。使用するタイミングの詳細については、 @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();
    }
}
}
1
Pieter