目录
3、IOC的容器有哪些?(ApplicationContext的实现类有哪些?)
4、ApplicationContext与BeanFactory的区别?
8、Spring中的单例Bean是线程安全的吗?怎么解决线程安全问题?
一、Spring
IOC
1、什么是Spring框架?
Spring是一个Java的开发框架,大大简化Java开发工作者的工作量,Spring有三个核心的部件:IOC/DI (控制反转/依赖注入)& AOP(面向切面)。
2、什么是IOC?
IOC是指控制反转,将对象的创建权交给Spring容器,使用时可以直接从容器中拿取,减少了程序之间的耦合程度,也更加利于后续的维护。
3、IOC的容器有哪些?(ApplicationContext的实现类有哪些?)
答:ClassPathXmlApplicationContext,FileSystemXmlApplicationContext,AnnotationConfigApplicationContext,BeanFactory。
4、ApplicationContext与BeanFactory的区别?
首先他们都是Spring的容器。
它们的区别是:
- BeanFactory是底层接口,ApplicationContext是他的派生接口,ApplicationContext的的功能会更强大。
- BeanFactory是懒加载运行,内存不足时,可以使用BeanFactory。ApplicationContext默认时容器初始化时加载所有的bean对象,它使用的速度相比较BeanFactory加载会更快,缺点是起始阶段比较消耗内存。
5、BeanFactory与FactoryBean的区别?
BeanFactory是一个工厂接口,重点在与Factory上,是Spring中所有的工厂类的父接口,用于管理和创建容器Bean对象。
FactoryBean是一个Bean接口,重点在于Bean上,主要用来构建复杂的Bean对象,FactoryBean接口主要有三个方法:
- 1、getObject():返回一个Bean对象并放入容器中
- 2、getObjectType():返回Bean对象的具体类型
- 3、isSingleton():判断是是否为单例
6、Spring中Bean有哪些作用域,之间有什么区别?
- singleton:单例,所有请求公用一个Bean,Bean在每个Spring容器中只有一个实例。
- properType:多例,每次使用都会创建一个Bean。一个Bean的定义可以有多个实例。
- request:每个HTTP请求,都会创建一个Bean,改作用域仅在基于web的Spring ApplicationContext情形下有效
- session:每个HTTP会话,都会创建一个Bean,在会话销毁时bean也会被销毁,该作用域仅在web的ServerleContext。
7、 bean标签中的属性?
<bean id=" " class=" " name=" " scope=" " init-method=" " destroy-method=" " lazy-method=" " autowire=" ">
- id:是Bean的唯一标识,IOC容器中Bean的ID值不允许重复,否则会报错。在Bean被依赖时、在获取Bean时使用。
- name:用于指定Bean的别名,bean标签的name属性也是不能重复。name标签等同于id属性
- class:要创建的Bean对象的全路径,只有子类Bean不用定义改属性。
- scope:表示Bean的作用域范围
- init-method:指定当前Bean的初始化方法,在Bean实例创建后,首先执行该属性指定的方法。
- destroy-method:指定当前Bean的销毁方法,在Bean即将被销毁前会自动执行改属性指定的方法。
- lazy-init:用于指定当前Bean的初始化时间,若值为true表示在初次调用时才会自动创建实例并初始化,false表示在IOC容器创建的时候就会完成创建实例和初始化。
- autowire:用于指定当前Bean的依赖关系的自动注入方式,自动装配,默认是"default"
8、Spring中的单例Bean是线程安全的吗?怎么解决线程安全问题?
不安全,但是Spring中的Bean是无状态的,不存储数据,所有某种程度上是安全的。
解决:
- 将Bean的作用域改为非单例
- 将共享变量放到ThreadLocal中,ThreadLcoal是一个本地线程,它存储的数据相对其他线程而言是封闭且隔离的。也可以解决线程安全问题。
9、 Spring容器中Bean的生命周期
BeanDefinition --> 实例化Bean --> 设置属性值 --> 初始化 --> 放到容器中待使用 -->销毁
- 先通过配置文件或者注解拿到所有的BeanDefinition,并放到BeanDenifitionMap中
BeanDefinition是☞Bean的定义,描述的时Bean的类型,及这个Bean的名字,有哪些属性,有哪些构造方法,有哪些方法等。- 从BeanDefinitionMap中拿到Bean定义并且实例化Bean,利用Java Reflection API。
- 通过依赖注入的方式给容器中Bean中的属性设置属性值。
- 初始化,给属性赋值
- 初始化完成后,Bean才真正的创建完成。将创建好的Bean放入ConcurrentHashMap中,此时即可通过getBean()方法来获取bean
- 容器销毁时Bean也会跟着销毁。
10、Spring框架中都用到了哪些设计模式?
- 工厂模式:BeanFactory就是简单的工厂模式体现,用来创建对象的实例。
- 单例模式:Bean默认为单例模式。
- 代理模式:Spring中的Aop功能用到了JDK的动态代理和CGLib字节码生成技术。
- 模板方法:用来解决代码重复问题。
- 观察者模式:定义一种对象的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖这个对象的都会得到通知被制动更新,如Spring中的Listener的实现ApplicationListener。
DI
1.什么是DI?
DI是指依赖注入。给容器中的Bean的属性赋值就叫依赖注入。
2、依赖注入的方式有哪些?
构造器注入 <constructor-arg name=" " ref=" " / value=" ">
setter注入<property name=" " ref=" " / value=" ">
通过注解注入
- name:指要注入的属性名称
- ref:指引用一个已经存在的对象,可以引用其他的Bean对象,使用时,Spring容器会在饮用后进行验证,验证当前的xml是否存在引用的Bean对象。
- value:指创建一个新的对象,value可以赋一些简单类型的值和对象的值,使用value时,Spring会在容器启动,实例化bean时进行验证。
AOP
1、什么是AOP?
面向切面编程。指将公共代码抽取出来,在不改变原代码的情况下对方法进行增强。
- 连接点:所有可以被增强的方法都是连接点
- 切入点:进行了功能增强的方法就是切入点
- 通知:指共性的功能
- 通知类:通知所在的类就是通知类
- 切面:切入点+通知就是切面。描述的是 在哪些方法上进行什么功能增强。
2、AOP的底层原理?
动态代理。程序在运行期间动态的生成一个代理对象,当调用到原始方法时,真正执行的时代理对象的代理方法。
动态代理有两种实现方式。一种时基于JDK的动态代理(反射的方式),一种时基于CGLib的动态代理(继承的方式)。
3、JDK动态代理的CGLib动态代理的区别?
- JDK动态代理只是提供接口代理,不支持类的代理
- CGLib是通过继承的方式做的动态代理,若某类被声明为final,那么CGLib是不能做动态代理的。
4、Spring中有哪些通知类?
- @Before :在目标方法执行之前执行的通知
- @After :在目标方法执行之后执行的通知
- @Around :在目标方法执行前后都可以执行的通知
- @AfterReturning : 在目标方法执行之后返回的通知
- @AfterThrowing : 在目标方法执行时抛出异常的执行通知
5、Spring AOP中常见的注解有哪些?
- @EnableAspectJAutoProxy:开启注解格式AOP,写在SpringConfig中
- @Aspect:写在类上,表明改类是AOP的切面类。
- @PointCut:声明改注解是一个切入点,通知行为的注解都可以直接用
Spring事务&注解
1、Spring中常用的注解
@Component:标识了一个受Spring管理的组件,泛指组件。
@Respository:标识持久层,数据访问组件,即DAO组件。
@Service:标识业务层组件。
@Controller:标识表现出,控制层组件
@RequestMapping:是用来请求地址映射的注解,可用于类或者方法上。
@Resource和@Autowired都是做bean的注入时使用。
2、Spring事务的作用?
保证业务层方法的同时成功或者失败
3、Spring事务管理的方式?
- 编程式事务:在代码中硬编码,使用TransactionTemplate管理事务,并通过它执行数据库操作。
- 声明式事务:在xml文件中管理,Spring的声明式事务是建立在AOP机制之上的,其本质是对目标方法前后进行拦截,在目标方法前创建或者加入一个事务,在执行完毕之后根据执行情况进行提交或者回滚。
4、Spring中事务的隔离级别
在TransactionDefinition接口中定义了五个表示隔离级别的常量:
- Default:
使用的后端数据库默认的隔离级别,Mysql默认采用Repeatable_Read隔离级别,Oracle默认采用Read_Committed隔离级别- Read_UnCommitted:
读未提交:只处理跟新丢失。如果一个事务已经开始写数据,则不允许其他事务同时进行写操作,但是允许其他事务读此行数据。- Read_Committed:
读已提交:处理更新丢失、脏读。事务能够看到的数据都是其他事务已经提交的修改数据,也就是保证不会看到中间性状态,脏读就不会出现了。- Repeatable_Read:
可重复读取:处理更新丢失、脏读、不可重复读取。保证同一个事务多次读取的数据是一致的,这是Mysql InnoDB 引擎的默认隔离级别。- Serializable:
序列化:提供严格的事务隔离。事务只能一个一个执行,不能并发执行。并发事务之间是串行化的,通常意味着读取需要获取共享读锁。更新需要获取排他锁写,如果SQL使用Where语句,还会获取区间锁,是最高级别的隔离。隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大,可以有限考虑把数据库系统的隔离级别设置为 RC,它能够避免脏读,且具有不错的性能。
5、不考虑事务的隔离级别会有什么问题?
并发事务可能会造成:
- 脏读:脏读指一个事务处理过程中读取了另一个事务未提交的数据。
- 不可重复读:对于两个事务A、B,事务B在事务A多次读取同一数据时,更新并提交,导致事务A多次读取的数据不一致。
- 幻读 :指对于两个事务A、B,事务A从一个表中读取了字段,然后B在该表中插入了一些新的行,之后如果A再次读取同一个表,就会多出几行。
- 更新丢失:两个事务同时对一个数据进行更新,一个事务的更新覆盖了另一个事务的更新,这是因为系统没用执行任何锁操作。
6、Spring中什么时候@Transaction会失效?
如果某个方法是private的,那么@Transaction就会失效,因为底层使用的是CGLib,CGLib是通过继承来实现的,子类不能重写父类的私有方法。
7、Spring中事务的传播行为?
可以在事务属性中通过Propagation属性来指定事务传播行为:
- Propagation_Required:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
- Propagation_Supports:支持当前事务,如果当前存在事务,就加入该事务。如果当前不存在事务,就以非事务执行。
- Propagation_Mandatory:支持当前事务,如果当前存在事务,就加入该事务。如果当前不存在事务,就抛出异常。
- Propagation_Requires_New:创建新事务,不论当前是否存在事务都会创建新事物。
- Propagation_Not_Supported:以非事务的方式运行,如果当前存在事务,会将当前事务挂起。
- Propagation_Never:以非事务的方式运行,如果当前存在事务,则抛出异常。
- Propagation_Nested:如果当前存在事务,则在嵌套事务内执行,如果当前不存在事务,则按Required属性执行。
8、如何添加事务?
1.使用@Transaction注解
2.在主配置类上添加 @EnableTransactionManager
3.将事务交给Spring管理 PlatformTransactionManagement
9、事务传播行为的作用?
用于解决业务层方法相互调用产生的事务问题,描述的是事务协调员是否要和事务管理员同成功或者同失败。
10、Spring中事务是如何实现的?
1、Spring事务的底层是基于数据库事务和AOP机制的。
2、首先对于使用了@Transaction注解的Bean,Spring会创建一个代理对象作为Bean。
3、当调用了代理对象的方法时,会先判断该方法上是否加入了@Transaction注解
4、如果加了,那么利用事务管理器创建一个数据库连接
5、并且修改数据库连接里的autocommit属性为false,禁止此连接自动提交,这是实现Spring事务非常重要的一步
6、然后执行当前方法,方法中会执行SQL
7、执行完当前方法后,如果没有出现异常就直接提交事务
8、如果出现了异常,并且这个异常是需要回滚的,就会混滚事务,否则仍然提交事务
9、Spring事务的隔离对应的就是数据库的隔离级别
10、Spring事务的传播机制是Spring事务自己实现的,也是Spring事务中最复杂的
11、Spring事务的传播机制是基于数据库连接来实现的,一个数据库连接一个事务,如果当前传播机制配置为需要新开一个事务,那么实际上就是先建立一个数据库连接,在此数据库连接上执行sql。