• listener中获取spring中管理的bean


    看第一个例子:

    自定义一个listener:

    package com.test.common.listener;
    
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    
    import org.springframework.beans.factory.annotation.Autowired;
    
    import com.test.moudules.test.service.MyService;
    
    public class CustomListener implements ServletContextListener {
        
        @Autowired
        MyService myService;
    
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
        }
    
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            System.out.println("*****started*******");
            myService.test();
        }
    
    }

    在web.xml中进行配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
      <display-name>testWeb</display-name>
      <welcome-file-list>
        <welcome-file>index.html</welcome-file>
      </welcome-file-list>
      
       <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-context*.xml</param-value>
        </context-param>
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
         <listener>
            <listener-class>com.test.common.listener.CustomListener</listener-class>
        </listener>
    <!-- springmvc 前端控制器 -->
        <servlet>
            <servlet-name>dispatcherSerlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>dispatcherSerlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>

    MyService(纳入spring管理的普通bean):

    package com.test.moudules.test.service;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class MyService {
    
        public void test() {
            System.out.println("this is test method");
        }
    }

    启动web应用结果:

    java.lang.NullPointerException
        at com.test.common.listener.CustomListener.contextInitialized(CustomListener.java:22)

    分析原因:

    listener(以及filter)是由servlet容器(比如tomcat)来进行管理的,而像MyService这些bean是由spring容器管理的,所以在CustomListener中是识别不了自动注入的注解(@Autowired),也无法获取到spring容器中的MyService这些bean的,所以报空指针异常。

    看第二个例子:

    package com.test.common.listener;
    
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    
    import org.springframework.web.context.support.WebApplicationContextUtils;
    
    import com.test.moudules.test.service.MyService;
    
    public class CustomListener implements ServletContextListener {
    
        MyService myService;
    
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
        }
    
    //servlet容器启动时执行的方法
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            System.out.println("*****started*******");
            myService = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext())
                    .getBean(MyService.class);
            myService.test();
        }
    
    }

    启动web应用结果:

    *****started*******
    this is test method

    分析原因:看结果是执行成功了拿到了MyService的bean,并执行了方法。如何实现呢?我们最终的目标是要拿到spring管理的bean(像MyServlce这些类的实现),通过

    WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext())可以拿到spring容器的applicationContext,进而拿到相关的bean。

    注意:

    配置顺序必须如下:

     <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-context*.xml</param-value>
        </context-param>
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
         <listener>
            <listener-class>com.test.common.listener.CustomListener</listener-class>
        </listener>

    即让spring容器先启动起来,再启动自定义的listener,若顺序反了肯定也拿不到相应的bean,因为spring容器还未启动。

     看第三个例子:

    package com.test.common.listener;
    
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.context.support.SpringBeanAutowiringSupport;
    
    import com.test.moudules.test.service.MyService;
    
    public class AutoWiredBeanListener implements ServletContextListener {
    
        @Autowired
        MyService myService;
    
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
        }
    
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            // TODO Auto-generated method stub
            SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, sce.getServletContext());
            System.out.println("SpringBeanAutowiringSupport");
            myService.test();
    
        }
    
    }
    SpringBeanAutowiringSupport
    this is test method

    看执行结果,通过使用@Autowired注解的方式也可以注入spring管理的bean,此处是使用了

    SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, sce.getServletContext());传入当前对象和servletContext。方法的解释为:

    Process {@code @Autowired} injection for the given target object, based on the current root web application context as stored in the ServletContext.(根据传入的servletContext所关联的webApplicationContext,处理相关的注入,具体原理可跟进代码分析,依赖于AutowiredAnnotationBeanPostProcessor)。

  • 相关阅读:
    vue引用js报错Uncaught SyntaxError: Unexpected token <
    VS Code离线安装扩展方法
    zTree、jsTree排序和简单的js数字字符串混合排序方法
    C# 如何读取匿名类型Anonymous Type的属性
    ajax使用jsonp请求方式
    VS2015 Bad Request解决方法
    C# json对象中包含数组对象时,如何存入数据库
    js 最短代码生成随机数(字符串、id)
    HDU 6395 Sequence 杜教板子题
    hdu GuGuFishtion 6390 数论 欧拉函数
  • 原文地址:https://www.cnblogs.com/silenceshining/p/12466354.html
Copyright © 2020-2023  润新知