学习记录
前言
暑期实习,不会的零散知识一大堆,每次遇到了,搞清楚之后就把要点截个图配点文字丢到有道云笔记里,然后再也不看,下次遇到接着不会。想了想以后干脆直接丢到这里,查阅更方便,并且由于知识点很碎,在这里记录也更舒服。
不过也不是每天都有闲工夫学习记录,业务上要处理的东西也不少,争取提高更新频率吧
ThreadLocal和Synchronized
二者都是为了解决多线程中相同变量的访问造成的冲突问题。都起到了隔离线程的作用,只有在当前的线程内才能取到对应的值。
- synchronized是用时间换空间,暂停线程
- ThreadLocal用空间换时间,每个线程单独一份存储空间。
ThreadLocal有一个静态内部类ThreadLocalMap,每个thread对应数组的一个下表,对应的value就存储的该线程的该变量的信息
@ComponentScan
自动扫描组件。会默认扫描该类所在包的所有配置类,其作用相当于配置文件中的 <context:component-scan>,也可以指定value来扫描需要的包
查看组件是否注册进容器
这样可以得到所有注册到组件中的beanname
FilterRegistrationBean
是SpringBoot的过滤器。
注册自定义的过滤器并且设置一些拦截方法.
Filter接口
三大组件之一。
如果注册了filter,则请求不会直接到servlet程序,而是调用Filter的doFilter,再有这个doFilter来决定是否激活激活servlet,或者对请求和响应消息进行更改。
doFilter不会直接调用servlet的service方法,而是调用FilterChain.doFilter 方法来激活目标 Servlet 的 service 方法,FilterChain 对象时通过 Filter.doFilter 方法的参数传递进来的
Filter天生有三个方法。
普通情况下是在xml中配置 < filter-mapping > 注解的方式是在filter接口的实现类为返回类型的方法上加@Bean【有待操作和验证】
init
根据配置创建实例对象,保存在内存。filter实例被创建后,会立刻调用init,这个方法在整个生命周期中只执行一次,会传递一个包含了filter配置以及运行环境信息的FilterConfig对象。
doFilter
如上所属,参数request和response是Web容器传过来的,或者是FilterChain中的上一个filter传来的,还有个参数就是filterchain,因为要调用他的doFilter方法
destroy
仅执行一次,做一些如关闭数据库连接和IO流等操作
FilterChain接口
多个过滤器会组成过滤器链,拦截顺序与配置顺序一致,上一个 Filter.doFilter 方法中调用 FilterChain.doFilter 方法将激活下一个 Filter的doFilter 方法,最后一个 Filter.doFilter 方法中调用的 FilterChain.doFilter 方法将激活目标 Servlet的service 方法。
FilterConfig接口
ServletContext的情况和Filter的配置信息都封装到这个接口中。接口里面的一些方法:
- getFilterName 方法,返回 元素的设置值,或者就是@Bean对应的filter的方法名
- getServletContext 方法,返回 FilterConfig 对象中所包装的 ServletContext 对象的引用。
- getInitParameter 方法,用于返回在 web.xml 文件中为 Filter 所设置的某个名称的初始化的参数值。
ServletContextInitializer
组织结构
SpringBoot用来提供注册Bean的一个接口,解答了上面的疑惑,在springboot中配置filter和listener之类就可以省略配置文件,直接用@Bean注解。结构如下:
和之前的代码就对上了。
TomcatStarter
TomcatStarter是Spring Boot Web Servlet应用结合Tomcat使用时的一个ServletContainerInitializer实现。ServletContextInitializer的实例化对象会被设置到ServletContainerInitializer TomcatStarter上,而TomcatStarter在Servlet容器启动过程中调用自己的方法 onStartup,会逐一调用这些ServletContextInitializer的方法 onStartup初始化ServletContext。
以下是Tomcat starter的代码:
简而言之,就是TomcatStarter里面的onStartup,会传入ServletContext为参数,然后逐个调用ServletContextInitializer里的onStartup,同时传入ServletContext,来完成组件在容器里的初始化
函数式接口
定义
指的是有且仅有一个抽象方法的接口,但是可以有多个非抽象方法。可以隐式的写为lambda表达式
jdk8中有几个常用的继承于function的接口。
谓词接口 Predicate
**接受一个T,返回boolean。**作用是判断一个或多个条件,满足就为true,不满足为false。
其中有一个抽象方法,test,需要我们实现,还有一堆与或非的逻辑。negate是取反。
stream的filter使用的就是这个
DoublePredicate接口 DoublePredicate IntPredicate LongPredicate与Predicate没有继承关系
单元操作接口
单元操作接口有UnaryOperator LongUnaryOperator IntUnaryOperator DoubleUnaryOperator
UnaryOperator 接收一个T类型,返回一个T类型
stream里的map默认使用的就是这个方法.
compose方法是在上个操作之前,andThen是在上个操作之后。例子:
二元操作接口
有BinaryOperator LongBinaryOperator IntBinaryOperator DoubleOperator。
与一元的类似,两个操作符。
可以用在reduce的聚合相加上。实例:
【注:stream.of是创建一个流】
单元函数接口Function
接收一个T类型的参数,返回一个R类型对象。和单元操作接口一样,唯一的区别是单元函数关心函数的返回值,可以将T->R【类型的转换】
实际上UnaryOperator extends Function,所以其实Function势必单元操作更通用的
二元函数接口Bifunction
同上,是二元单元接口的父类,例子:
消费者接口 Consumer
同样也有二元消费者 BiConsumer
接受T,返回void,accept,吃进去就没了
工厂接口
与消费者相对,什么都不要,得到T,supply
方法引用
通过方法的名字来指向一个方法,使用两个冒号,都可以替换成lambda表达式的形式。
Lambda的实质是简化了匿名内部类的书写,而方法引用实质是用另一个方法来省去写匿名内部类的方法体,有点胶水的感觉。