spring
1什么是 spring?
<bean id="唯一性" class="类全名">
<property name="属性名" value="属性值" | ref="容器中另外一个 bean 的 id 值"/>
</bean>
它是一个容器框架(spring容器),用来装 javabean(java 对象),中间层框架(万能胶)可以起一个连接作用,比如说把 SpringMVC 和 Mybatis 粘合在一起运用。简单来说,Spring 是一个的控制反转(IoC)和面向切面(AOP)的轻量级容器框架。
Spring 是一个轻量的 IoC DI 和 AOP 容器开源框架(Spring 是一个可以帮我们创建对象,设置对象属性值的开源容器(map)框架)
好处:解决代码耦合度高的问题, 控制器事务繁琐的问题, 使用第三方框架麻烦
2什么是 spring IOC?
以前我找对象,我得找到人,让后才能看她是什么性格,。。。
现在,所有的人都在媒介哪里登记一下,我找的话,找媒介,说出我得需求,媒介给我提供即可
这个媒介就是ioc,媒介去把所有信息提供给我,我拿到我得女朋友就是di注入
1.IoC其实是一种设计思想:将对象之间的依赖关系统一的交给了容器来管理,实现了松散耦合,
2.以前是在对象内部通过new进行创建对象,而现在由spring容器里面的ioc容器去创建对象
3. 传统实现中,我们自己在对象中主动控制去直接获取依赖的对象,也就是正转
在控制反转中,所有的类都会在 spring 容器中登记,告诉 spring 你是个什么东西,你需要什么东西,然后 spring 会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。把控制器交给了容器,ioc容器来帮忙创建及注入依赖对象;现在是所有对象都被 spring 的ioc控制,让他们都依赖于ioc容器,通过ioc容器来主动建立关系,实现控制权的转移
所以在Spring中,IoC容器扮演了一个中心角色,负责创建所需要的对象,装配对象之间的依赖关系,并管理它们的整个生命周期。
IoC 还有一个另外的功能:“依赖注入 (DI=Dependency Injection)” ,即由容器动态的将某种依赖关系注入到组件之中,DI(依赖注入)其实就是 IOC 的一种类型, IoC 的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过 DI(Dependency Injection,依赖注入)来实现的
IoC 的三种注入方式:(1)接口注入(2)构造方法注入。时效性好,但是灵活性差。(3)赋值方式注入。时效性差,但是灵活性好,需要有 set 方法。
<!-- 告诉 Spring 帮我们创建什么对象,设置什么属性值 -->
<bean id="person" class="cn.wolfcode._01_hello.Person"> <!-- IoC -->
<!--
Person p = new Person();
p.setName("红旗")
-->
<property name="name" value="大罗"/> <!-- DI -->
</bean>
3有没有用过 aop?aop 的特性有哪些? 有什么应用?用到的业务的场景是怎样的?
有,AOP(面向接口编程) 是基于动态代理实现的;和 OOP(面向对象编程)相比较,AOP 是对 OOP 的补充延续(plus)。OOP 是静态的抽象,而 AOP 是动态的抽象。关于 AOP 的概念,简单来说就是将一个工程中与源代码无关,但是很多地方都要用,抽出来也不影响源代码上下文的那一部分代码抽出来,然后要用的时候就织入进去,进行使用,至于是在指定的代码之前使用还是之后又或者异常使用等,可以动态的进行;
减少重复代码,提高开发效率,并且便于维护
应用:例如,在很多业务中都需要记录操作日志,所以在业务流程中嵌入大量的日志代码。系统中嵌入了这种大量与业务无关的其他重复性代码,系统的复杂性、代码的重复性增加了。维护起来会更加复杂。
应用场景: ①记录日志; ②监控方法运行时间 (监控性能) ; ③权限控制 ;④ 缓存优化 (第一次调用查询数据库,将查询结果放入内存对象, 第二次调用, 直接从内存对象返回,不需要查询数据库 ); ⑤事务管理 (调用方法前开启事务, 调用方法后提交关闭事务 )
Pointcut(切入点):被增强的方法
Advice(通知/ 增强):封装增强业务逻辑的方法
Aspect(切面):切点+通知
Weaving(织入):将切点与通知结合的过程
4 Spring 动态代理的方式有几种, 他们之间有什么区别
有两种方式:
JDK 动态代理,基于接口(默认代理模式),CGLIB 动态代理基于父类(若要使用需要进行配置);
区别:
jdk 的代理对象与被代理对象实现了同一接口,底层通过 clone()方法,将实现类的方法复制过来在按照 invoke 中的配置对方法进行增强。
cglib 代理则是代理对象继承了被代理对象的方法,然后自身进行增强。
这两种代理思想在外来的自动生成代码方向会经常被使用,实现完全体代码的复用性两种方式的对比和选择如下:
若目标对象实现了若干接口,spring 使用 JDK 的 Proxy 类代理。
优点:因为有接口,所以使系统更加松耦合
缺点:为每一个目标类创建接口
若目标对象没有实现任何接口,spring 使用 CGLIB 库生成目标对象的子类。
优点:因为代理类与目标类是继承关系,所以不需要有接口的存在。
缺点:因为没有使用接口,所以系统的耦合性没有使用 JDK 的动态代理好
5.spring 底层都用过哪些设计模式
- 简单工厂
又叫做静态工厂方法(StaticFactory Method)模式, 简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类
- 工厂方法(Factory Method)
定义一个用于创建对象的接口,让子类决定实例化哪一个类, Spring 中的 FactoryBean 就是典型的工厂方法模式
3. 单例(Singleton)
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
4. 适配器(Adapter)
将一个类的接口转换成客户希望的另外一个接口。Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
5.包装器(Decorator)
动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator 模式相比生成子类更为灵活。
6. 代理(Proxy)
为其他对象提供一种代理以控制对这个对象的访问。
从结构上来看和 Decorator 模式类似,但 Proxy 是控制,更像是一种对功能的限制,而 Decorator 是增加职责, Spring 的 Proxy 模式在 aop 中有体现,比如 JdkDynamicAopProxy 和 Cglib2AopProxy。
7.观察者(Observer)
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
8. 策略(Strategy)
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
9.模板方法(Template Method)
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
另外还有命令模式,职责链模式,抽象工厂模式。
6 Spring框架中有许多常用注解,以下是一些常见的注解及其作用:
1.@Component: 标识一个类为Spring容器的组件,通常用于自动扫描和装配Bean。
2.@Autowired: 自动装配Bean,通过类型进行匹配注入。@Autowired可用于:构造函数、成员变量、Setter方法
3.@Resource: 类似于@Autowired,但通过名称进行注入。
@Autowired和@Resource之间的区别:
(1) @Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。
(2) @Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入。
4.@Qualifier: 和@Autowired一起使用,通过指定Bean的名称进行注入。
5.@Repository: 标识一个类为数据访问层(DAO)的组件。
6.@Service: 标识一个类为业务逻辑层(Service)的组件。
7.@Controller: 标识一个类为控制层(Controller)的组件。
8.@RequestMapping: 映射URL到Controller的处理方法。
9.@PathVariable: 获取URL中的参数。
10.@RequestParam: 获取请求参数的值。
11.@ResponseBody: 返回数据直接写入HTTP响应中。
12.@SessionAttribute: 将属性存储到Session中。
13.@Aspect: 定义切面,用于实现横切关注点的功能。
14.@Transactional: 声明事务的属性,用于控制数据库事务。
7Spring中Bean的作用域?
1.singleton(单例)(默认的):在整个应用中只创建一个Bean实例,并在容器启动时就创建,以后每次请求都返回同一个实例。
2.prototype(原型):每次请求都会创建一个新的Bean实例,适用于一些状态不可共享的Bean。
3.request(请求):在每个HTTP请求中创建一个Bean实例,该Bean实例仅在当前请求中有效,对于不同的请求,会创建不同的Bean实例。
4.session(会话):在每个HTTP Session中创建一个Bean实例,该Bean实例仅在当前Session中有效,对于不同的Session,会创建不同的Bean实例。
5.global-session(全局会话):在基于portlet的web应用中使用,该作用域仅在基于portlet的web应用中有效,一个portlet的多个请求共享一个Bean实例。
8.Spring Bean的生命周期?
简单来说,Spring Bean的生命周期只有四个阶段:
à实例化 Instantiation(像我们平时new一个对象一样)
--> 属性赋值 Populate (比如我们的bean中有一个属性,这个属性添加了@Autowired自动装配注解。)
--> 初始化 Initialization
--> 销毁 Destruction
9 Spring框架中的Bean是线程安全的么?如果线程不安全,那么如何处理?
因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体情况还是要结合Bean的作用域来讨论。
对于prototype作用域的Bean,每次都创建一个新对象,也就是线程之间不存在Bean共享,因此不会有线程安全问题。
对于singleton作用域的Bean,所有的线程都共享一个单例实例的Bean,因此是存在线程安全问题的。但是如果单例Bean是一个无状态Bean,也就是线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。比如Controller类、Service类和Dao等,这些Bean大多是无状态的,只关注于方法本身。
有状态Bean(Stateful Bean) :就是有实例变量的对象,可以保存数据,是非线程安全的。
无状态Bean(Stateless Bean):就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的。
对于有状态的bean(比如Model和View),就需要自行保证线程安全,最浅显的解决办法就是将有状态的bean的作用域由“singleton”改为“prototype”。
也可以采用ThreadLocal解决线程安全问题,为每个线程提供一个独立的变量副本,不同线程只操作自己线程的副本变量。
10. 请阐述 Spring 的事务隔离级别。
Spring 事务上提供以下的隔离级别:
- ISOLATION_DEFAULT(默认的): 使用后端数据库默认的隔离级别
- ISOLATION_READ_UNCOMMITTED(允许读没有提交的) : 脏读:允许读取事务回滚前未提交的变更的数据,可能会导致脏读,幻读(被读的事务进行了操作导致,读两次的结果(增删导致的数量的变化)不一样)或不可重复读(一个事务,读了两次相同的,导致结果不一样(内容不一样))
- ISOLATION_READ_COMMITTD (必须读取已提交的): 允许读取为提交数据,可以阻止脏读,当时幻读或不可重复读仍可能发生
- ISOLATION_REPEATABLE_READ(可重复读): 对统一字段多次读取结果是一致的,除非数据是被本事务自己修改.可以阻止脏读,不可重复读,但幻读可能发生
- ISOLATION_SERIALIZABLE(串行化,一个一个执行) : 完全服从 ACID
丢失修改:两次事务,同时修改一个导致了最后一个执行的进行了覆盖
11. spring 的事务的传播机制
propagation_required 如果没有,就开启一个事务;如果有,就加入当前事务(方法 B 看到自己已经运行在 方法 A 的事务内部,就不再起新的事务,直接加入方法 A)
propagation_requires_new 如果没有,就开启一个事务;如果有,就将当前事务挂起。(方法 A 所在的事务就会挂起,方法 B 会起一个新的事务,等待方法 B 的事务完成以后,方法 A 才继续执行)
propagation _nested 如果没有,就开启一个事务;如果有,就在当前事务中嵌套其他事务
propagation _supports 如果没有,就以非事务方式执行;如果有,就加入当前事务(方法 B 看到自己已经运行在 方法 A 的事务内部,就不再起新的事务,直接加入方法 A)
propagation _not_supported 如果没有,就以非事务方式执行;如果有,就将当前事务挂起,(方法 A 所在的事务就会挂起,而方法 B 以非事务的状态运行完,再继续方法 A 的事务)
propagtion_never 如果没有,就以非事务方式执行;如果有,就抛出异常。
propagtion_mandatory 如果没有,就抛出异常;如果有,就使用当前事务
12什么是Springdata的jpa
13 如何创建一个程序?
①导入Spring 依赖
②创建Bean
③创建Spring核心配置文件 applicationContext.xml
④在Spring配置文件中配置Bean
⑤创建ApplicationContext对象,通过getBean方法获得Bean实例
14 BeanFactory 和 ApplicationContext 有什么区别
BeanFactory与ApplicationContext是spring核心接口,都可以当spring的容器。
BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;
ApplicationContext 面向使用Spring 框架的开发者,
- 功能上的区别
BeanFactory是Spring中最底层的接口,是IOC的核心,其功能包含了各种Bean的定义、加载、实例化,是IOC最基本的功能。
ApplicationContext接口是BeanFactory的子类,具有BeanFactory所有的功能,同时继承了MessageSource,所以提供了更完整的框架功能,资源文件访问、载入多个上下文配置文件等
- 加载方式的区别
BeanFactory是延时加载,也就是说在容器启动时不会注入bean,而是在需要使用bean的时候,才会对该bean进行加载实例化。
ApplicationContext 是在容器启动的时候,一次性创建所有的bean,所以运行的时候速度相对BeanFactory比较快。
- 创建方式的区别
BeanFactory是以编程的方式创建的。
ApplicationContext 是以声明的方式创建的。
- 注册方式的区别
BeanFactory是需要手动注册的。
ApplicationContext 是自动注册的。
5.1.15