Spring Boot ConflictingBeanDefinitionException:@Controller 的注解指定的 bean 名称 class
Spring Boot ConflictingBeanDefinitionException: Annotation-specified bean name for @Controller class
我的 Spring 启动应用程序中一直出现 ConflictingBeanDefinitionException
错误。我不完全确定如何解决它,我有几个 @Configuration
注释 classes 帮助设置 Thymeleaf,Spring 安全和 Web。为什么应用程序尝试设置 homeController
两次? (它在哪里尝试这样做?)
错误是:
org.springframework.beans.factory.BeanDefinitionStoreException:
Failed to parse configuration class [org.kemri.wellcome.hie.Application]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException:
Annotation-specified bean name 'homeController' for bean class [org.kemri.wellcome.hie.HomeController] conflicts with existing, non-compatible bean definition of same name and class [org.kemri.wellcome.hie.controller.HomeController]
我的 spring 引导主应用程序初始化程序:
@EnableScheduling
@EnableAspectJAutoProxy
@EnableCaching
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
protected final SpringApplicationBuilder configure(final SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}
我的数据库配置文件:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages="org.kemri.wellcome.hie.repositories")
@PropertySource("classpath:application.properties")
public class DatabaseConfig {
@Autowired
private Environment env;
@Autowired
private DataSource dataSource;
@Autowired
private LocalContainerEntityManagerFactoryBean entityManagerFactory;
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("spring.datasource.driverClassName"));
dataSource.setUrl(env.getProperty("spring.datasource.url"));
dataSource.setUsername(env.getProperty("spring.datasource.username"));
dataSource.setPassword(env.getProperty("spring.datasource.password"));
return dataSource;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactory =
new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setDataSource(dataSource);
// Classpath scanning of @Component, @Service, etc annotated class
entityManagerFactory.setPackagesToScan(
env.getProperty("spring.jpa.hibernate.entitymanager.packagesToScan"));
// Vendor adapter
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
entityManagerFactory.setJpaVendorAdapter(vendorAdapter);
// Hibernate properties
Properties additionalProperties = new Properties();
additionalProperties.put(
"hibernate.dialect",
env.getProperty("spring.jpa.hibernate.dialect"));
additionalProperties.put(
"hibernate.showsql",
env.getProperty("spring.jpa.hibernate.showsql"));
additionalProperties.put(
"hibernate.hbm2ddl.auto",
env.getProperty("spring.jpa.hibernate.hbm2ddl.auto"));
entityManagerFactory.setJpaProperties(additionalProperties);
return entityManagerFactory;
}
@Bean
public JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager =
new JpaTransactionManager();
transactionManager.setEntityManagerFactory(
entityManagerFactory.getObject());
return transactionManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
}
我的 Thymeleaf 配置文件:
@Configuration
public class ThymeleafConfig {
@Bean
public ServletContextTemplateResolver templateResolver(){
ServletContextTemplateResolver thymeTemplateResolver = new ServletContextTemplateResolver();
thymeTemplateResolver.setPrefix("/WEB-INF/views/");
thymeTemplateResolver.setSuffix(".html");
thymeTemplateResolver.setTemplateMode("HTML5");
return thymeTemplateResolver;
}
@Bean
public SpringSecurityDialect springSecurityDialect(){
SpringSecurityDialect dialect = new SpringSecurityDialect();
return dialect;
}
@Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.addTemplateResolver(templateResolver());
Set<IDialect> dialects = new HashSet<IDialect>();
dialects.add(springSecurityDialect());
engine.setAdditionalDialects(dialects);
return engine;
}
@Bean
public ThymeleafViewResolver thymeleafViewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
resolver.setViewClass(ThymeleafTilesView.class);
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
}
我的网络配置 class:
@Configuration
@PropertySource("classpath:application.properties")
public class WebConfig extends WebMvcAutoConfigurationAdapter {
@Autowired
private Environment env;
@Bean
public JavaMailSenderImpl javaMailSenderImpl() {
JavaMailSenderImpl mailSenderImpl = new JavaMailSenderImpl();
mailSenderImpl.setHost(env.getProperty("smtp.host"));
mailSenderImpl.setPort(env.getProperty("smtp.port", Integer.class));
mailSenderImpl.setProtocol(env.getProperty("smtp.protocol"));
mailSenderImpl.setUsername(env.getProperty("smtp.username"));
mailSenderImpl.setPassword(env.getProperty("smtp.password"));
Properties javaMailProps = new Properties();
javaMailProps.put("mail.smtp.auth", true);
javaMailProps.put("mail.smtp.starttls.enable", true);
mailSenderImpl.setJavaMailProperties(javaMailProps);
return mailSenderImpl;
}
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager();
}
}
我的控制器(设置控制器时出错)
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
/**
* Simply selects the home view to render by returning its name.
*/
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
return "index.html";
}
}
什么可能导致我的控制器 class 出现 ConflictingBeanDefinitionException
错误?
您似乎有两个 entityManagerFactory,一个将自动装配,一个将以编程方式解析为 Bean:
@Autowired
private LocalContainerEntityManagerFactoryBean entityManagerFactory;
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
...
}
我认为您只需要在 entityManagerFactory() 方法中配置工厂。
正如我发现的那样,解决方案是通过在组件扫描中包含一个过滤器来禁用双重初始化。就我而言:
@EnableScheduling
@EnableAspectJAutoProxy
@EnableCaching
@Configuration
@ComponentScan(basePackages = { "org.kemri.wellcome.hie" },
excludeFilters = {@Filter(value = Controller.class, type = FilterType.ANNOTATION)})
@EnableAutoConfiguration
@PropertySource("classpath:application.properties")
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
我在使用 spring-boot 生成的 .war 文件时遇到了同样的问题。批准的解决方案(Timothy Tuti 自己的解决方案)对我来说并没有完全按原样工作,但我稍微调整了一下,它就工作了。我刚刚将以下行添加到我的 Application.java:
@ComponentScan(basePackages = { "com.mypackage" })
作为参考,这里是我的完整 Application.java
package com.inmoment.devchallenge;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.config.EnableNeo4jRepositories;
import org.springframework.data.neo4j.config.Neo4jConfiguration;
@SpringBootApplication
@Configuration
@ComponentScan(basePackages = { "com.inmoment.devchallenge.controller" })
@EnableAutoConfiguration
public class Application extends SpringBootServletInitializer {
@Configuration
@EnableNeo4jRepositories(basePackages = "com.inmoment.devchallenge.repository")
static class ApplicationConfig extends Neo4jConfiguration {
public ApplicationConfig() {
setBasePackage("com.inmoment.devchallenge.repository");
}
@Bean
GraphDatabaseService graphDatabaseService() {
return new GraphDatabaseFactory().newEmbeddedDatabase("accessingdataneo4j.db");
}
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
我 运行 遇到同样的问题,但出于不同的原因。
如果您在项目中四处移动 类 而未能执行 'clean',也会发生这种情况。
我使用 gradle 和 spring-boot 插件。现在我通常 运行:
$> ./gradlew clean bootRun
当我使用 InteliJ运行 进行 Spring 集成测试 时,我遇到了同样的问题。
重构后,我的一个控制器 class 实际上在 /out/production/classes 目录中是重复的,该目录是自 2017.2 版以来 Intelij 的默认输出目录.
由于 gradle 输出目录不同(它是 build/classes),gradle clean 目标没有效果。
对我来说,解决方案是手动删除 /out/production/classes 并重新 运行 我的集成测试。
对于没有 2 个输出目录的可能的持久解决方案,请参阅 here
我在更改了几个文件夹名称和相关包名称后使用 mvn 遇到了这个问题。比我应用 maven clean 和 运行 spring 再次启动,一切都解决了:
mvn clean
mvn spring-boot:run
我通过在 class.
之上添加一个 bean 名称解决了我的问题
@Component("myBeanName1")
public class MyBean {
}
然后用@Autowire初始化它,这样:
@Autowire
@Qualifier("myBeanName1")
MyBean myBean;
我的 Spring 启动应用程序中一直出现 ConflictingBeanDefinitionException
错误。我不完全确定如何解决它,我有几个 @Configuration
注释 classes 帮助设置 Thymeleaf,Spring 安全和 Web。为什么应用程序尝试设置 homeController
两次? (它在哪里尝试这样做?)
错误是:
org.springframework.beans.factory.BeanDefinitionStoreException:
Failed to parse configuration class [org.kemri.wellcome.hie.Application]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException:
Annotation-specified bean name 'homeController' for bean class [org.kemri.wellcome.hie.HomeController] conflicts with existing, non-compatible bean definition of same name and class [org.kemri.wellcome.hie.controller.HomeController]
我的 spring 引导主应用程序初始化程序:
@EnableScheduling
@EnableAspectJAutoProxy
@EnableCaching
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
protected final SpringApplicationBuilder configure(final SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}
我的数据库配置文件:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages="org.kemri.wellcome.hie.repositories")
@PropertySource("classpath:application.properties")
public class DatabaseConfig {
@Autowired
private Environment env;
@Autowired
private DataSource dataSource;
@Autowired
private LocalContainerEntityManagerFactoryBean entityManagerFactory;
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("spring.datasource.driverClassName"));
dataSource.setUrl(env.getProperty("spring.datasource.url"));
dataSource.setUsername(env.getProperty("spring.datasource.username"));
dataSource.setPassword(env.getProperty("spring.datasource.password"));
return dataSource;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactory =
new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setDataSource(dataSource);
// Classpath scanning of @Component, @Service, etc annotated class
entityManagerFactory.setPackagesToScan(
env.getProperty("spring.jpa.hibernate.entitymanager.packagesToScan"));
// Vendor adapter
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
entityManagerFactory.setJpaVendorAdapter(vendorAdapter);
// Hibernate properties
Properties additionalProperties = new Properties();
additionalProperties.put(
"hibernate.dialect",
env.getProperty("spring.jpa.hibernate.dialect"));
additionalProperties.put(
"hibernate.showsql",
env.getProperty("spring.jpa.hibernate.showsql"));
additionalProperties.put(
"hibernate.hbm2ddl.auto",
env.getProperty("spring.jpa.hibernate.hbm2ddl.auto"));
entityManagerFactory.setJpaProperties(additionalProperties);
return entityManagerFactory;
}
@Bean
public JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager =
new JpaTransactionManager();
transactionManager.setEntityManagerFactory(
entityManagerFactory.getObject());
return transactionManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
}
我的 Thymeleaf 配置文件:
@Configuration
public class ThymeleafConfig {
@Bean
public ServletContextTemplateResolver templateResolver(){
ServletContextTemplateResolver thymeTemplateResolver = new ServletContextTemplateResolver();
thymeTemplateResolver.setPrefix("/WEB-INF/views/");
thymeTemplateResolver.setSuffix(".html");
thymeTemplateResolver.setTemplateMode("HTML5");
return thymeTemplateResolver;
}
@Bean
public SpringSecurityDialect springSecurityDialect(){
SpringSecurityDialect dialect = new SpringSecurityDialect();
return dialect;
}
@Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.addTemplateResolver(templateResolver());
Set<IDialect> dialects = new HashSet<IDialect>();
dialects.add(springSecurityDialect());
engine.setAdditionalDialects(dialects);
return engine;
}
@Bean
public ThymeleafViewResolver thymeleafViewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
resolver.setViewClass(ThymeleafTilesView.class);
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
}
我的网络配置 class:
@Configuration
@PropertySource("classpath:application.properties")
public class WebConfig extends WebMvcAutoConfigurationAdapter {
@Autowired
private Environment env;
@Bean
public JavaMailSenderImpl javaMailSenderImpl() {
JavaMailSenderImpl mailSenderImpl = new JavaMailSenderImpl();
mailSenderImpl.setHost(env.getProperty("smtp.host"));
mailSenderImpl.setPort(env.getProperty("smtp.port", Integer.class));
mailSenderImpl.setProtocol(env.getProperty("smtp.protocol"));
mailSenderImpl.setUsername(env.getProperty("smtp.username"));
mailSenderImpl.setPassword(env.getProperty("smtp.password"));
Properties javaMailProps = new Properties();
javaMailProps.put("mail.smtp.auth", true);
javaMailProps.put("mail.smtp.starttls.enable", true);
mailSenderImpl.setJavaMailProperties(javaMailProps);
return mailSenderImpl;
}
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager();
}
}
我的控制器(设置控制器时出错)
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
/**
* Simply selects the home view to render by returning its name.
*/
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
return "index.html";
}
}
什么可能导致我的控制器 class 出现 ConflictingBeanDefinitionException
错误?
您似乎有两个 entityManagerFactory,一个将自动装配,一个将以编程方式解析为 Bean:
@Autowired
private LocalContainerEntityManagerFactoryBean entityManagerFactory;
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
...
}
我认为您只需要在 entityManagerFactory() 方法中配置工厂。
正如我发现的那样,解决方案是通过在组件扫描中包含一个过滤器来禁用双重初始化。就我而言:
@EnableScheduling
@EnableAspectJAutoProxy
@EnableCaching
@Configuration
@ComponentScan(basePackages = { "org.kemri.wellcome.hie" },
excludeFilters = {@Filter(value = Controller.class, type = FilterType.ANNOTATION)})
@EnableAutoConfiguration
@PropertySource("classpath:application.properties")
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
我在使用 spring-boot 生成的 .war 文件时遇到了同样的问题。批准的解决方案(Timothy Tuti 自己的解决方案)对我来说并没有完全按原样工作,但我稍微调整了一下,它就工作了。我刚刚将以下行添加到我的 Application.java:
@ComponentScan(basePackages = { "com.mypackage" })
作为参考,这里是我的完整 Application.java
package com.inmoment.devchallenge;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.config.EnableNeo4jRepositories;
import org.springframework.data.neo4j.config.Neo4jConfiguration;
@SpringBootApplication
@Configuration
@ComponentScan(basePackages = { "com.inmoment.devchallenge.controller" })
@EnableAutoConfiguration
public class Application extends SpringBootServletInitializer {
@Configuration
@EnableNeo4jRepositories(basePackages = "com.inmoment.devchallenge.repository")
static class ApplicationConfig extends Neo4jConfiguration {
public ApplicationConfig() {
setBasePackage("com.inmoment.devchallenge.repository");
}
@Bean
GraphDatabaseService graphDatabaseService() {
return new GraphDatabaseFactory().newEmbeddedDatabase("accessingdataneo4j.db");
}
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
我 运行 遇到同样的问题,但出于不同的原因。
如果您在项目中四处移动 类 而未能执行 'clean',也会发生这种情况。
我使用 gradle 和 spring-boot 插件。现在我通常 运行:
$> ./gradlew clean bootRun
当我使用 InteliJ运行 进行 Spring 集成测试 时,我遇到了同样的问题。
重构后,我的一个控制器 class 实际上在 /out/production/classes 目录中是重复的,该目录是自 2017.2 版以来 Intelij 的默认输出目录. 由于 gradle 输出目录不同(它是 build/classes),gradle clean 目标没有效果。
对我来说,解决方案是手动删除 /out/production/classes 并重新 运行 我的集成测试。
对于没有 2 个输出目录的可能的持久解决方案,请参阅 here
我在更改了几个文件夹名称和相关包名称后使用 mvn 遇到了这个问题。比我应用 maven clean 和 运行 spring 再次启动,一切都解决了:
mvn clean
mvn spring-boot:run
我通过在 class.
之上添加一个 bean 名称解决了我的问题@Component("myBeanName1")
public class MyBean {
}
然后用@Autowire初始化它,这样:
@Autowire
@Qualifier("myBeanName1")
MyBean myBean;