100-Spring学习笔记-面试题

一、基本概念

1Spring优点

1.1、轻量级、非入侵式:对现有的类结构没有影响

1.2、可以提供众多服务,如事务管理,WS

1.3、对主流的框架提供了很多的集成支持,如hibernateStruts2,像一个胶水一样,把一些好的框架粘合在一起方便实用。

1.4、使用SpringIOC容器,将对象之间的依赖关系交给Spring,降低组件之间的耦合性,让我们更专注于应用逻辑

1.5Spring DI 机制降低了业务对象替换的复杂性

1.6Spring的高度可开放性,并不强制依赖于Spring,开发者可以自由选择Spring部分或全部

2Spring缺点

2.1、没有SpringBoot好用

 

二、Spring

1ApplicationContext

1.1FileSystemXmlApplicationContext

1.2ClassPathXmlApplicationContext

1.3WebXmlApplicationContext

 

三、SpringMVC

1、执行流程

1.1、用户发送请求至前端控制器DispatcherServlet

1.2DispatcherServlet收到请求调用HandlerMapping处理器映射器。

1.3、处理器映射器根据请求url找到具体的处理器,生成处理对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet

1.4DispatcherServlet通过HandlerAdapter处理器适配器调用处理器

1.5、执行处理器(Controller,也叫后端控制器)

1.6Controller执行完成返回ModelAndView

1.7HandlerAdaptercontroller执行结果ModelAndView返回给DispaServlet

1.8DispatcherServletModelAndView传给ViewReslover视图解析器

1.9ViewReslover解析后返回具体View

1.10DispatcherServletView进行渲染视图(即将模型数据填充视图中)

1.11DispatcherServlet响应用户

 

2、常用注解

2.1@Controller 用于定义控制器类

2.2@ResponseBody 表示方法的返回结果直接写入HTTP response body

2.3@PathVariable 获取路径参数

2.4@RequestParam 用在方法的参数前面

2.5@RequestBody 返回JSON格式

2.6@RestController @Controller@ResponseBody的合集

2.7@RequestMapping 提供理由信息,负责URLController中的具体函数

2.8@ControllerAdvice 统一处理异常

 

3servlet生命周期

3.1、加载和实例化

3.2、初始化

3.3、请求处理

3.4、服务终止

 

四、AOP

1、基本概念

1.1、核心业务功能和切面功能分别独立进行开发,然后把切面功能和核心业务功能编织在一起,这就叫AOP

1.2、让关注点代码与业务代码分离

1.3、面向切面编程就是指:对很多功能都有的重复代码抽取,再运行的时候往业务方法上动态注入切面类代码

1.4、应用场景:日志、事务管理、权限控制

2、实现原理

2.1jdk动态代理

2.1.1、主要通过Proxy.newProxyInstance()InvocationHandler这两个类和方法实现

2.1.2、实现过程

、创建代理类proxy实现Invocation接口,重写invoke()方法:调用被代理类方法时默认调用此方法

、将被代理类作为构造函数的参数传入代理类proxy

、调用Proxy.newProxyInsatnce(classloader,interfaces,handler)方法生成代理类。

1、生成的代理类 》

1.1$Proxy0 extends Proxy implements Person

1.2、类型为 $Proxy0

1.3、因为已经继承了Proxy,所以java动态代理只能对接口进行代理

2、代理对象会实现用户提供的这组接口,因此可以将这个代理对象强制类型转化为这组接口中的任意一个

3、通过发射生成对象

、总结:代理类调用自已方法时,通过自身持有的中介类对象调用中介类对象的invoke方法,从而达到代理执行被代理对象的方法。

2.2cglib

2.2.1、生成对象类型为Enhancer

2.2.2、实现原理类似于 jdk 动态代理,只是他在运行期间生成的代理对象是针对目标类扩展的子类

2.3、静态代理

2.3.1、缺点

、如果要代理一个接口的多个实现的话需要定义不同的代理类

、代理类和被代理类必须实现同样的接口,万一接口有变动,代理,被代理类 都得修改。

2.3.2、在编译的时候就直接生成代理类

2.4JDK动态代理和cglib的对比

2.4.1CGLib所创建的动态代理对象在实际运行时候的性能要比JDK动态代理高

1.61.7的时候,CGLib更快

1.8的时候,jdk更快

2.4.2CGLib在创建对象的时候所花费的时间却比JDK动态代理多

2.4.3singleton的代理对象或者具有实例池的代理,因为无需频繁的创建代理对象,所以比较适合采用CGLib动态代理,反之,则适合用JDK动态代理

2.4.4JDK动态代理是面向接口的,CGLib动态代理是通过字节码底层继承代理类实现(如果被代理类被final关键字所修饰,那么会失败)

2.4.5JDK生成的代理类类型是Proxy(因为继承的是Proxy)CGLIB生成的代理类类型是Enhancer类型

2.4.6、如果要被代理的对象是个实现类,那么Spring会使用JDK动态代理来完成操作(Spring默认采用JDK动态实现机制)

如果要被代理的对象不是个实现类,那么Spring会强制使用CGLib来实现动态代理

3、配置方式

3.1XML方式

3.2、注解方式

3.3、基于Java类配置

通过 @Configuration @Bean 这两个注解实现的

1@Configuration作用于类上,相当于一个xml配置文件

2@Bean作用于方法上,相当于xml配置中的<bean>

 

五、IOC

1、依赖注入

1.1、装配方式(依赖注入的具体行为)

1.1.1、基于注解的自动装配

、实现方式

@Autowired byName 优先byType

注解

@Resource 优先byName byType

