本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。
前言
aware 意思是注入的意思。今天我们来看看两个重量级的属性注入类
servlet
- web项目初期就是servlet走天下。那么ServletContext就不得不提了,在web应用中我们熟悉的有Request作用域和Session作用域
request作用域
- 一次请求的生命周期,由客户端创建请求开始到服务端对请求作出响应结束,这就是request的生成周期。
- request的时效性很短,往往都是对单词请求的操作。对请求的参数及响应也都是一次性的
session作用域
- 超出request作用域,session是针对客户端的,一个客户端在一定时间内可以看做是一个session对象。期间可以横跨多个request请求。
- session的使用场景往往都是在用户的登录操作中
ServletContext作用域
- 而对于ServletContext他的作用域就更高了,他是凌驾于服务器之上的。或者说他的生命周期是跟随服务器的,服务器启动是ServletContext开始,服务器关闭是ServletContext关闭。
- 对于ServletContext的使用场景其实我们使用频率还是挺高的。在MVC中我们接口的请求路径就是存储在ServletContext中从而实现数据共享的。因为接口一旦设置好之后在程序运行期间是不会有变动的,在运行期间其它地方需要获取映射信息通过ServletContext正好。如果是使用Session的话就设计客户端保持连接等问题了。
对比
- Request、Session、ServletContext三者都是通过键值对的方式存储属性
- 三者生命周期逐渐扩大
- ServletContext可以通过getInitParameter获取内置在程序中的属性。通过getAttribute获取动态设置的属性。可以通过getResource获取资源文件信息
- ServletContext还有一个临时文件地方存储。通过javax.servlet.context.tempdir上下文属性使用
获取
public interface ZxhtomComponent extends ApplicationContextAware, ServletContextAware
- 然后ZxhtomComponent就可以调用getServletContext来获取ServletContext类进行实际操作了。
spring
- 有的时候我们在程序运行期间需要在普通类中获取Spring中的bean , 这个时候我们就无法通过@Autowire等注解实现属性注入了。而Spring为我们提供了
ApplicationContext可以手动获取指定的bean 。 但是该属性是一个接口如果我们想使用就需要实现ApplicationContextAware这个接口。该接口保证了将ApplicationContext属性注入
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext var1) throws BeansException;
}
- 我们实现这个接口,并在子类中添加ApplicationContext属性
@Component //这里必须加,因为最终通过BeanPostProcessor实现回调的。而该类就是在bean初始化前后拦截的
public class ApplicationContextUtil implements ApplicationContextAware {
public static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextUtil.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return ApplicationContextUtil.applicationContext;
}
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
- 这样一个普通类ApplicationContextUtil就完成了,我们可以在我们的任何地方通过该类的getBean方法获取到Spring中的bean了。
Aware
- 上面我们从servlet和spring两个角度出发实现如何获取对应的上下文类。servlet中是servletContext , spring中的ApplicationContext 。 而他们都是通过Aware结尾类进行属性注入的。
- 换句话来说,他们都继承了org.springframework.beans.factory.Aware 接口。他们分别是ApplicationContextAware,ServletContextAware 。
- Aware的坐拥就是将bean注入到普通类中。从而通过上下文进行相关操作。
其它相关Aware
BeanNameAware
- 获取该bean在容器中的名称
BeanFactoryAware
- 获取当前的BeanFactory
MessageSourceAware
- 获取MessageSource , 国际化相关
ResourceLoaderAware
- 获取ResourceLoader
何处注入
- springboot中函数入口在AbstractApplicationContext#refresh方法中。该方法我们可以知道有一个prepareBeanFactory
- 然后我们进去会发现最红会在invokeAwareInterfaces中对下面的Aware进行属性回调。
欢迎在评论区讨论,掘金官方将在掘力星计划活动结束后,在评论区抽送100份掘金周边,抽奖详情见活动文章