这里写目录标题
- IOC容器
- AOP
- Springboot
- SpringMVC核心组件
- Mybatis映射器
IOC容器
面向接口编程
IOC和DI是什么?
a) 控制反转是就是应用本身不负责依赖对象的创建和维护,依赖对象的创建及维护是由外部容器负责的,这样控制权就由应用转移到了外部容器,控制权的转移就是控制反转。
b) 依赖注入是指:在程序运行期间,由外部容器动态地将依赖对象注入到组件中如:一般,通过构造函数注入或者setter注入。
为什么底层是map?
- 要方便bean存储,
- 方便查找bean
- 没指定,是单例的
a) Map<String,Bean的信息> map= new ConcurrentHashMap();
b) 即Map<String,BeanDefination> map
Spring架构设计过程
Processor:Spring框架的扩展性
新增两个接口:FactoryBean,Environment
BeanFctory和FactoryBean:用于Spring定制化
- SpringCloud的组件Feign用到FactoryBean:
- 总结:创造一般的对象:用BeanFactory;创造独特的对象,用FactoryBean。
- FactoryBean:三个方法:
a) getObject();
b) getObjectType()
c) isSingleton()
1.BeanFactory 和 FactoryBean的区别?
- BeanFactory是个Factory,也就是IOC容器或对象工厂,在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的,提供了实例化对象和拿对象的功能。
a) 使用场景:
b) 从Ioc容器中获取Bean(byName or byType)
c) 检索Ioc容器中是否包含指定的Bean
d) 判断Bean是否为单例 - FactoryBean是个Bean,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似。
a) 使用场景:
b) ProxyFactoryBean
2.BeanFactory和ApplicationContext的异同
- 相同:
a) Spring提供了两种不同的IOC 容器,一个是BeanFactory,另外一个是ApplicationContext,它们都是Java interface,ApplicationContext继承于BeanFactory(ApplicationContext继承ListableBeanFactory。
b) 它们都可以用来配置XML属性,也支持属性的自动注入。
c) 而ListableBeanFactory继承BeanFactory),BeanFactory 和 ApplicationContext 都提供了一种方式,使用getBean(“bean name”)获取bean。 - 不同:
a) 当你调用getBean()方法时,BeanFactory仅实例化bean,而ApplicationContext 在启动容器的时候实例化单例bean,不会等待调用getBean()方法时再实例化。
b) BeanFactory不支持国际化,即i18n,但ApplicationContext提供了对它的支持。
c) BeanFactory与ApplicationContext之间的另一个区别是能够将事件发布到注册为监听器的bean。
d) BeanFactory 的一个核心实现是XMLBeanFactory 而ApplicationContext 的一个核心实现是ClassPathXmlApplicationContext,Web容器的环境我们使用WebApplicationContext并且增加了getServletContext 方法。
e) 如果使用自动注入并使用BeanFactory,则需要使用API注册AutoWiredBeanPostProcessor,如果使用ApplicationContext,则可以使用XML进行配置。
f) 简而言之,BeanFactory提供基本的IOC和DI功能,而ApplicationContext提供高级功能,BeanFactory可用于测试和非生产使用,但ApplicationContext是功能更丰富的容器实现,应该优于BeanFactory
3.ApplicationContext的关系详解
- BeanFactory 简单粗暴,可以理解为就是个 HashMap,Key 是 BeanName,Value 是 Bean 实例。通常只提供注册(put),获取(get)这两个功能。我们可以称之为 “低级容器”。
- ApplicationContext 可以称之为 “高级容器”。因为他比 BeanFactory 多了更多的功能。
a) “应用上下文”, 代表着整个大容器的所有功能
b) 该接口定义了一个 refresh 方法,此方法是所有阅读 Spring 源码的人的最熟悉的方法,用于刷新整个容器,即重新加载/刷新所有的 bean
4.ApplicationContext通常的实现是什么?
- FileSystemXmlApplicationContext :此容器从一个XML文件中加载beans的定义,XML Bean 配置文件的全路径名必须提供给它的构造函数。
- ClassPathXmlApplicationContext:此容器也从一个XML文件中加载beans的定义,这里,你需要正确设置classpath因为这个容器将在classpath里找bean配置
- WebXmlApplicationContext:此容器加载一个XML文件,此文件定义了一个WEB应用的所有bean
Spring IOC容器
1.描述下Spring IOC容器的初始化过程
Spring IOC容器的初始化简单的可以分为三个过程:
a) 加载第一个过程是Resource资源定位。这个Resouce指的是BeanDefinition的资源定位。IO流/这个过程就是容器找数据的过程,就像水桶装水需要先找到水一样。
b) 第二个过程是BeanDefinition的载入过程。这个载入过程是把用户定义好的Bean表示成Ioc容器内部的数据结构,而这个容器内部的数据结构就是BeanDefition。
c) 第三个过程是向IOC容器注册这些BeanDefinition的过程,这个过程就是将前面的BeanDefition保存到HashMap中的过程。
Bean的生命周期
总结:
- 实例化Bean:
a) 对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化。对于ApplicationContext容器,当容器启动结束后,通过获取BeanDefinition对象中的信息,实例化所有的bean。 - 设置对象属性(依赖注入):
a) 实例化后的对象被封装在BeanWrapper对象中,紧接着,Spring根据BeanDefinition中的信息 以及 通过BeanWrapper提供的设置属性的接口完成依赖注入。 - 处理Aware接口:
a) 接着,Spring会检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给Bean:
b) 如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String beanId)方法,此处传递的就是Spring配置文件中Bean的id值;
c) 如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory()方法,传递的是Spring工厂自身。
d) 如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文; - BeanPostProcessor:
a) 如果想对Bean进行一些自定义的处理,那么可以让Bean实现了BeanPostProcessor接口,那将会调用postProcessBeforeInitialization(Object obj, String s)方法。 - InitializingBean 与 init-method:
a) 如果Bean在Spring配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法。 - 如果这个Bean实现了BeanPostProcessor接口,
a) 将会调用postProcessAfterInitialization(Object obj, String s)方法;由于这个方法是在Bean初始化结束时调用的,所以可以被应用于内存或缓存技术;
以上几个步骤完成后,Bean就已经被正确创建了,之后就可以使用这个Bean了。 - DisposableBean:
a) 当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用其实现的destroy()方法; - destroy-method:
a) 最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。
Spring循环依赖
1.问题描述:
2.问题解决:
3.思考问题
注释:
- 全局唯一:只存在: A@1755或者lambda表达式的A
- 三级缓存:
- 普通对象:匿名内部类:lambda表达式
- 代理对象:A@1755
AOP
面向切面编程
1.问题描述:
AOP的运行流程
AOP拦截器链是如何调用的?
AOP的实现原理
- Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
- Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。
- 如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
Spring通知有哪些类型
(1)前置通知(Before advice):在某连接点(join point)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)。
(2)返回后通知(After returning advice):在某连接点(join point)正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。
(3)抛出异常后通知(After throwing advice):在方法抛出异常退出时执行的通知。
(4)后通知(After (finally) advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
(5)环绕通知(Around Advice):包围一个连接点(join point)的通知,如方法调用。这是最强大的一种通知类型。 环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。 环绕通知是最常用的一种通知类型。
Spring 是如何管理事务的?
Spring事务管理主要包括3个接口,Spring的事务主要是由它们(PlatformTransactionManager,TransactionDefinition,TransactionStatus)三个共同完成的。
- PlatformTransactionManager:事务管理器–主要用于平台相关事务的管理
主要有三个方法:
a) commit 事务提交;
b) rollback 事务回滚;
c) getTransaction 获取事务状态。 - TransactionDefinition:事务定义信息–用来定义事务相关的属性,给事务管理器PlatformTransactionManager使用
这个接口有下面四个主要方法:
a) getIsolationLevel:获取隔离级别;
b) getPropagationBehavior:获取传播行为;
c) getTimeout:获取超时时间;
d) isReadOnly:是否只读(保存、更新、删除时属性变为false–可读写,查询时为true–只读)
事务管理器能够根据这个返回值进行优化,这些事务的配置信息,都可以通过配置文件进行配置。 - TransactionStatus:事务具体运行状态–事务管理过程中,每个时间点事务的状态信息。
例如它的几个方法:
a) hasSavepoint():返回这个事务内部是否包含一个保存点,
b) isCompleted():返回该事务是否已完成,也就是说,是否已经提交或回滚
c) isNewTransaction():判断当前事务是否是一个新事务 - 声明式事务的优缺点:
a) 优点:不需要在业务逻辑代码中编写事务相关代码,只需要在配置文件配置或使用注解(@Transaction),这种方式没有侵入性。
b) 缺点:声明式事务的最细粒度作用于方法上,如果像代码块也有事务需求,只能变通下,将代码块变为方法。
Spring 的不同事务传播行为有哪些,干什么用的?
bean的作用域
(1)singleton:默认,每个容器中只有一个bean的实例,单例的模式由BeanFactory自身来维护。
(2)prototype:为每一个bean请求提供一个实例。
(3)request:为每一个网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。
(4)session:与request范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效。
Spring的自动装配
- 在spring中,对象无需自己查找或创建与其关联的其他对象,由容器负责把需要相互协作的对象引用赋予各个对象,使用autowire来配置自动装载模式。
- 在Spring框架xml配置中共有5种自动装配:
(1) no:默认的方式是不进行自动装配的,通过手工设置ref属性来进行装配bean。
(2) byName:通过bean的名称进行自动装配,如果一个bean的 property 与另一bean 的name 相同,就进行自动装配。
(3) byType:通过参数的数据类型进行自动装配。
(4) constructor:利用构造函数进行装配,并且构造函数的参数通过byType进行装配。
(5) autodetect:自动探测,如果有构造方法,通过 construct的方式自动装配,否则使用 byType的方式自动装配。 - 基于注解的方式:
(1) 使用@Autowired注解来自动装配指定的bean。在使用@Autowired注解之前需要在Spring配置文件进行配置,<context:annotation-config />。在启动spring IoC时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied、@Resource或@Inject时,就会在IoC容器自动查找需要的bean,并装配给该对象的属性。在使用@Autowired时,首先在容器中查询对应类型的bean:
(2) 如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据;
(3) 如果查询的结果不止一个,那么@Autowired会根据名称来查找;
(4) 如果上述查找的结果为空,那么会抛出异常。解决方法时,使用required=false。
(5) @Autowired可用于:构造函数、成员变量、Setter方法
(6) 注:@Autowired和@Resource之间的区别 - @Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。
- @Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入。
怎样开启注解装配?
- 注解装配在默认情况下是不开启的,为了使用注解装配,我们必须在Spring配置文件中配置 context:annotation-config/元素。
@Component, @Controller, @Repository, @Service 有何区别?
@Required 注解有什么作用
@Qualifier 注解有什么作用
@RequestMapping 注解有什么用?
Springboot
Spring框架中有哪些不同类型的事件
(1)上下文更新事件(ContextRefreshedEvent):在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。
(2)上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
(3)上下文停止事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
(4)上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
(5)请求处理事件(RequestHandledEvent):在Web应用中,当一个http请求(request)结束触发该事件。
什么是SpringBoot?
- 是基于Spring基础之上的二次封装框架,设计目标就是简化Spring那些麻烦的地方。
- 它的优点:
a) 部署更加简单:内置web容器,有java环境就可以运行
b) 使监控更加简单:提供大量端点,可以直接监控应用
c) 使配置更加简单:提供大量默认配置与自定义配置,不再让配置文件到处都是
Spring Boot 中的 starter 到底是什么 ?
Starter是一个集成接合器,它主要帮我们简化两个步骤:
- Jar包依赖关系:在Starter内部采用统一版本,统一第三方包的方式进行整合,我们不需要再去找其他的jar包,只需要引入Starter即可解决全部jar包问题
- 完成了自动配置:starter包内,会将需要的配置用xxxAutoConfiguration类进行处理,省略掉大量的配置项
Springboot是如何完成的自动配置?
- SPI机制,在spring.factories文件中指向了对应jar包的AutoConfiguration类,该类中利用条件注解完成了对Bean的自动加载,
- 同时在SpringBoot的启动类上由@EnableAutoConfiguration读取每个Starter文件的spring.factories。由此,完成的自动配置
SpringBoot处理异常?
- ControllerAdvice处理异常。通过实现一个ControllerAdvice类,来处理控制类抛出的所有异常
描述一下SpringBoot启动类的注解?
启动类的注解是:@SpringBootApplication
主要包含以下3个注解:
@Configuration注解,实现配置文件的功能
@EnableAutoConfiguration:打开自动配置的功能
@ComonentScan:Spring组件扫描
如何理解 Spring Boot 配置加载顺序?
- Springboot启动会扫描一下位置的application.properties.yml作为默认的配置文件
- 工程根目录:./config/
- 工程根目录:./
- Classpath:/config/
- Classpath:/
- 加载的优先级顺序是从上向下加载,并且所有的文件都会被加载,高优先级的内容会覆盖低优先级的内容,形成互补配置
- 也可以通过指定配置spring.config.location来改变默认配置,一般在项目已经打包后,我们可以通过指令:java -jar xxxx.jar –spring.config.location=d:/雎然/application.yml来加载外部的配置
SpringMVC核心组件
Spring MVC的主要组件?
什么是DispatcherServlet
Spring的MVC框架是围绕DispatcherServlet来设计的,它用来处理所有的HTTP请求和响应。
什么是Spring MVC框架的控制器?
控制器提供一个访问应用程序的行为,此行为通常通过服务接口实现。控制器解析用户输入并将其转换为一个由视图呈现给用户的模型。Spring用一个非常抽象的方式实现了一个控制层,允许用户创建多种用途的控制器。
Spring MVC的控制器是不是单例模式,如果是,有什么问题,怎么解决?
是单例模式,所以在多线程访问的时候有线程安全问题,不要用同步,会影响性能的,解决方案是在控制器里面不能写字段。
Mybatis映射器
#{}和${}的区别
- #{}是占位符,预编译处理;${}是拼接符,字符串替换,没有预编译处理。
- Mybatis在处理#{}时,#{}传入参数是以字符串传入,会将SQL中的#{}替换为?号,调用PreparedStatement的set方法来赋值。
- Mybatis在处理时 , 是 原 值 传 入 , 就 是 把 {}时,是原值传入,就是把时,是原值传入,就是把{}替换成变量的值,相当于JDBC中的Statement编译
- 变量替换后,#{} 对应的变量自动加上单引号 ‘’;变量替换后,${} 对应的变量不会加上单引号 ‘’
- #{} 可以有效的防止SQL注入,提高系统安全性;${} 不能防止SQL 注入
- #{} 的变量替换是在DBMS 中;${} 的变量替换是在 DBMS 外