1.Spring是什么
Spring是开源的,因为其大小和开销两方面来说都是轻量级,所以说Spring是一个轻量级的开源框架其中的IOC/DI控制反转和依赖注入可以轻松解除代码之间的耦合度,达到松耦合的目的因为其包含并管理应用对象Bean的配置和生命周期所以Spring也是一个容器
Spring 春天 Java开发的春天
轻量级的高内聚低耦合的开源框架,它是容器框架,有着用来承载JavaBean对象和中间层框架的作用
可以起一个管理JavaBean和中间连接的作用,可以让我们的企业开发更快,更简洁
Spring的两大核心分别是IOC/DI(控制反转/依赖注入)和 AOP(面向切面)
轻量级∶从大小和开销两方面而言Spring都是轻量级的
低耦合∶通过控制反转的技术轻松解除代码之间耦合度,达到松耦合的目的
高内聚∶提供了比如说面向切面编程的丰富支持,允许通过分离应用的业务逻辑和系统级别服务进行内聚性的开发
容器∶包含并管理应用对象Bean的配置和生命周期
框架∶将简单的组件配置,组合成为复杂的应用
2.谈谈你对IOC的理解
IOC容器∶里面存的是各种对象
常用方式是通过扫描组件实现对象的加载
由自己获取依赖改为由IOC容器注入依赖的过程,这就是"控制反转"这个名称的由来
控制,对依赖的控制权
反转,该由自己干的事,变成了IOC容器去干
- IOC容器∶里面存的是各种对象
(1.基于xml里配置的bean节点;2.@Repository,@Service,@Controller,@Component)
在项目启动的时候会读取配置文件的bean节点或者注解标注的组件,根据全限定类型(包名.类名)使用反射创建对象并放到容器里,这时候容器里就有各种各样对象了,使用的时候,通过DI(@Autowired,@Resource等注解)进行注入- 控制反转
没有IOC时∶对象A依赖于B,那么对象A在初始化的时候或者运行到某一点的时候,自己必须主动去创建对象B,或者使用已经创建好的对象B,无论创建还是使用对象B,控制权都在自己手上
引入IOC容器之后∶对象A和对象B之间失去了联系,当对象A运行到需要对象B的时候IOC容器会主动创建一个对象B 注入到对象A需要的地方
通过前后对象,对象A获取依赖对象B的过程,由主动变为了被动行为,控制权颠倒了,这就是"控制反转"这个名称的由来
依赖注入∶
“获取依赖对象的过程被反转了”,控制反转后,获取依赖对象的规过程由自身管理变为了由IOC容器主动注入
依赖注入的实现是IOC的方法,就是IOC容器运行期间,动态将某种依赖关系注入到对象之中
3.@Autowired 与 @Resource之间的区别
@Autowired 是Spring提供的
三种注入方法∶1.构造方法注入;2.setter注入;3.字段注入
注入规则∶
@Autowired会先按照类型进行匹配,如果类型匹配超过1个,会根据@Qualifier的值进行匹配
如果没有@Qualifier,那么就根据名称进行匹配,如果名称匹配不上,容器启动会报错
如果容器中没有该类型bean,会报错,除非添加@Autowired(required=false)
了
需要对某个类型的bean进行注入时
- 如果容器有唯—一个该类型的bean
使用@Autowired可以直接进行注入,会依照类型进行比对- 如果容器中不存在该类型的bean 使用@Autowired会报错
- 需要进行注入的时候,如果容器中有唯一一个此类型的bean就进行注入如果没有就不注入
可以使用 @Autowired(required=false)4如果容器中需要的类型的bean有很多个
- 如果有额外注解 @Qualifier(“p2”)那么根据该注解的名称进行匹配
- 如果没有 @Qualifier或者不对应,但是名称可以匹配,那么根据名称进行匹配
- 如果没有 @Qualifier注解并且名称也不匹配,启动报错
@Resource是JDK提供的
两种注入方式∶setter注入和字段注入
注入规则∶
@Resource注入会根据属性/字段名称进行匹配,若匹配不上则根据类型进行匹配
如果@Resource(name=“p2”)那么会根据名称进行匹配,即使名称不匹配,也不会根据类型进行匹配
4.Spring框架中用到了哪些设计模式
- 工厂模式∶ Spring使用工厂模式,通过BeanFactory,ApplicationContext创建bean对象
- 代理模式∶ Spring AOP功能实现
- 单例模式∶ Spring中的Bean默认都是单例的
- 模板方法模式∶Spring中的jdbcTemplate以Template结尾的都是模板模式
- 适配器模式∶Spring AOP的增减或通知使用了适配器模式,SpringMVC中的也是用到适配器模式适配Controller
5.单例模式
在容器中,bean的实例只有一个,所以大家共用一个实例
懒汉式
类加载时不会创建对象实例,只有使用的对象实例才会被创建
public class LazySingleton{ //创建一个类
private LazySingleton(){} //创建一个私有的构造方法
private static LazySingleton singleton=null; //创建一个私有静态的当前类的属性singleton,并赋值为null
public static LazySingleton getSingleton(){ //创建一个公开的静态方法,返回值类型为当前类的类型
if(singleton==null){ //判断当前类的私有静态属性singleton是否为空
singleton = new LazySingleton(); //若为空,创建当前类对象并赋值给singleton
}
return singleton; //返回该对象
//考虑线程安全,可以在方法上加synchronized
}
}
饿汉式
类加载时就已经将对象实例创建完成
public class HungrySingleton{ //创建一个类
//创建一个私有静态的当前类属性sinleton并实例化
private static HungrySingleton singleton=new HungrySingleton();
private HungrySingleton(){} // 私有的构造方法
public HungrySingleton getSingleton(){ // 创建公开的静态方法,返回值是当前类的类型
return singleton; // 将私有静态属性singleton返回
}
}
- 懒汉式默认不会实例化,要等到外部调用方法时才会,饿汉式一开始就实例化了对象
- 线程安全上,饿汉式肯定是线程安全的,因为没出现的之前就实例化了对象,懒汉式是线程不安全的,因为多线程如果一个判断完实例为null,时间片没了那么一个线程也进入了方法,判断实例也为nulI那么该线程就会创建实例对象,刚才的线程获取到时间片之后,已经到了实例化的步骤,那么就会出现多个实例
- 性能,饿汉式不需要加锁,执行效果高,但是懒汉可能是出现安全问题,可能需要加锁,执行效率低
- 占用内存∶饿汉式不管你用不用得到它的实例对象,它一开始就已经实例化在那里了,占用内存空间,但是懒汉式是等到了用的时候才实例化,不会浪费内存
可实现懒汉式线程安全的方式 加锁 synchronized 或者 可以使用 volatile 关键字
6.Bean 的作用域
singleton ∶单例 默认 每个容器只有一个bean的实例,单例的模式是有BeanFactory自身来维护,该对象的生命周期与Spring IOC容器一致
prototype∶非单例 为每一个bean请求,提供一个实例,在每次注入时,都会创建一个新的对象
request∶Web环境下的作用域,bean被定义为每个HTTP请求中创建一个单例对象,也就是说在单个请求中都会复用这一个单例对象
session∶与request范围类似,确保每个session有一个bean的实例,在session过期后,bean随之消失