spring-循环依赖

2020-04-15  本文已影响0人  16325

spring依赖

在项目中有个springContextHolder,实现applicationContextAware。
这次需求增加了一个filter,用的servlet3.0的注解webfilter。然后再init方法中用这个holder的静态方法获取了一个spring的service。
开发完,测试没问题能拿到。但是原理不是很清楚。

谁先加载

spring的加载使用的编码方式,实现了WebApplicationInitializer,最终是实现了ServletContainerInitializer接口。

ServletContainerInitializer可以编码定义web.xml 中的内容。
这里有一个疑问:web.xml,注解,ServletContainerInitializer中编码增加的listener,filter等。他们的顺序如何控制?

上边的问题没有查到资料。但是肯定一点就是,servlet三大将肯定是按照listener-fileter-servlet这个顺序来加载的。也就是说我新增的WebFilter注解定义的过滤器,肯定是在spring加载完配置之后才init,所以这里肯定可以去到spring的applicatonContext

Filter的顺序

ServletContainerInitializer 的调用时机

以Tomcat举例, 以下逻辑总结于Tomcat7.x

public interface ServletContainerInitializer {
    void onStartup(Set<Class<?>> var1, ServletContext var2) throws ServletException;
}

ServletContext提供了各种各样的方法,可以完全替代所有web.xml中的配置。

spring配置(原始)

spring的配置,一般在项目中包括两部分。一是核心功能也就是ioc和aop,还有就是mvc,当然如果使用struts的话就没有这部分配置了。

先看看原始的,用xml的方式。核心配置
包括各种bean的定义,注入等。

<!--spring监听器 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!--spring配置文件 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
classpath:applicationContext_pub.xml,classpath:applicationContext-cxf-rs.xml,
        </param-value>
    </context-param>

springMvc
包括消息转换,controller的异常处理,当然也可以定义正常的bean

<!--配置springMVC-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-config.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

spring配置(编码)

servlet3.0之后可以使用ServletContainerInitializer来编码定义了。这个接口会在容器初始化得到执行。然后可以注册listener,servlet等。

其实就是把web.xml中的配置用编码实现,spring的配置文件可以不动

 // root context
        XmlWebApplicationContext rootContext = new XmlWebApplicationContext();

        rootContext.setConfigLocations(resolveConfigPath("*-context.xml"), resolveConfigPath("*-context-cas.xml"));
        servletContext.addListener(new ContextLoaderListener(rootContext));

        // web dispatcher servlet
        XmlWebApplicationContext web = new XmlWebApplicationContext();
        web.setParent(rootContext);
        web.setConfigLocation(resolveConfigPath("*-servlet.xml"));
        ServletRegistration.Dynamic app = servletContext.addServlet("appServlet", new DispatcherServlet(web));
        app.setLoadOnStartup(1);
        app.addMapping("/");

以上代码,其实就是注册了ContextLoaderListener和DispatcherServlet,和上一点在web.xml中的配置并无两样。

spring配置(全编码)

如果spring的配置文件不想写了,全都采用注解的方式呢?还是使用ServletContainerInitializer编码的方式 。但是不加载配置文件了。

 // root context
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();

        rootContext.register(RootConfig.class);
        servletContext.addListener(new ContextLoaderListener(rootContext));

        // web dispatcher servlet
        AnnotationConfigWebApplicationContext web = new AnnotationConfigWebApplicationContext();
        web.setParent(rootContext);
        rootContext.register(WebConfig.class);
        ServletRegistration.Dynamic app = servletContext.addServlet("appServlet", new DispatcherServlet(web));
        app.setLoadOnStartup(1);
        app.addMapping("/");

RootConfig和WebConfig就对应spring的核心配置xml和mvc配置xml。把xml转成java代码的方式,各种注解套上就可以了。

spring的循环依赖

上边好像有点跑题了啊,写这篇主要是为了说spring循环依赖的问题。
a依赖b,b依赖a。不论是xml配置文件中或者是编码方式。这种方式spring的怎么解决的呢?

上一篇下一篇

猜你喜欢

热点阅读