百木园-与人分享,
就是让自己快乐。

springmvc项目中InitializingBean执行2次

为了修复生产数据,需要执行一段一次性的代码。 鉴于是spring老项目,就想到了InitializingBean。

 

代码如下。服务启动后,log里发现出现2条“一次性任务开始”。 好在里面逻辑做了防重控制,没有受到什么影响。

@Slf4j
@Component
public class TransToBankBean implements InitializingBean {
    @Autowired
    private FixedLdysZhOrdersService xxxService;

    @Override
    public synchronized void afterPropertiesSet() {
        log.info(\"一次性任务开始\");
        ....
    }
}

 

今天理了一下程序配置。发现web.xml配置有问题。

<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<web-app xmlns=\"http://xmlns.jcp.org/xml/ns/javaee\"
         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
         xsi:schemaLocation=\"http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd\"
         version=\"4.0\">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mvc.xml,classpath:spring-mybatis.xml,classpath:spring-dubbo.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>SpringMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>
    <servlet-mapping>
        <servlet-name>SpringMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>/index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

 

注意到上面web.xml中有两个contextConfigLocation, 一个位于context-param参数中, 另一个位于servelt的init-param参数中。

问题就出现在这个contextConfigLocation上。

 

contextConfigLocation,名如其义,指的是context配置(文件)的位置。
servelt/init-param的contextConfig是为了加载DispatcherServlet的, 而context-param的contextConfig是为了加载web程序需要加载的数据库等等配置。

再来说说servlet节点配置:
servlet有这么几个属性:servlet-name、servlet-class、init-param。其中,servlet-class通常就是我们熟知的 DispatcherServlet。init-param中可以指定contextConfigLocation。
1) init-param里如果未配置contextConfigLocation,则要求程序在WEB-INF存在名为[servlet-name]-servlet.xml的配置文件,否则程序启动会报异常:java.io.FileNotFoundException:Could not open ServletContext resource [/WEB-INF/SpringMVC-servlet.xml] 。(注意:我这里servlet-name的值是SpringMVC,所以文件名字会是 SpringMVC-servlet.xml)
2) init-param里如果有contextConfigLocation配置,则DispatcherServlet会使用这个指定的配置文件作为配置。例如,我指定的参数值是classpath:spring-mvc.xml, 这个文件定义在main/resources下,编译后存在于程序包的classes目录中。

显然,上面web.xml中两个contextConfigLocation都指定了spring-mvc.xml。这个context文件里指定了component-scan包扫描路径。
上面定义的InitializingBean实现类就在这些package下面。所以,不难理解,这个类所覆写的afterPropertiesSet会被执行两次。

 

好,了解了上面的解释。那么,我们就知道该怎么改了。------>分离配置,解决扫描两遍的问题。
改造后的web.xml如下, 两处contextConfigLocation分别指定的是application-context.xml 和 spring-mvc.xml。两者各司其职 -----> application-context.xml是spring应用程序的上下文配置,不含springmvc配置; spring-mvc.xml中只有springmvc配置。

<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<web-app xmlns=\"http://xmlns.jcp.org/xml/ns/javaee\"
         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
         xsi:schemaLocation=\"http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd\"
         version=\"4.0\">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:application-context.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>SpringMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>
    <servlet-mapping>
        <servlet-name>SpringMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>/index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

 spring-mvc.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:mvc=\"http://www.springframework.org/schema/mvc\"
       xmlns:context=\"http://www.springframework.org/schema/context\"
       xsi:schemaLocation=\"http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd\">

    <!-- 扩充了注解驱动,可以将请求参数绑定到控制器参数 -->
    <mvc:annotation-driven/>

    <mvc:default-servlet-handler/>

    <!--    controller所在包-->
    <context:component-scan base-package=\"com.levy.rpcprovider.controller\"/>

</beans>

 


当看到一些不好的代码时,会发现我还算优秀;当看到优秀的代码时,也才意识到持续学习的重要!--buguge
本文来自博客园,转载请注明原文链接:https://www.cnblogs.com/buguge/p/16286630.html


hr.signhr{width:80%;margin:0 auto;border: 0;height: 4px;background-image: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.75), rgba(0, 0, 0, 0))}


来源:https://www.cnblogs.com/buguge/p/16286630.html
本站部分图文来源于网络,如有侵权请联系删除。

未经允许不得转载:百木园 » springmvc项目中InitializingBean执行2次

相关推荐

  • 暂无文章