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的主要内容,如果未能解决你的问题,请参考以下文章

thymeleaf-spring4:jar 找不到工件 - gradle intellij

无法自动装配服务:参数引用类但不存在此类服务

Spring:无法从父上下文自动装配 bean

Symfony 3.4 自动装配服务

具有自动装配的字段但得到无法自动装配字段消息

注入自动装配的依赖项失败,无法自动装配字段