Spring:WebMvcConfigurerAdapter bean注册了两次(Spring: WebMvcConfigurerAdapter bean registered twice)

编程入门 行业动态 更新时间:2024-10-21 23:20:59
Spring:WebMvcConfigurerAdapter bean注册了两次(Spring: WebMvcConfigurerAdapter bean registered twice)

这是Spring + Jackson + joda时间的后续问题:如何指定序列化/反序列化格式? 。

当我编写代码的最终版本时,我第一次写如下:(仅显示相关部分)

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

没有@EnableWebMvc,因为使用了默认的@EnableWebMvc类Spring Boot。 请注意,userInterceptor bean位于WebMvcConfigurerAdapter类中,该类也是一个bean。

当我运行该应用程序时,发生以下错误: (我自己的班级路径名被自己替换为'...')

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类更改为静态内部类。

应用程序“正常”启动,但ApiWebMvcConfiguration类已实例化两次。 也就是说,“### ApiWebMvcConfiguration”被打印两次。 因此,“### addInterceptors”被打印两次。

然后,当UserIntercepter的代码运行时,由于null @Autowired JdbcTemplate而失败。 也就是说,@ Autowired并不适用于该对象。 (JdbcTemplate在其他对象中成功@Autowired)

所以,我将代码更改为最终版本,如Spring + Jackson + joda时间所示:如何指定序列化/反序列化格式? 也就是说,UserIntercepter bean被拔出了ApiWebMvcConfiguration,问题就消失了。

这是正确的行为吗? @Bean不应该嵌套吗?

This is a followup question of Spring + Jackson + joda time: how to specify the serialization/deserialization format?.

When I was writing the final version of the code, for the first time I wrote it as follows: (only relevant portion is shown)

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

There is no @EnableWebMvc, since the default @EnableWebMvc class of Spring Boot is used. Notice that userInterceptor bean is in the WebMvcConfigurerAdapter class, which is also a bean.

When I've run the application, following error occured: (class pathnames of my classes were replaced to '...' by myself)

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

Then I changed ApiWebMvcConfiguration class to a static inner class.

Application was started 'normally', but ApiWebMvcConfiguration class was instantiated twice. That is, "### ApiWebMvcConfiguration" was printed twice. And accordingly, "### addInterceptors" was printed twice.

Then, when UserIntercepter's code ran, it failed because of null @Autowired JdbcTemplate. That is, @Autowired was not working for the object. (JdbcTemplate was successfully @Autowired in other objects)

So, I changed the code to the final version as shown in Spring + Jackson + joda time: how to specify the serialization/deserialization format?, that is, UserIntercepter bean was pulled out of ApiWebMvcConfiguration, the problem was gone.

Is this correct behaviour? Should @Bean not be nested?

最满意答案

Spring试图实例化ApiWebMvcConfiguration本身。 这不起作用,因为非静态内部类不能像普通类一样实例化。 他们需要引用外部类的实例。 因此出现错误消息“找不到默认构造函数”。

当您将内部类更改为静态类时,实例化会起作用,但正如您所注意到的,它仍然会发生两次。

问题是userInterceptor()的@Bean注释。 你告诉Spring它可以从这个方法获得一个bean。 但是为了获得一个,Spring需要一个ApiWebMvcConfiguration实例。 所以它自己创造了一个。 但是另一个是由apiWebMvcConfiguration()方法创建的。

Spring tries to instantiate the ApiWebMvcConfiguration itself. That does not work because non-static inner classes cannot be instantiated like normal classes. They need a reference to an instance of the outer class. Hence the error message "No default constructor found".

When you change the inner class to a static one, instantiation works, but as you noticed, it still happens twice.

The problem is the @Beanannotation for userInterceptor(). You tell Spring that it can get a bean from this method. But in order to get one, Spring needs an instance of ApiWebMvcConfiguration. So it creates one itself. But then another one is created by the apiWebMvcConfiguration() method.

更多推荐

本文发布于:2023-08-01 15:03:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1359192.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:两次   WebMvcConfigurerAdapter   Spring   registered   bean

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!