0

これは、Spring + Jackson + joda time のフォローアップの質問です: シリアライゼーション/デシリアライゼーション形式を指定する方法は? .

コードの最終バージョンを書いていたとき、初めて次のように書きました: (関連する部分のみが示されています)

@Configuration
public class WebMvcConfiguration
{
    @Bean
    public WebMvcConfigurerAdapter apiWebMvcConfiguration()
    {
        return new ApiWebMvcConfiguration();
    }

    public class ApiWebMvcConfiguration extends WebMvcConfigurerAdapter
    {
        public ApiWebMvcConfiguration()
        {
            log.debug("### ApiWebMvcConfiguration");
        }

        @Bean
        public UserInterceptor userInterceptor()
        {
            return new UserInterceptor(false);
        }

        @Override
        public void addInterceptors(InterceptorRegistry registry)
        {
            log.debug("### addInterceptors");
            registry.addInterceptor(userInterceptor())
                .addPathPatterns("/api/user/**");
        }
    }

    private static final Log log =
        LogFactory.getLog(WebMvcConfiguration.class);
}

Spring Boot のデフォルトの @EnableWebMvc クラスが使用されるため、@EnableWebMvc はありません。
userInterceptor Bean は、Bean でもある WebMvcConfigurerAdapter クラスにあることに注意してください。

アプリケーションを実行すると、次のエラーが発生しました:
(自分のクラスのクラス パス名が「...」に置き換えられました)

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name '...WebMvcConfiguration$ApiWebMvcConfiguration': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [...WebMvcConfiguration$ApiWebMvcConfiguration]: No default constructor found; nested exception is java.lang.NoSuchMethodException: ...WebMvcConfiguration$ApiWebMvcConfiguration.<init>()
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1076)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1021)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:609)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
    at ...Application.main(Application.java:17)
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [...WebMvcConfiguration$ApiWebMvcConfiguration]: No default constructor found; nested exception is java.lang.NoSuchMethodException: ...WebMvcConfiguration$ApiWebMvcConfiguration.<init>()
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:85)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1069)
    ... 14 more
Caused by: java.lang.NoSuchMethodException: ...WebMvcConfiguration$ApiWebMvcConfiguration.<init>()
    at java.lang.Class.getConstructor0(Class.java:2810)
    at java.lang.Class.getDeclaredConstructor(Class.java:2053)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:80)
    ... 15 more

次に、ApiWebMvcConfiguration クラスを static 内部クラスに変更しました。

アプリケーションは「正常に」開始されましたが、ApiWebMvcConfiguration クラスが 2 回インスタンス化されました。つまり、「### ApiWebMvcConfiguration」が 2 回出力されました。したがって、「### addInterceptors」が 2 回出力されました。

次に、UserIntercepter のコードを実行すると、@Autowired JdbcTemplate が null のため失敗しました。つまり、@Autowired はオブジェクトに対して機能していませんでした。(JdbcTemplate は他のオブジェクトで @Autowired に成功しました)

そこで、Spring + Jackson + joda time: how to specify the serialization/deserialization format?に示すように、コードを最終バージョンに変更しました。つまり、UserIntercepter Bean が ApiWebMvcConfiguration から取り出され、問題はなくなりました。

これは正しい動作ですか?
@Bean をネストしてはいけませんか?

4

2 に答える 2

0

@Configuration クラス内のネストされたクラスは、常に @Bean として解釈されます。したがって、独自の明示的な @Bean 定義を追加して、2 回登録しました。

于 2013-12-19T07:37:35.923 に答える
0

Spring はApiWebMvcConfigurationそれ自体をインスタンス化しようとします。非静的内部クラスは通常のクラスのようにインスタンス化できないため、これは機能しません。外部クラスのインスタンスへの参照が必要です。したがって、「デフォルトのコンストラクターが見つかりません」というエラーメッセージが表示されます。

内部クラスを静的クラスに変更すると、インスタンス化は機能しますが、お気づきのように、インスタンス化はまだ 2 回行われます。

問題は の @Bean注釈ですuserInterceptor()。このメソッドから Bean を取得できることを Spring に伝えます。しかし、それを取得するために、Spring は のインスタンスを必要としますApiWebMvcConfiguration。したがって、それ自体を作成します。しかし、メソッドによって別のものが作成されapiWebMvcConfiguration()ます。

于 2013-12-19T07:37:02.177 に答える