2016-12-29 2 views
0

私が知っている限り、春は管理されていないクラスに豆を注入するいくつかの方法を提供します。 AutowireCapableBeanFactoryを使用して明示的に行うことができます。 (How to inject dependencies into a self-instantiated object in Spring?なぜ春が自動的に非管理クラスの@Autowitredフィールドになるのですか?

しかし、私は春がそのような注入を自動的に実行すると、奇妙な(IMHO)の動作に直面しました。ここで

は春のバッチを持つ例であり、

構成:

@SpringBootConfiguration 
public class ProcessorJobConfig { 

//..... 

@Bean(name = "pullRestTemplate") 
public RestTemplate createPullRestTemplate() { 
    RestTemplate restTemplate = restTemplateBuilder.build(); 

    return restTemplate; 
} 

@Bean(name = "step") 
public Step step(@Autowired ItemReader<Measurement> itemReader, 
       @Autowired ItemProcessor<Measurement, Event> itemProcessor, 
       @Autowired ItemWriter<Event> itemWriter) { 
    return stepBuilderFactory.get("step") 
      .<Measurement, Event>chunk(Integer.MAX_VALUE) 
      .reader(itemReader) 
      .processor(itemProcessor) 
      .writer(itemWriter) 
      .build(); 
} 

@Bean(name = "restProcessorJob") 
public Job job(@Qualifier("step") Step step) throws Exception { 
    return jobBuilderFactory.get("restProcessorJob") 
      .start(step) 
      .build(); 
} 

@Bean 
public ItemReader<Measurement> itemReader() { 
    RestMeasureReader restMeasureReader = new RestMeasureReader(); // Use new() explicitly 
    return restMeasureReader; 
} 

//..... 
} 

リーダー:

public class RestMeasureReader implements ItemReader<Measurement> { 
private static final Logger LOGGER = LoggerFactory.getLogger(RestMeasureReader.class); 

/** 
* NOTE: This field will be injected automatically by spring, even we are using new() to create instance of this class. 
*/ 
@Autowired 
@Qualifier("pullRestTemplate") 
private RestTemplate restTemplate; 

@Override 
public Measurement read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException { 
    // do some stuff 
} 
} 

とアプリケーション自体

@EnableBatchProcessing 
@EnableTask 
@SpringBootApplication 
public class TestAutowiredTaskApplication { 
    public static void main(String[] args) { 
     SpringApplication.run(TestAutowiredTaskApplication.class, args); 
} 
} 

でも私は(新しい明示的な使用します)RestMeasureReaderをインスタンス化するには、そのRestTemplateフィールドを後で挿入します。 正常な動作ですか? new()を使ってオブジェクトを作成するとき、春が自動的にフィールドを挿入するとは思わない。

+1

Springの '@ Bean'アノテーションでアノテーションされたメソッドの中に、クラスの新しいインスタンスを作成しています。これは、Spring管理Beanになります。 '@ Bean'アノテーションを削除すると、それは春管理Beanではありません。私は、リファレンスガイド、特にJavaベースの設定に関するセクションを読むことをお勧めします。 –

答えて

2

@Configurationクラスの中でnewを使用することについて話しているのなら、それは正常な動作です。これはSpringのJava設定です。それはSpringの管理コンテキストです。コード内で明示的にitemReader()と呼ぶつもりはありません。 だから、あなたはこれをやろうとしているとき:

@Autowired 
private ItemReader<Measurement> iterReader; 

あなたはSpringのIoCのからあなたRestMeasureReaderのインスタンスを取得します。

コード内にnew RestMesureReader()を明示的にコールしようとすると、フィールドを注入したSpring Proxyではなく、RestMesureReaderの新しいインスタンスが取得されます。

itemReader()メソッド宣言から@Beanを削除してみてください。RestMesureReaderをオートワイヤできません。

したがって、基本的に@Configurationクラスは、実際のJavaコードではなくSpringの設定に過ぎません。あなたがnewと呼んでも、Springはあなたにプロキシクラスを返します。

詳細については、this guideを参照してください。

1

@Bean で注釈が付けられたメソッドによって返されたSpringプロセスBeanこれにより、Java構成を使用するときにオートワイヤリングまたはライブサイクルコールバックを使用できます。

よりミニマル例:aという名前のBeanが手動で作成された場合でも、ここで

@Configuration 
public class MyConfiguration { 

    @Bean 
    public A a() { 
    return new A(); 
    } 

    static class A { 
    @Autowired 
    private B b; 

    @PostConstruct 
    public void onPostConstruct() { 
     System.out.println("postConstruct: " + b); 
    } 
    } 

    @Component 
    static class B { 
    } 
} 

、春には、依存関係(b)を注入し、@PostConstructコールバックを呼び出します。

関連する問題