谈谈你对spring的理解:
Spring 是一个开源框架,可以实现java模块化开发,贯穿表现层,业务层,逻辑层,实现了各个层之间的解耦合关系
Spring 有两大核心是:IOC(控制反转)和 AOP(面向切面编程) DI(依赖注入)
(1)IOC(控制反转的理解):就是指创建对象的控制权的转移,以前创建对象的主动权和时机是由自己把控的,而现在这种权力转移到 Spring 容器中,并由容器根据配置文件去创 建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。
spring中bean的生命周期:
1 准备Spring的上下文环境,也就是ApplicationContext(Spring中的核心接口和容器,允许容器通过应用程序上下文环境创建、获取、管理bean)
2 扫描XML文件,或者是注解,得到一系列的BeanDefinitaion
3 然后通过BeanFactoryPostProcessor(Bean工厂的后置处理器), 要对BeanDefinition做一些处理,替换一些属性的值,比如MyBatis的Bean,就会做这个处理。
4 开始实例化Bean,即new出来Java对象,当然,他不是真的new,而是通过反射实例化Bean
5 开始初始化Bean,对Bean的属性赋值,即根据Bean的依赖关键,进行Bean的依赖注入
6 对Bean的后置处理,调用BeanPostProcessor,进行AOP相关的操作,这时候就会对Bean进行切面增强。
7 将Bean放入Bean容器,即一个HashMap中,这时候开发者就可以使用这个Bean了。
8 Bean的销毁,当Spring的AppliationContext要关闭的时候,会调用DisposableBean的destory方法,或者Bean的destory方法,进行Bean销毁。
BeanFactory 和 ApplicationContext 有什么区别
ApplicationContext
1.ApplicationContext是一个接口,提供了访问spring容器的API
2.ClassPathXmlApplicationContext是一个类,实现了上述功能
3.ApplicationContext的顶层接口是BeanFactory
4.BeanFactory定义了bean相关的最基本操作
5.ApplicationContext在BeanFactory基础上追加了若干新功能
单例Bean和单例模式
单例模式表示JVM中某个类的对象只会存在唯⼀⼀个。
⽽单例Bean并不表示JVM中只能存在唯⼀的某个类的Bean对象。
spring的bean是线程安全的吗?
Bean的作用域
singleton:默认作用域,单例bean,每个容器中只有一个bean的实例。
prototype:为每一个bean请求创建一个实例。
request:为每一个request请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。
session:与request范围类似,同一个session会话共享一个实例,不同会话使用不同的实例。
application:bean定义在servletContext的生命周期中复用一个单例对象(跨容器)。
global-session:全局作用域,所有会话共享一个实例。如果想要声明让所有会话共享的存储变量的话,那么这全局变量需要存储在global-session中。
Bean的线程安全分析
对于prototype作用域的Bean,每次都创建一个新对象,也就是线程之间不存在Bean共享,因此不会有线程安全问题。
对于singleton作用域的Bean,所有的线程都共享一个单例实例的Bean,因此是存在线程安全问题的。
但是如果单例Bean是一个无状态Bean,也就是线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。解释一下:
无状态Bean(Stateless Bean):就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的。
有状态Bean(Stateful Bean) :就是有实例变量的对象,可以保存数据,是非线程安全的。
对于有状态的bean(比如Model和View),就需要自行保证线程安全, 解决办法就是:
将有状态的bean的作用域由“singleton”改为“prototype”
{
singleton和prototype的区别:
singleton是单实例,prototype是多实例
前者在加载spring配置文件时候就会创建单实例对象
后者不是在加载spring配置文件时候创建对象,在调用getBean方法时候创建多实例对象
}
采用ThreadLocal解决线程安全问题,为每个线程提供一个独立的变量副本
线程同步机制和ThreadLocal都是为了解决多线程中相同变量的访问冲突问题:
同步机制采用了“时间换空间”的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要排队。
ThreadLocal采用了“空间换时间”的方式。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。
Spring 的对象默认是单例的还是多例的? 单例 bean 存不存在线程安全问
题呢?
Spring 框架中都用到了哪些设计模式?
Spring 事务的实现方式和实现原理
Spring的常用注解
@Component 标识为普通组件
@Service 标识为业务层组件
@Controller 标识为控制层组件
@Repository 标识为持久层组件
*上面四个注解功能是一样的,都可以用来创建bean实例
属性注入:
@AutoWired:根据属性类型进行自动注入(装配)
@Qualifier:根据名称进行注入(这个Qualifier注解的使用,要和上面@Autowired一起使用)
@Resource:可以根据类型注入,也可以根据名称注入
@Value:注入普通类型属性
配置类:
@Configuration 标识这个类是一个配置类
@ComponentScan 开启组件扫描
@EnableTransactionManagement 开启事务
@Bean 创建bean实例
@Transactional 一般是在业务逻辑层加的 让该类有事务的功能特性
@RequestMapping 将请求和处理请求的控制器方法关联起来,建立映射关系
@PathVariable 将占位符所表示的数据赋值给控制器方法的形参 (用于RESTful风格中)
@ResponseBody 将该方法的返回值直接作为响应报文的响应体响应到浏览器,当成是一个响应体返回数据而不是视图名称
@RestController 复合注解,标识在控制器的类上,@RestController=@Controller+@ResponseBody
@Resource 和@Autowired 依赖注入的区别是什么? @Qualifier 使用场
景是什么?
Spring 的事务传播行为
Spring事务什么时候会失效
spring事务的原理是AOP,进⾏了切⾯增强,那么失效的根本原因是这个AOP不起作⽤了!常⻅情况有 如下⼏种
1、发⽣⾃调⽤,类⾥⾯使⽤this调⽤本类的⽅法(this通常省略),此时这个this对象不是代理类,⽽是 UserService对象本身! 解决⽅法很简单,让那个this变成UserService的代理类即可!
2、⽅法不是public的:@Transactional 只能⽤于 public 的⽅法上,否则事务不会失效,如果要⽤在 ⾮ public ⽅法上,可以开启 AspectJ 代理模式。
3、数据库不⽀持事务
4、没有被spring管理
5、异常被吃掉,事务不会回滚(或者抛出的异常没有被定义,默认为RuntimeException)
Spring中什么时候@Transactional会失效
因为Spring事务是基于代理来实现的,所以某个加了@Transactional的⽅法只有是被代理对象调⽤时, 那么这个注解才会⽣效,所以如果不是被代理对象来调⽤这个⽅法,那么@Transactional是不会生效的。
同时如果某个⽅法是private的,那么@Transactional也会失效,因为底层cglib是基于⽗⼦类来实现的,⼦类是不能重载⽗类的private⽅法的,所以⽆法很好的利⽤代理,也会导致@Transactianal失效