如何在Java的Filter中注入Service

一、背景
        建立一个全局拦截器LoginFilter,它继承了Filter,web应用启动的顺序是:listener->filter->servlet,而因为项目应用了spring mvc,所以我们会有一个配置文件(applixationContext.xml),我们在配置spring时会用到spring的listener,它会读取applicationContext.xml里的配置对spring context进行初始化;项目启动时,先初始化listener,因此配置在applicationContext.xml里的bean会被初始化和注入;然后再来就filter的初始化,再接着才到我们的dispathServlet的初始化,因此,当我们需要在filter里注入一个注解的bean时,就会注入失败,因为filter初始化时,注解的bean还没初始化,没法注入。


二、方案
 1、新建ClosableApplicationContextAware类保存applicationContext对象

@Service
public class ClosableApplicationContextAware implements ApplicationContextAware{
 
    private static Logger LOGGER = LoggerFactory.getLogger(ClosableApplicationContextAware.class);
    private static ApplicationContext applicationContextStatic;
 
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        applicationContextStatic = applicationContext;
    }
 
    public ApplicationContext getApplicationContext() {
        return applicationContextStatic;
    }
 
    public static Object getBean(String beanName) {
        return applicationContextStatic.getBean(beanName);
    }
    public static <T>T getBean(Class<T> clazz) {
        return applicationContextStatic.getBean(clazz);
    }
 
}


2、新建ClosableApplication类

1)@PostConstruct:如果想在生成对象时完成某些初始化操作,而偏偏这些初始化操作又依赖于依赖注入,那么就无法在构造函数中实现。为此,可以使用@PostConstruct注解一个方法来完成初始化,@PostConstruct注解的方法将会在依赖注入完成后被自动调用。

Constructor >> @Autowired >> @PostConstruct

2)ConfigurableApplicationContext:此接口结合了所有ApplicationContext需要实现的接口,它在ApplicationContext的基础上增加了一系列配置应用上下文的功能。配置应用上下文和控制应用上下文生命周期的方法在此接口中被封装起来,以免客户端程序直接使用。
3)registerShutdownHook():向JVM注册一个回调函数,用以在JVM关闭时,销毁此应用上下文。

public class ClosableApplication {
 
    @Autowired
    ClosableApplicationContextAware applicationContextAware;
    private static Logger LOGGER = LoggerFactory.getLogger(ClosableApplication.class);
 
    @PostConstruct
    public void init() {
        LOGGER.info("ClosableApplication init");
        ApplicationContext applicationContext = applicationContextAware.getApplicationContext();
        if (applicationContext instanceof ConfigurableApplicationContext) {
            ((ConfigurableApplicationContext)applicationContext).registerShutdownHook();
        }
    }
}

3、在applicationContext.xml中添加

 <bean class="com.dami.ClosableApplication" init-method="init" lazy-init="false"> </bean>
4、LoginFileter类调用

public class LoginFilter implements Filter {
       private UserService userService;
 
 
   @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response, FilterChain filterChain)
                                    throws ServletException, IOException {
        userService = ClosableApplicationContextAware.getBean(UserService.class);
    }
}

注:原文作者测试了四个方案,本文只摘取了成功的方案,如果想了解测试失败了的方案,请点下面的链接去看原文。

本文转载自:https://blog.csdn.net/xiao__jia__jia/article/details/102468865

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值