四种方法Servlet容器使用Spring的Bean对象

今天在做一个需求的时候,需要在Servlet接口中调用一个Spring的Bean对象,因为Servlet和Spring生命周期不同,所被管理的容器不同,因此不能直接通过@Autowire注入

以下三个方案,思路分别是:

  • 在初始化这个Servlet类接口的时候,重写init()方法,允许Servlet扫描Bean对象
  • 在初始化这个Servlet类接口的时候,重写init()方法,指定获取bean:getBean()
  • 在利用配置类在装载Servlet的时候,将bean对象地址作为形参传给Servlet

0.Servlet结构演示

这里做演示用的StringRedisTemplate 本身不是一个SpringBean对象,但是由于项目中有配置将其扫描为了bean,所以这里直接用StringRedisTemplate 来做演示

public class ValidateCodeServlet extends HttpServlet {
//@Autowired
private StringRedisTemplate stringRedisTemplate;

//    public ValidateCodeServlet() {
//    }
//    public ValidateCodeServlet(StringRedisTemplate stringRedisTemplate) {
//        this.stringRedisTemplate = stringRedisTemplate;
//    }


 @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
....}


    @Override
    public void init(ServletConfig config) throws ServletException {
.....
    }

1.允许Servlet扫描Bean对象

@Override
public void init(ServletConfig config) throws ServletException {
    // 父类不初始化会导致getServletContext()空指针异常
    super.init(config);
    // 将当前this 的 Servlet交给Spring托管,因此该Servlet可以用@Autowired
    SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext());
}

1.1SpringBeanAutowiringSupport类

通过这个类的名字,结合注释可以知道,这个类主要的作用是对@Autowired进行增强
看注释中的如下部分,通过@Autowired将Spring的Bean对象解析到当前的Web上下文(Servlet上下文)

1.2processInjectionBasedOnServletContext

Servlet注入Spring的Bean对象,最终的执行方法是processInjection()

1.2.1processInjection()

2.get指定的bean

@Override
public void init(ServletConfig config) throws ServletException {

     ServletContext servletContext = this.getServletContext();
     WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext);
     this.stringRedisTemplate = (StringRedisTemplate) context.getBean("StringRedisTemplate");
     }

如果目标类本身没有直接注入Spring容器而是配置扫描,会报错,所以不推荐这种做法,更推荐方法1

2.1WebApplicationContextUtils工具类

在SpringBeanAutowiringSupport类的注释中有提到
WebApplicationContextUtils类允许基于ServletContext轻松访问Spring根web应用程序上下文。

3.配置类传递bean地址

bean对象本质上也是一个java的对象,只要能获取其地址值,就可以正常使用


这样配置就不需要写inti()了

4.同样的,对于Filter

Filter也是Servlet的产物,他的上下文环境也不同于Spring上下文,同样还是这个需求里面用的是Filter对其进行校验,也需要注入Srping的Bean对象,当然不能直接@Autowired


5.普通类调用bean工具类

 @Component
public class SpringContexUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;

@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
applicationContext = context;
}

//静态加载applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通过反射获取Bean
public static <T> T getBean(Class<T> requiredType){
return getApplicationContext().getBean(requiredType);
}
//通过id名获取bean
public static <T> T getBean(String name){
return (T) getApplicationContext().getBean(name);
}
}

把Servlet或者Filter当普通类,直接用工具类调用即可

需要注意的点

因为项目启动时装载在前,很多修改“装载过程”的地方不能通过热部署来reload,需要重启项目

6.总结

在使用Servlet对象之前,将其需要注入的SpringBean作为形参,在配置类中(即启动时装载)指定SpringBean对象的地址值给Servlet或Filter的形参即可

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Bean 的作用域和生命周期是 Spring 框架中非常重要的两个概念,这里简单介绍一下。 1. Bean 的作用域 在 Spring 中,Bean 的作用域指的是 Bean 实例的创建和销毁的范围。Spring 提供了以下五种作用域: - singleton:单例模式,容器中只有一个 Bean 实例,所有对 Bean 的请求都将返回同一个实例。 - prototype:每次请求都会创建一个新的 Bean 实例。 - request:每个 HTTP 请求都会创建一个新的 Bean 实例。 - session:每个 HTTP Session 都会创建一个新的 Bean 实例。 - global session:基于 Servlet 3.0+ 的环境下,每个全局的 HTTP Session 都会创建一个新的 Bean 实例。 2. Bean 的生命周期 Bean 的生命周期指的是 Bean 实例从创建到销毁的整个过程。Spring 提供了以下七个阶段: - 实例化 Bean:Spring 根据 Bean 的定义创建一个 Bean 的实例。 - 设置 Bean 属性:Spring 将配置文件中的属性设置到 Bean 实例中。 - BeanNameAware:如果 Bean 实现了 BeanNameAware 接口,SpringBean 的 ID 传递给 setBeanName 方法。 - BeanFactoryAware:如果 Bean 实现了 BeanFactoryAware 接口,SpringBeanFactory 实例传递给 setBeanFactory 方法。 - InitializingBean:如果 Bean 实现了 InitializingBean 接口,Spring 将调用 afterPropertiesSet 方法。 - 自定义初始化方法Bean 可以配置自定义的初始化方法。 - DisposableBean:如果 Bean 实现了 DisposableBean 接口,Spring 将调用 destroy 方法。 - 自定义销毁方法Bean 可以配置自定义的销毁方法。 以上就是 Spring Bean 的作用域和生命周期的简单介绍。理解 Bean 的作用域和生命周期对于正确使用 Spring 框架非常重要。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值