Thymeleaf-Spring4 无法自动装配 TemplateEngine
Posted
技术标签:
【中文标题】Thymeleaf-Spring4 无法自动装配 TemplateEngine【英文标题】:Thymeleaf-Spring4 unable to autowire TemplateEngine 【发布时间】:2014-07-21 13:29:58 【问题描述】:我正在尝试将 Thymeleaf 电子邮件模板添加到工作中的 Spring MVC + Thymeleaf 应用程序中,如 here 所述。
当我尝试在我的服务类中自动装配 TemplateEngine 时收到此错误:
错误:org.springframework.web.context.ContextLoader - 上下文初始化失败 org.springframework.beans.factory.BeanCreationException:创建名为“mailManager”的bean时出错:注入自动装配的依赖项失败;嵌套异常是 org.springframework.beans.factory.BeanCreationException:无法自动装配字段:私有 org.thymeleaf.TemplateEngine no.test.lab.manager.MailManager.templateEngine;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有为依赖项找到类型为 [org.thymeleaf.TemplateEngine] 的合格 bean:预计至少有 1 个 bean 有资格作为此依赖项的自动装配候选者。依赖注解:@org.springframework.beans.factory.annotation.Autowired(required=true) 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475) 在 org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304) 在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) 在 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300) 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703) 在 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760) 在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482) 在 org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403) 在 org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306) 在 org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106) 在 org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4797) 在 org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5291) 在 org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) 在 org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901) 在 org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877) 在 org.apache.catalina.core.StandardHost.addChild(StandardHost.java:633) 在 org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:657) 在 org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1637) 在 java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) 在 java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) 在 java.util.concurrent.FutureTask.run(FutureTask.java:166) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 在 java.lang.Thread.run(Thread.java:722) 引起:org.springframework.beans.factory.BeanCreationException:无法自动装配字段:私有 org.thymeleaf.TemplateEngine no.test.lab.manager.MailManager.templateEngine;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有为依赖项找到类型为 [org.thymeleaf.TemplateEngine] 的合格 bean:预计至少有 1 个 bean 有资格作为此依赖项的自动装配候选者。依赖注解:@org.springframework.beans.factory.annotation.Autowired(required=true) 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508) 在 org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289) ... 27 更多 引起:org.springframework.beans.factory.NoSuchBeanDefinitionException:没有为依赖找到[org.thymeleaf.TemplateEngine]类型的合格bean:预计至少有1个bean有资格作为此依赖的自动装配候选者。依赖注解:@org.springframework.beans.factory.annotation.Autowired(required=true) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1103) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:963) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858) 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480) ... 29 更多 2014 年 6 月 1 日上午 8:15:01 org.apache.catalina.core.StandardContext listenerStart 严重:向 org.springframework.web.context.ContextLoaderListener 类的侦听器实例发送上下文初始化事件的异常 org.springframework.beans.factory.BeanCreationException:创建名为“mailManager”的bean时出错:注入自动装配的依赖项失败;嵌套异常是 org.springframework.beans.factory.BeanCreationException:无法自动装配字段:私有 org.thymeleaf.TemplateEngine no.test.lab.manager.MailManager.templateEngine;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有为依赖项找到类型为 [org.thymeleaf.TemplateEngine] 的合格 bean:预计至少有 1 个 bean 有资格作为此依赖项的自动装配候选者。依赖注解:@org.springframework.beans.factory.annotation.Autowired(required=true) 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475) 在 org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304) 在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) 在 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300) 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703) 在 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760) 在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482) 在 org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403) 在 org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306) 在 org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106) 在 org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4797) 在 org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5291) 在 org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) 在 org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901) 在 org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877) 在 org.apache.catalina.core.StandardHost.addChild(StandardHost.java:633) 在 org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:657) 在 org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1637) 在 java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) 在 java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) 在 java.util.concurrent.FutureTask.run(FutureTask.java:166) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 在 java.lang.Thread.run(Thread.java:722) 引起:org.springframework.beans.factory.BeanCreationException:无法自动装配字段:私有 org.thymeleaf.TemplateEngine no.test.lab.manager.MailManager.templateEngine;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有为依赖项找到类型为 [org.thymeleaf.TemplateEngine] 的合格 bean:预计至少有 1 个 bean 有资格作为此依赖项的自动装配候选者。依赖注解:@org.springframework.beans.factory.annotation.Autowired(required=true) 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508) 在 org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289) ... 27 更多 引起:org.springframework.beans.factory.NoSuchBeanDefinitionException:没有为依赖找到[org.thymeleaf.TemplateEngine]类型的合格bean:预计至少有1个bean有资格作为此依赖的自动装配候选者。依赖注解:@org.springframework.beans.factory.annotation.Autowired(required=true) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1103) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:963) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858) 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480) ... 29 更多
mvc-dispatcher-servlet.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="no.test.lab.web.controller" />
<tx:annotation-driven/>
<mvc:annotation-driven conversion-service="conversionService" />
<mvc:resources mapping="/css/**" location="/WEB-INF/css/" />
<mvc:resources mapping="/js/**" location="/WEB-INF/js/" />
<mvc:resources mapping="/images/**" location="/WEB-INF/images/" />
<mvc:resources mapping="/lib/**" location="/WEB-INF/lib/" />
<mvc:resources mapping="/assets/**" location="/WEB-INF/views/assets/" />
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatters">
<set>
<bean class="no.test.lab.web.formatter.DateFormatter"/>
</set>
</property>
</bean>
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations">
<list>
<value>WEB-INF\conf\config_$spring.profiles.active.properties</value>
<value>WEB-INF\conf\version.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>
<!-- BEGIN JSP/Tiles -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass">
<value>org.springframework.web.servlet.view.tiles2.TilesView</value>
</property>
<property name="order" value="1" />
</bean>
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tiles.xml</value>
</list>
</property>
</bean>
<!-- END JSP/Tiles -->
<!-- BEGIN Thymeleaf -->
<bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML5" />
<property name="cacheTTLMs" value="$thymeleaf.cache_ttl" />
<property name="order" value="0" />
</bean>
<!-- THYMELEAF: Template Resolver for email templates -->
<bean id="emailTemplateResolver" class="org.thymeleaf.templateresolver.ClassLoaderTemplateResolver">
<property name="prefix" value="/WEB-INF/mail/" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML5" />
<property name="characterEncoding" value="UTF-8" />
<property name="cacheTTLMs" value="$thymeleaf.cache_ttl" />
<property name="order" value="2" />
</bean>
<bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
<property name="templateResolvers">
<set>
<ref bean="templateResolver"/>
<ref bean="emailTemplateResolver"/>
</set>
</property>
<property name="additionalDialects">
<set>
<bean class="org.thymeleaf.extras.springsecurity3.dialect.SpringSecurityDialect"/>
</set>
</property>
</bean>
<bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine" />
<property name="viewNames" value="view_*" />
<property name="order" value="0" />
</bean>
<!-- END Thymeleaf -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="no.test.lab.web.interceptor.RootInterceptor" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/lab/**"/>
<bean class="no.test.lab.web.interceptor.LabInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
</beans>
pom.xml:
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring4</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity3</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
服务类:
@服务 公共类 MailManager @自动连线 私有模板引擎模板引擎; @自动连线 私有 JavaMailSender 邮件发送者; ...【问题讨论】:
你还有其他的Spring配置文件吗? 是的,有很多配置文件。 Spring批处理、集成、安全等。上面的bean其实来自mvc-dispatcher-servlet.xml 是否在mvc-dispatcher-servlet.xml
或其他文件中启用了组件扫描?
是的。我用整个mvc-dispatcher-servlet.xml
更新了这个问题。应用程序正在从 JSP/Tiles 迁移到 Thymeleaf,因此也有 JSP/Tiles 的视图解析器。如果我从服务类中删除自动装配的 TemplateEngine,其他一切都正常(当然邮件模板部分除外)。
【参考方案1】:
您需要将templateEngine
移动到根应用程序上下文,因为这是您定义MailManager
的位置。您当前配置 Spring 的方式 templateEngine
是在 Web 应用程序上下文中定义的,这意味着根上下文中的 bean 无法使用它。
为此,只需将 templateEngine
bean 及其依赖项移动到 Spring 配置文件中,您在其中启用了对 controller
以外的包的组件扫描。
【讨论】:
谢谢 :) 我将 TemplateEngine 和两个模板解析器移到应用程序上下文中。以上是关于Thymeleaf-Spring4 无法自动装配 TemplateEngine的主要内容,如果未能解决你的问题,请参考以下文章