本文主要是介绍spring experience,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
- spring ioc 容器,举例来说,一个类,使用了socket 接口,如果有对应两个实现类,那么我在使用socket 的时候,如果想变更,那么就得重新写代码。但是比如使用了xml 的ioc 模式,就可以直接进行配置,不需要在代码中new。这样就做到了解耦。
spring 的思路
Spring是bean的容器,那么到底bean是什么,容器又在哪里。
spring bean 的生命周期
扫描bean,得到beanDefinition,
仔仔细细的介绍,有空看吧:面试官:请你说一下 Bean 的生命周期 - 知乎
Spring 的 bean 和 java 对象的区别
传统java bean 有一些规范
1. 必须要有无参构造方法
2. 所有属性是private
3. 通过get set 方法获取 设置
4. 可序列化
用处不同:java bean 作为传值的参数;spring 中的任何组件都可以作为bean
写法不同,如上
生命周期不同:SpringBean是受Spring管理的对象 所有能受Spring容器管理的对象都可以成为SpringBean。java bean生命周期由使用者决定、spring 的由spring 决定
一、切面的使用
切面作用:权限管理,事务管理,日志记录
1. 通知(Advice)
切面必须要完成的工作即称为通知。通知定义了切面是什么以及什么时候实用。
- 前置通知(Before):在目标方法被调用之前调用通知功能;
- 后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么;
- 返回通知(After-returning):在目标方法成功执行之后调用通知;
- 异常通知(After-throwing):在目标方法抛出异常后调用通知;
- 环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。
2. 连接点(Join Point)
我们的应用可能有数以千计的时机应用通知。这些时机被称为连接点。
3. 切点(Poincut)
切点的定义会匹配通知所要织入的一个或多个连接点。通常使用明确的类和方法名称,或是利用正则表达式定义所匹配的类和方法名称来指定这些切点。
就是实际要执行切面的那个的“连接点”。
4. 切面(Aspect)
切面是通知和切点的结合。通知和切点共同定义了切面的全部内容----它是什么,在何时和何处完成其功能。
5. 引入(Introduction)(一个动作)
引入允许我们向现有的类添加新方法或属性。
6. 织入(Weaving)(一个动作)
织入是把切面应用到目标对象并创建新的代理对象的过程。
使用“织入”这个词的语境:切面在指定的连接点被织入到目标对象中。
- 编译期:切面在目标类编译时被织入。这种方式需要特殊的编译器。AspectJ的织入编译器就是以这种方式织入切面的。
- 类加载期:切面在目标类加载到JVM时被织入。这种方式需要特殊的类加载器(ClassLoader),它可以在目标类被引入应用之前增强该目标类的字节码。AspectJ 5的加载时织入(load-timeweaving,LTW)就支持以这种方式织入切面。
- 运行期:切面在应用运行的某个时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态地创建一个代理对象。Spring AOP就是以这种方式织入切面的。
二、Spring对切面的支持
Spring提供了4种类型的AOP支持:
- 基于代理的经典Spring AOP;
- 纯POJO切面;
- @AspectJ注解驱动的切面;
- 注入式AspectJ切面(适用于Spring各版本)。
前三种都是Spring AOP实现的变体,Spring AOP构建在动态代理基础之上,因此,Spring对AOP的支持局限于方法拦截。
三、切点
通过类定义切点
execution(* com.xgj.aop.spring.advisor.aspectJ.function.execution.classpoint.Cleaner.*(..))
匹配Cleaner接口的所有方法(包括实现类中覆写的方法), 第一个 * 代表返回任意类型 ,Cleaner.*代表Cleaner接口中的所有方法,看后面是有个括号,括号里面是参数
execution(* com.xgj.aop.spring.advisor.aspectJ.function.execution.classpoint.Cleaner.*(..))
匹配Cleaner接口及其所有实现类的方法,不但匹配实现类中覆写的方法,也包括实现类中不在接口中定义的方法
通过类包定义切点
在类名模式串中,.*表示包下的所有类,..*表示包、子孙包下的所有类
execution(* com.xgj.*(..))匹配com.xgj包下所有类的所有方法
execution(* com.xgj..*(..))匹配com.xgj包、子孙包下所有类的所有方法.比如 com.xgj.dao ,com.xgj.service,com.xgj.dao.user包下所有类的所有方法都匹配。 当 ..出现在类名中时,必须后面跟*表示子孙包下的所有类。
execution(* com..*Dao.find*(..))匹配包名前缀为com的任何包下类名后缀为Dao的方法,方法名必须以find为前缀, 比如com.xgj.UserDao#findUserById()方法都是匹配切点。
四、@Pointcut 声明切点
@Pointcut("execution(* com.wtj.springlearn.aop.Performance.perform(..))")public void per(){};//表演前 手机静音@Before("per()")public void silenceCellPhone(){System.out.println("silence Cell Phone");}
参考:https://juejin.cn/post/6844903897006342151
spring 事务两种,编程式,声明式。
@Transactional 会对此bean 生成一个代理对象,作为bean,放入ioc 容器中。将自动提交设置为false,没异常,则提交。
可以配置哪些异常才回滚。默认runtimeexception/error
db & spring 以spring 为准
spring 配置了db 不支持的,以db 为准
spring 事务的传播机制
一共有七种,3-3-1
1. required,默认。有,加入;没有,创建
2. support 有,加入;没有,不用
3. mandatory 有,加入;没有,报错(这个是抛异常的)
4. required_new 有,挂起,新建一个,各自回滚各自的;
5. not support 有,挂起;b 以非事务方式运行
6. never 如a 存在,抛异常(这个也是如果不符合规则,抛异常)
7l. nested 有,则嵌套其中执行(a 是父事务,b 是子事务);没有,同required 一样
父回,子必回;子回,父不一定回(可catch)
spring 事务管理:可能是最漂亮的Spring事务管理详解_不忘初心-CSDN博客_spring 事务详解
事务的属性 包含5 个方面
1. 隔离机制(读未提交、度已提交、可重复度、串行化)
2. 传播机制
3. 回滚规则
4. 事务超时
5. 是否只读
事务分为读写事务、只读事务
而这两种都是事务,对于“只读事务”,有它的作用,有它的不同。
作用:如果你一次执行多条查询语句,例如统计查询,报表查询,在这种场景下,多条查询SQL必须保证整体的读一致性,否则,在前条SQL查询之后,后条SQL查询之前,数据被其他用户改变,则该次整体的统计查询将会出现读数据不一致的状态,此时,应该启用事务支持。而比如说只有一条语句进行读,那么此时没有必要设置只读事务。
不同:它只是一个“暗示”,提示数据库驱动程序和数据库系统,这个事务并不包含更改数据的操作,那么JDBC驱动程序和数据库就有可能根据这种情况对该事务进行一些特定的优化。
但是,如果要在这个事务里面进行insert 或者update 也是可以的,只不过对于数据一致性的保护不像“读写事务”那样保险而已。因此,“只读事务”仅仅是一个性能优化的推荐配置而已,并非强制你要这样做不可
如果某些场景没有设置事务,那么可能造成“不可重复读”的问题。
再次仔细理解:这个设置@Transaction(readOnly = true) 的事情,正常默认readOnly = false,如果设置为true,那么就是把这个事务标识为“只读”。仅仅是标识一下,它还是个事务,本身就是个事务,不论你在这里面进行读还是写,还是只有写,也不论你标没标,它就是个事务。标识为只读事务,仅仅是为了“优化”,通知数据库驱动程序和数据库系统。降低开销。
事实上readOnly 和spring没有任何关系,spring事务仅仅是一层封装,最后都要调用底层驱动的setReadonly方法来开启。所以readOnly 是否能到来优化还是要看 数据库类型和驱动类型
;所以readonly语义不是所有的数据库驱动都支持的
有说只读事务里是不允许修改数据的,有说能修改单 ,我觉得应该不能修改。
参考:Spring事务管理 —— readOnly只读事务-云海天教程
platformTransactionManager
spring 事务失效(本质是aop 不生效)
1. 自调用
2. 方法不是public
3. db 不支持事务
4. 没有被spring 管理
5. 异常被吃掉
6. 异常类型不对
Servlet Tomcat Spring
关于servlet 的不同版本定义:
- servlet就是一个接口
- Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。
servlet 不会直接处理客户端的http 请求,servlet并不会去监听8080端口;直接与客户端打交道是“容器”,比如常用的tomcat。
客户端的请求直接打到tomcat,它监听端口,请求过来后,根据url等信息,确定要将请求交给哪个servlet去处理,然后调用那个servlet的service方法,service方法返回一个response对象,tomcat再把这个response返回给客户端。
servlet 接口的五个方法:
- init(ServletConfig)
- getServletConfig()
- service(ServletRequest, ServletResponse)
- getServletInfo()
- destroy()
上文来自:(写的不太清晰,如果有时间可以看看)Servlet/Tomcat/ Spring 之间的关系 - shawshawwan - 博客园
一个资源如果无法映射到URL,那就无法被外界访问。web 服务器就是用来将主机上的资源映射成外部可访问的URL。
本质上也是一种应用程序,通常运行于实体服务器之上,绑定服务器的IP 地址并监听某一个Tcp 端口来接收并处理Http 请求。
关于servlet、tomcat、spring 的关系
这个说的简单,可以看看:【每日一篇】Servlet/tomcat/spring mvc之间关系_aaaawwwwssssdsaw的博客-CSDN博客
java web 三大组件
- servlet
- filter
- listener
各种类型服务器的区别:Web服务器、HTTP服务器及应用服务器的区别?_zhangpower1993的博客-CSDN博客
(回去看看那本书,入门的那个,当要使用Servlet完成的复杂的功能时,需要编写多个Servlet类,并且在web.xml进行注册)
spring filter 和intercepter 的区别
(spring 过滤器、拦截器)
AOP 不是技术,而是一种思想
多态就是同一个接口,使用不同的实例而执行不同操作。如打印机接口,有黑白 & 彩色打印机的实现,打印效果分别为黑白 & 彩色。
过滤器和拦截器都是面向切面编程的一个具体实现。
区别:
- Filter是依赖于Servlet容器,属于Servlet规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用。
- Filter的执行由Servlet容器回调完成,而拦截器通常通过动态代理的方式来执行。
- Filter的生命周期由Servlet容器管理,而拦截器则可以通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。
HttpRequest-->Filter-->Servlet-->Controller/Service-->Filter--->HttpResponse
filter 可以对request、response 做修改
filter 也是一个接口,实现了该接口并进行相应配置,就可以使Filter生效,进而实现:对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后再对服务器响应进行后处理。Filter的底层原理是基于函数回调的,这里用到了责任链模式。
Filter 和Servlet 一样,创建和销毁由Web 服务器负责。
每个请求都会创建一个FilterChain对象,所以不用担心会有线程安全问题。
web 应用程序启动时,服务器会根据程序的web.xml 文件中的配置信息调用init 方法来初始化filter。当服务关闭时,调用destroy 方法销毁。
在一个应用程序中一个Filter只会被创建和销毁一次,在进行完初始化之后,Filter中声明了public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
方法,用来实现一些需要在拦截完成之后的业务逻辑。
注意到上面的doFilter()
方法的参数中,有chain
这个参数,它是传递过来的拦截链对象,里面包含了用户定义的一系列的拦截器,这些拦截器根据其在web.xml中定义的顺序依次被执行。当用户的信息验证通过或者当前拦截器不起作用时,我们可以执行chain.doFilter()
方法来跳过当前拦截器来执行拦截器链中的下一个拦截器。
beanDefinition
BeanDefinitionRegistryPostProcessor--- Spring源码从入门到精通(二十八) - 知乎
Spring MVC中的HandlerInterceptor等。相比于Filter,框架中的Interceptor的产生作用的时间和位置不一样,下面描述了应用了Spring MVC中的HandlerInterceptor的web请求流程:
HttpRequest ----> DispactherServlet ----> HandlerInterceptor ---->Controller----> HandlerInterceptor ----> HttpResponse
两者的主要区别在于Filter起作用的时机是在请求到达Servlet之前,二HandlerInterceptor其作用的时机是在DispactherServlet接收到用户请求完成请求到相应的Handler映射之后。虽然都先于在具体的业务逻辑执行,但是还是存在一些差异。Filter面对的是所有的请求,而HandlerInterceptor是面对具体的Controller。Filter总是先于HandlerInterceptor发挥作用,在Filter中甚至可以中断请求,从而使它无法到达相应的Servlet。而且两者的配置也不一样,Filter是在web.xml中进行配置,HandlerInterceptor是在具体的applicationContext.xml中进行配置。
二者区别参考:Servlet Filter & Spring MVC Interceptor - 知乎
Filter 中三个方法,init、doFilter、destroy
Interceptor 中三个方法,preHandle、postHandle、afterCompletion。preHandle是请求执行前执行的,postHandler是请求结束执行的,但只有preHandle方法返回true的时候才会执行,afterCompletion是视图渲染完成后才执行,同样需要preHandle返回true,该方法通常用于清理资源等工作。
新手能看懂的(Interceptor)和(Filter)区别与使用! - 知乎
Listener
监听器是一个专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生情况时,立即采取相应的行动。
参考:Java Web三大组件-Zhuoli's Blog
一个讲概念的,监听器、过滤器、拦截器
spring项目--过滤器,拦截器,监听器_weisian的博客-CSDN博客_spring过滤器拦截器
Spring MVC
- spring mvc 的执行流程
- 用户向服务器发送请求,请求被 springMVC 前端控制器 DispatchServlet 捕获;
- 前端控制器请求处理器映射器:查询能够处理该请求的Controller
- 将找到的Controller路径返回给前端控制器.
- 前端控制器请求处理器适配器: 找到能够处理该请求的处理器。
- 处理器执行请求代码。(controller-service-dao)
- 将处理后的结果和响应页面封装到ModelAndView对象中,返回给处理器适配器。
- 将ModelAndView对象返回给前端控制器.
- 前端控制器请求视图解析器: 解析View对象,确定是哪个页面。
- 视图解析器内部拼接,将页面名称拼接成真实的页面路径,返回给前端控制器。(拼接前缀和后缀:View=hello -->(/WEB-INF/hello.jsp))
- 视图渲染(将数据填充到页面中(request域中)),最后将完整的view展示给用户。
spring mvc 常见问题:
精心整理的 SpringMVC常见面试题 - 知乎
Spring MVC面试题(2020最新版)_ThinkWon的博客-CSDN博客_springmvc面试题
dispatcherServlet:Spring MVC DispatcherServlet详解 - 知乎
spring 连续问题:BeanDefinitionRegistryPostProcessor--- Spring源码从入门到精通(二十八) - 知乎
ApplicationListener 的使用(简单介绍:ApplicationListener--- Spring源码从入门到精通(二十九) - 知乎)
用来监听容器中发布的事件(ApplicationEvent)。
只要容器中有相关事件发布,就能监听到:A、ContextRefreshedEvent容器刷新完成,所有bean都完全创建,会发布这个事件。B、ContextClosedEvent关闭容器会发布这个事件。(spring事件)
原理:使用的观察者模式,参考链接:ApplicationListener原理分析 - Griez - 博客园
InitializingBean 的使用
类实现了InitializingBean,实现其中的afterPropertiesSet 方法。
参考:揭秘Spring(四)之InitializingBean - 知乎
50 道题
50 道 经典 Spring 面试题
spring
- 缺点:
- 缺少一个公用控制器
- 没有spring boot 好用
- 把框架粘合在一起,拆分就不好搞了
- ioc 控制反转,实现有两种,依赖注入(DI) & 依赖查找(用得少)
DI 如何实现的:DI 是让对象被动地接受依赖类,而不用自己去容器中主动查找它依赖的类。容器实例化对象时,主动将它依赖的对象注入给它。
- IOC 优点
松耦合、代码量降低。
ICO 容器支持加载服务时的饿汉式初始化和懒加载
- IOC 容器初始化过程
基于xml 的容器初始化,当创建一个ClassPathXmlApplicationContext 时,构造方法做了两件事:
(1)调用父容器的构造方法为容器设置Bean 资源加载器
(2)
- spring 提供的功能
- 控制反转
- mvc 框架
- 事务管理(本地事务、全局事务JTA)
- 异常处理(转换为一致的unchecked 异常)
- spring 缺少一个公共控制器?
以下:IOC 的实现、IOC 优点、IOC 初始化过程、DI 的实现、DI 的注解、DI 的过程
- ioc 容器两种实现
依赖注入、依赖查找 - ioc 优点,解耦
支持加载服务时的饿汉式初始化 和 懒加载 - ioc 容器初始化过程
- 依赖注入的实现方法
- 构造方法注入
- 优点:对象构造完成后可以马上处于就绪状态
- 缺点:依赖对象多,构造函数长;非必须的依赖要引入多个构造方法
- setter 方法注入
- 可以被继承,允许设置默认值
- 无法在对象构造完成后,马上进入就绪状态
- 接口注入(有那些接口 beanPostProcessor、aware)
必须实现某个接口,接口提供方法为其注入依赖对象
(要求被注入的对象实现不必要的接口,侵入性强)
- spring ioc 的实现机制:
原理是使用工厂模式 加 反射机制interface Fruit {public abstract void eat();}class Apple implements Fruit {public void eat(){System.out.println("Apple");} }class Orange implements Fruit {public void eat(){System.out.println("Orange");} }class Factory {public static Fruit getInstance(String ClassName) {Fruit f=null;try {f=(Fruit)Class.forName(ClassName).newInstance();} catch (Exception e) {e.printStackTrace();}return f;} }class Client {public static void main(String[] a) {Fruit f=Factory.getInstance("io.github.dunwu.spring.Apple");if(f!=null){f.eat();}} }
- 构造方法注入
- 依赖注入相关注解(使用方法、原理)
@Autowire
@Qualifier - 依赖注入的过程
bean 相关
-
Bean 的生命周期
-
Bean 的作用范围
使用:@Scope(value = "prototype")-
singleton 单例,不论收到多少次Bean 请求,每个容器中只有一个Bean 实例
-
prototype 原型模式,每次Bean 请求都创建一个新的实例
-
request 每次http 请求创建一个,并放到request 域中
-
session 每个session 中有一个bean 实例,session 过期,bean 失效
-
global session:当应⽤部署在 Portlet 容器时,如果想让所有 Portlet 共⽤全局存储变量,那么该变量需要存储在 global session 中
-
-
xml 方式创建Bean
-
默认无参构造方法,需要指明bean 标签中的id 和class 属性,如果没有无参构造方法,报错
-
工厂方法
-
静态工厂方法
通过bean 标签中的class 属性指明静态工厂
factory-method 指明静态工厂方法 -
实例工厂方法
通过 bean 标签中的 factory-bean 属性指明实例工厂
factory-method 属性指明实例工厂方法
-
-
-
spring 配置到应用开发中的方式(怎么配)
-
基于xml
-
基于注解
-
基于java
-
-
基于xml 配置方式配置Spring
基于xml 配置的目的是使所有spring 组件都可以用xml 文件的形式来配置
意味着不会出现spring 配置类型(比如说声明、java)
基于xml 配置方式:是使用被spring 命名空间所支持的一系列xml 标签来实现的
主要有以下主要的命名空间:context、beans、jdbc、tx、aop、mvc 等
-
如何通过注解来创建bean
把当前类置入spring 容器中,相当于在xml 中配置一个bean 标签。value 属性指定bean 的id,默认使用当前类首字母小写的类名
@Component 通用组件、@Controller、@Service、@Repository 三个都是衍生注解,作用及属性都是一致的,只是提供了不同的语义
-
-
如何通过注解配置文件
-
BeanFactory、FactoryBean、ApplicationContext 的区别
BeanFactory 是一个Bean 工厂,使用简单工厂模式,是Spring IOC 容器顶级接口,可以理解为含有Bean 集合的工厂类
BeanFactory 实例化后并不会自动实例化Bean,只有当Bean 被使用时才实例化与装配依赖关系,属于延迟加载
里面包含了各种bean 的定义,读取bean 的配置文档,管理bean 的加载、实例化,控制bean 的生命周期,维护bean 的依赖关系
FactoryBean 是一个工厂Bean,使用了工厂方法模式,如果⼀个 Bean 实现了这个接口,那么它就是创建对象的工厂 Bean,而不是 Bean 实例本身
ApplicationConext 是 BeanFactory 的子接口,扩展了 BeanFactory 的功能,提供了支持国际化的⽂本消息,统⼀的资源⽂件读取方式,事件传播以及应⽤层的特别配置等。容器会在初始化时对配置的Bean 进行预实例化,Bean 的依赖注入在容器初始化时就已经完成,属于立即加载,适合单例模式,⼀般推荐使用。
-
Bean 的生命周期
BeanNameAware 接口
BeanFactoryAware 接口
BeanPostProcessors
InitializingBean
BeanPostProcessor
DisposableBean
-
-
spring 支持的orm
-
spring 框架中单例Bean 线程安全吗
不安全
大部分Bean 是“无状态的”
如果想要控制“线程安全”,则需要自己实现
-
用到了哪些设计模式
-
工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;
- 单例模式:Bean默认为单例模式。
- 代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;
- 模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
- 观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现–ApplicationListener。
-
-
@Autowire 的使用场景
-
spring 中有哪些不同类型的事件
Spring 提供了以下5种标准的事件:
- 上下文更新事件(ContextRefreshedEvent):在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。
- 上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
- 上下文停止事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
- 上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
- 请求处理事件(RequestHandledEvent):在Web应用中,当一个http请求(request)结束触发该事件。如果一个bean实现了ApplicationListener接口,当一个ApplicationEvent 被发布以后,bean会自动被通知。
这个主要看看问题,内容简略看看:https://blog.csdn.net/mengchuan6666/article/details/119572744
这个比上面那个好:https://zhuanlan.zhihu.com/p/369115360
spring ioc 实现原理
Spring IoC实现原理(附思维导图) - 简书
tcp 为什么三次握手:TCP协议为什么需要三次握手?_Nicky's blog-CSDN博客
lru:【图解数据结构与算法】LRU缓存淘汰算法面试时到底该怎么写_JavaEdge全是干货的技术号-CSDN博客
垃圾回收:java中垃圾回收机制中的引用计数法和可达性分析法(最详细) - igoodful - 博客园
浅析JAVA的垃圾回收机制(GC) - 简书
如何设计秒杀系统:
阿里面试官问我:如何设计秒杀系统?我给出接近满分的回答_敖丙-CSDN博客
分布式事务 等等:字节跳动面试官这样问消息队列:分布式事务、重复消费、顺序消费,我整理了一下_敖丙-CSDN博客
这篇关于spring experience的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!