自动扫描(component-scan

1.1.2、基于XML配置的显示装配

1.1.3、基于Java配置的显示装配 能够在编译时就发现错误

 

1.2、依赖注入的方式

1.2.1、构造器方式注入

<bean id="text" class="com.maven.Text" />

<bean id="hello" class="com.maven.Hello"><constructor-arg ref="text" /></bean>

构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖。

1.2.2setter方法注入

例如:<bean id="hello" class="com.maven.Hello"><property name="text" ref="text" /></bean>

之所以叫setter方法注入,因为这是通过找到类对应的setter方法,再进行相应的注入。

Setter方法注入是容器通过无参构造器或无参static工厂 方法实例化bean之后,调用该beansetter方法,即实现了基于setter的依赖注入。

1.2.3、最好的解决方案是用构造器参数实现强制依赖,setter方法实现可选依赖。

 

1.3、循环依赖

1.3.1、构造器方式无法解决,只能抛出异常。

1.3.2、因为Spring容器不缓存“prototype”作用域的bean,因此无法提前暴露一个创建中的bean:多例方式无法解决,只能抛出异常。

1.3.3、通过提前暴露一个单例工厂方法,从而使其他bean能够引用到该bean/提前暴露一个正在创建中的bean单例模式可以解决

 

1.4、不用创建对象,而只需要描述它如何被创建,不在代码里直接组装组件和服务,但是要在配置文件里描述哪些组件需要哪些服务,之后一个容器(IOC容器)负责把他们组装起来。

 

2、容器的初始化过程

1Resource定位,指对BeanDefinition的资源定位过程。通俗地讲,就是找到定义Javabean信息的XML文件,并将其封装成Resource对象

2BeanDefinition的载入,把用户定义好的Javabean表示为IOC容器内部的数据结构,这个容器内部的数据结构就是BeanDefinition

3、向IOC容器注册这些BeanDefinition

 

 

3bean知识

3.1bean的生命周期

3.1.1、实例化Bean

3.1.2、设置Bean的属性

3.1.3、检查Aware的相关接口并设置相关依赖

BeanNameAware

BeanFactoryAware

ApplicationContextAware

3.1.4、检查BeanPostProcessor接口并进行前置处理

3.1.5、检查BeanSpring配置文件中配置的init-method属性并自动调用其配置的初始化方法。

》由于这个是在Bean初始化结束时调用那个的方法,也可以被应用于内存或缓存技术

3.1.6、检查BeanPostProcessor接口并进行后置处理

3.1.7、当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用那个其实现的destory()方法

3.1.8、最后,如果这个BeanSpring配置中配置了destory-method属性,会自动调用其配置的销毁方法

 

3.2bean的作用域

3.2.1singleton

Spring IOC容器中只会存在一个共享的Bean实例,无论有多少个Bean引用它,始终指向同一对象

singletonBean的默认作用域

、默认情况下是容器初始化的时候创建,但也可设定运行时再初始化bean

DefaultSingletonBeanRegistry类里的singletonObjects哈希表保存了单例对象。

备注》Spring容器可以管理singleton作用域下bean的生命周期,在此作用域下,Spring能够精确制导bean何时被创建,何时初始化完成,以及何时销毁。

3.2.2prototype

、每次通过Spring容器获取prototype定义的bean时,容器都将创建一个新的Bean实例,每个Bean实例都有自已的属性和状态。

、当容器创建了bean的实例后,bean的实例就交给了客户端的代码管理,Spring容器将不再跟踪其生命周期,并且不会管理那些被配置成prototype作用域的bean的生命周期

、对有状态的bean使用prototype作用域,而对无状态的bean使用singleton作用域。

3.2.3request

在一次Http请求时,容器会返回该Bean的同一实例。而对不同的Htpp请求则会产生新的Bean,而且该bean仅在当前Http Request内有效

3.2.4session

在一次Http Session中,容器会返回该Bean的同一实例。而对不同的Session请求则会创建新的实例,该bean实例仅在当前Session内有效。

3.2.5global Session

在一个全局的Http Session中,容器会返回该Bean的同一实例,仅在使用portlet context时有效

3.3bean的创建

3.3.1、进入getBean()方法

3.3.2、判断当前bean的作用域是否单例,如果是,则去对应缓存中查找,没有查找到的话则新建实例并保存。如果不是单例,则直接新建实例(createBeanInstance

3.3.3、新建实例后再将注入属性(populateBean),并处理回调

、创建bean

、找到@Autowired的对象

、创建注入对象,并赋值

 

4、大致流程

1、首先根据配置文件找到对应的包,读取包中的类,找到所有含有@bean@service等注解的类,利用反射解析它们,包括解析构造器,方法,属性等等,然后封装成各种信息类收到container(其实是一个map) 里 (ioc容器初始化)

2、获取类时,首先从containere中查找是否有这个类,如果没有,则报错,如果有,则通过构造器信息将这个类new出来

3、如果这个类含有其他需要注入的属性,则进行依赖注入,如果有则还是从container找对应得解析类,new出对象,并通过之前解析出来的信息类找到setter方法(setter方法注入),然后用该方法注入对象(这就是依赖注入)。如果其中有一个类container里没有找到,则抛出异常。

4、如果有嵌套bean的情况,则通过递归解析

5、如果beanscopesingleton,则会重用这个bean不再重新创建,将这个bean放到一个map里,每次用都先从这个map里面找。如果scopesession,则该bean会放到session里面

6、总结:通过解析xml 文件,获取到bean的属性(idnameclassscope,属性等等)里面的内容,利用反射原理创建配置文件里类的实例对象,存入到Spring bean容器中。

posted @ 2019-10-06 17:57  HvH95  阅读(217)  评论(0)    收藏  举报