框架的基础知识
1.Javaweb
1. Servlet的运行过程?
Web容器加载Servlet并将其实例化后,Servlet生命周期开始,
容器运行其init()方法进行Servlet的初始化;
请求到达时调用Servlet的service()方法
service()方法会根据需要调用与请求对应的doGet或doPost等方法;
当服务器关闭或项目被卸载时服务器会将Servlet实例销毁,此时会调用Servlet的destroy()方法。
2. 讲解JSP中的四种作用域。
- page代表与一个页面相关的对象和属性。
- request代表与Web客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个Web组件;需要在页面显示的临时数据可以置于此作用域。
- session代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的session中。
- application代表与整个Web应用程序相关的对象和属性,它实质上是跨越整个Web应用程序,包括多个页面、请求和会话的一个全局作用域。
3.Servlet生命周期
1.创建对象->初始化->service()->doXXX()->销毁
2.对象创建只有一次,单例
初始化一次
销毁一次
3.关于线程安全
不安全的三个因素
①多线程的环境(有多个客户端,同时访问Servlet)
②多个线程共享资源,比如一个单例对象(Servlet是单例的)
③这个单例对象是有状态的(比如Servlet方法中采用全局变量,并且以该变量的运算结果作为下一步操作依据)
4.Cookie和Session的区别
1.存储位置不同
Session:服务端
Cookie:客户端
2.存储的数据格式不同
Session:value为对象,Object类型
Cookie:value为字符串,如果我们存储一个对象,对象转J son
3.存储数据的大小
Session:受服务器内存控制
Cookie:一般来说,最大为4K
4.生命周期不同:
Session:服务器端控制,默认30分钟。关闭浏览器不会消失。
Cookie:客户端控制,其实是客户端的一个文件,分2种情况:
①默认会话级Cookie,随浏览器关闭而消失
②比如设置7天免登陆,SetMaxAge
5.Cookie和Session之间的联系
http协议是无状态的协议,为了记住用户的状态,服务器会通过会话级的cookie来保存session标识。
JessionId保存session的id。
5.get 和 post 请求有哪些区别?
- get 请求会被浏览器主动缓存,而 post 不会。
- get 传递参数有大小限制,而 post 没有。
- post 参数传输更安全,get 的参数会明文限制在 url 上,post 不会。
6.转发和重定向的区别
1.转发
发生在服务器内部的跳转,对客户端来说就一次请求,request对象可以传递。
2.重定向
多次请求之间传递数据,需要session对象。
2. Spring
SpringBean的作用域
SpringBean生命周期:
- Spring对bean进行实例化,默认bean是单例;
- Spring对bean进行依赖注入;
- 如果bean实现了BeanNameAware接口,spring将bean的id传给setBeanName()方法;
- 如果bean实现了BeanFactoryAware接口,spring将调用setBeanFactory方法,将BeanFactory实例传进来;
- 如果bean实现了ApplicationContextAware接口,它的setApplicationContext()方法将被调用,将应用上下文的引用传入到bean中;
- 如果bean实现了BeanPostProcessor接口,它的postProcessBeforeInitialization方法将被调用;
- 如果bean实现了InitializingBean接口,spring将调用它的afterPropertiesSet接口方法,类似的如果bean使用了init-method属性声明了初始化方法,该方法也会被调用;
- 如果bean实现了BeanPostProcessor接口,它的postProcessAfterInitialization接口方法将被调用;
- 此时bean已经准备就绪,可以被应用程序使用了,他们将一直驻留在应用上下文中,直到该应用上下文被销毁;
- 若bean实现了DisposableBean接口,spring将调用它的distroy()接口方法。同样的,如果bean使用了destroy-method属性声明了销毁方法,则该方法被调用;
SpringAop核心概念
- 切面:类是对物体特征的抽象,切面就是对横切关注点的抽象
- 横切关注点:对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
- 连接点:被拦截到的点
- 切入点:对连接点进行拦截的定义
- 通知:所谓通知就是指拦截到连接点之后要执行的代码,通知分为前置,后置,异常,最终,环绕五类
- 目标对象:代理的目标对象
- 织入:将切面应用到目标对象并导致代理对象创建的过程
- 引入:在不修改代码的前提下,引入可以在运行期为类动态的添加一些方法或字段
SpringAop动态代理的原理
Spring
的AOP
实现原理其实很简单,就是通过动态代理实现的。如果我们为Spring
的某个bean
配置了切面,那么Spring
在创建这个bean
的时候,实际上创建的是这个bean
的一个代理对象,我们后续对bean
中方法的调用,实际上调用的是代理类重写的代理方法。而Spring
的AOP
使用了两种动态代理,分别是JDK的动态代理,以及CGLib的动态代理。
(一)JDK动态代理
JDK
的动态代理是基于反射实现。JDK
通过反射,生成一个代理类,这个代理类实现了原来那个类的全部接口,并对接口中定义的所有方法进行了代理。当我们通过代理对象执行原来那个类的方法时,代理类底层会通过反射机制,回调我们实现的InvocationHandler
接口的invoke
方法。并且这个代理类是Proxy类的子类。这就是JDK
动态代理大致的实现方式。
优点:
JDK
动态代理是JDK
原生的,不需要任何依赖即可使用;- 通过反射机制生成代理类的速度要比
CGLib
操作字节码生成代理类的速度更快;
缺点:
- 如果要使用
JDK
动态代理,被代理的类必须实现了接口,否则无法代理; JDK
动态代理无法为没有在接口中定义的方法实现代理,假设我们有一个实现了接口的类,我们为它的一个不属于接口中的方法配置了切面,Spring
仍然会使用JDK
的动态代理,但是由于配置了切面的方法不属于接口,为这个方法配置的切面将不会被织入。JDK
动态代理执行代理方法时,需要通过反射机制进行回调,此时方法执行的效率比较低;
(二)CGLib动态代理
CGLib
实现动态代理的原理是,底层采用了ASM
字节码生成框架,直接对需要代理的类的字节码进行操作,生成这个类的一个子类,并重写了类的所有可以重写的方法,在重写的过程中,将我们定义的额外的逻辑(简单理解为Spring
中的切面)织入到方法中,对方法进行了增强。而通过字节码操作生成的代理类,和我们自己编写并编译后的类没有太大区别。
优点:
- 使用
CGLib
代理的类,不需要实现接口,因为CGLib
生成的代理类是直接继承自需要被代理的类; CGLib
生成的代理类是原来那个类的子类,这就意味着这个代理类可以为原来那个类中,所有能够被子类重写的方法进行代理;CGLib
生成的代理类,和我们自己编写并编译的类没有太大区别,对方法的调用和直接调用普通类的方式一致,所以CGLib
执行代理方法的效率要高于JDK
的动态代理;
缺点:
-
由于
CGLib
的代理类使用的是继承,这也就意味着如果需要被代理的类是一个final
类,则无法使用CGLib
代理; -
由于
CGLib
实现代理方法的方式是重写父类的方法,所以无法对final
方法,或者private
方法进行代理,因为子类无法重写这些方法; -
CGLib
生成代理类的方式是通过操作字节码,这种方式生成代理类的速度要比JDK
通过反射生成代理类的速度更慢;
Spring框架中都用到了哪些设计模式?
- 代理模式:在AOP和remoting中被用的比较多。
- 单例模式:在spring配置文件中定义的bean默认为单例模式。
- 模板方法模式:用来解决代码重复的问题。
- 前端控制器模式:Spring提供了DispatcherServlet来对请求进行分发。
- 依赖注入模式:贯穿于BeanFactory / ApplicationContext接口的核心理念。
- 工厂模式:BeanFactory用来创建对象的实例。
你用过哪些重要的 Spring 注解?
@Controller - 用于 Spring MVC 项目中的控制器类。
@Service - 用于服务类。
@RequestMapping - 用于在控制器处理程序方法中配置 URI 映射。
@ResponseBody - 用于发送 Object 作为响应,通常用于发送 XML 或 JSON 数据作为响应。
@PathVariable - 用于将动态值从 URI 映射到处理程序方法参数。
@Autowired - 用于在 spring bean 中自动装配依赖项。
@Qualifier - 使用 @Autowired 注解,以避免在存在多个 bean 类型实例时出现混淆。
@Scope - 用于配置 spring bean 的范围。
@Configuration,@ComponentScan 和 @Bean - 用于基于 java 的配置。
@Aspect,@Before,@After,@Around,@Pointcut - 用于切面编程(AOP)。
@Component, @Controller, @Repository, @Service有何区别?
- @Component:这将 java 类标记为 bean。它是任何 Spring 管理组件的通用构造型。spring
的组件扫描机制现在可以将其拾取并将其拉入应用程序环境中。 - @Controller:这将一个类标记为 Spring Web MVC 控制器。标有它的 Bean 会自动导入到 IoC 容器中。
- @Service:此注解是组件注解的特化。它不会对 @Component 注解提供任何其他行为。您可以在服务层类中使用
- @Service 而不是 @Component,因为它以更好的方式指定了意图。
- @Repository:这个注解是具有类似用途和功能的 @Component 注解的特化。它为 DAO 提供了额外的好处。它将 DAO导入 IoC 容器,并使未经检查的异常有资格转换为 Spring DataAccessException。
有哪些不同类型的依赖注入实现方式?
依赖注入是时下最流行的IoC实现方式,依赖注入分为
- 接口注入
- Setter方法注入
- 构造器注入
其中接口注入由于在灵活性和易用性比较差,现在从Spring4开始已被废弃。
构造器依赖注入:构造器依赖注入通过容器触发一个类的构造器来