对Spring框架的理解
spring 是按照设计模式精心打造的,它实现了工厂模式的工厂类,这个类名为BeanFactory(接口),在程序中通常使用它的子类ApplicationContext(也是接口)
Java EJB EE开发 spring的核心技术有:IOC,AOP,java 的 高级特性:反射机制,代理
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
控制反转——Spring通过一种称作控制反转(IoC)的技术促进了松耦合。面向切面——Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。
容器——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。
框架——Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。
所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为Spring中的各种模块提供了基础支持。
IOC和AOP的理解
Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。
控制权的转换过程,当你创建对象时,不需要有你亲自创建,你将控制权给予spring的容器对象创建,完成后容器将控制权在返回给你,降低程序之间的耦合,便于设计更好的程序。
aop是面向切面编程,语言、框架的发展都是一步步的分离、解耦的过程,来降低程序之间的依赖性和耦合性,使其达到标准、易维护、易理解、易复用等,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,java中一般会说这样的一句话:“一个方法只做一件事情”。这样易复用、易理解、易维护。但是现在很多方法无法做到只做一件事情,我们的方法除了包含业务逻辑代码外还需要加例如日志、事务等相关操作的代码或代码引用。这样我们一个方法就不是做一件事情,而是做了业务逻辑、日志、事务三件事情。于是我们想办法把日志、事务定义成一个切面,这样可以在代码需要日志和事务的时候切入程序。来达到一个方法只做一件事情的目的。
Spring是如何进行事务管理
事务就是对一系列的数据库操作(比如插入多条数据)进行统一的提交或回滚操作,如果插入成功,那么一起成功,如果中间有一条出现异常,那么回滚之前的所有操作。这样可以防止出现脏数据,防止数据库数据出现问题。开发中为了避免这种情况一般都会进行事务管理。
Spring的声明式事务通常是指在配置文件中对事务进行配置声明,其中包括了很多声明属性,它是通过Spring Proxy帮你做代理,自己不用额外的写代码,只要在Spring配置文件中声明即可;通常用在数据库的操作里面;
编程式事务就是指通过硬编码的方式做事务处理,这种处理方式需要写代码,事务中的逻辑可以自己定制;可以是数据库的东东,也可以是其他的操作。
Spring中也有自己的事务管理机制,一般是使用TransactionMananger进行管理,可以通过Spring的注入来使用此功能
Spring事务的传播特性有了解
就是对程序中运行的方法进行事务的声明和事务的处理
- PROPAGATION_REQUIRED
支持当前事务,假设当前没有事务。就新建一个事务 - PROPAGATION_SUPPORTS
支持当前事务,假设当前没有事务,就以非事务方式运行 - PROPAGATION_MANDATORY
支持当前事务,假设当前没有事务,就抛出异常 - PROPAGATION_REQUIRES_NEW
新建事务,假设当前存在事务。把当前事务挂起 - PROPAGATION_NOT_SUPPORTED
以非事务方式运行操作。假设当前存在事务,就把当前事务挂起 - PROPAGATION_NEVER
以非事务方式运行,假设当前存在事务,则抛出异常 - PROPAGATION_NESTED
如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
IoC和DI的关系
DI是对IOC具体实现,,没有DI的具体IOC何来控制反转,怎么创建对象
@Autowired 与@Resource的区别
都是对象的注入@Resource是JDK的注释,@Autowired是spring的注释,使用方法基本一样
Spring支持的几种bean的作用域,怎么配置
singleton:单例模式,在整个Spring IoC容器中,使用 singleton 定义的 bean 只有一个实例,默认也是单例模式
prototype:原型模式,每次通过容器的getbean方法获取 prototype 定义的 bean 时,都产生一个新的 bean 实例
只有在 Web 应用中使用Spring时,request、session、global-session 作用域才有效
request:对于每次 HTTP 请求,使用 request 定义的 bean 都将产生一个新实例,即每次 HTTP 请求将会产生不同的 bean 实例。
session:同一个 Session 共享一个 bean 实例。
global-session:同 session 作用域不同的是,所有的Session共享一个Bean实例。
具体配置方式
依赖注入的实现方式
设值注入
构造注入
Setter注入
目前使用最广泛的 @Autowired:自动装配
Spring Bean的生命周期
- 实例化Bean对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化。 对于ApplicationContext容器,当容器启动结束后,便实例化所有的bean。
- 设置对象属性(依赖注入)实例化后的对象被封装在BeanWrapper对象中,并且此时对象仍然是一个原生的状态,并没有进行依赖注入。 紧接着,Spring根据BeanDefinition中的信息进行依赖注入。 并且通过BeanWrapper提供的设置属性的接口完成依赖注入。
- 注入Aware接口紧接着,Spring会检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给bean。
- BeanPostProcessor当经过上述几个步骤后(前置处理),bean对象已经被正确构造, 之后这个函数会在InitialzationBean完成后执行,因此称为后置处理。
- InitializingBean与init-method当BeanPostProcessor的前置处理完成后就会进入这个阶段。 InitializingBean接口只有一个函数:afterPropertiesSet()这一阶段也可以在bean正式构造完成前增加我们自定义的属性或者操作。
- DisposableBean和destroy-method和init-method一样,通过给destroy-method指定函数,就可以在bean销毁前执行指定的逻辑。
spring自动装配
- no:不启用自动装配。Autowire的默认值
- byName:根据属性名自动装配。这个属性会根据名字查找与属性一样的bean,并将其自动装配。
- byType:根据属性的类型查找JavaBean依赖注入的对象为其注入。如果容器中存在一个属性类型相同的bean,那么就会进行自动装配。如果有多个则会抛出异常。
- constructor:跟byType的方式类似,区别在于它不是用set方法注入,而是使用构造方法进行子注入。如果在容器中没有找到相同的bean就会抛出异常
- autodetect:通过bean类自省机制(introspection)来决定是使用constructor还是byType方式进行自动装配。如果发现是默认的构造器,就是用byType。
- default:由上级标签的default-autowire属性确定。
注意:在配置bean时,标签中Autowire属性的优先级比其上级标签高,即是说,如果在上级标签中定义default-autowire属性为byName,而在中定义为byType时,Spring IoC容器会优先使用标签的配置。
在Spring中怎么启用注解?
使用组件扫描器
<context:component-scan base-package=""> </context:component-scan>配置。
BeanFactory和ApplicationContext有什么区别
BeanFactory:
是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能;
BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化;所以相对于ApplicationContext速度慢,但是堆内存的消耗小。
ApplicationContext:
应用上下文,继承BeanFactory接口,它是Spring的一各更高级的容器,提供了更多的有用的功能;
ApplicationContext在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化; 速度快,但是内存的消耗大。
Spring支持的事务管理类型
• 编程式事务管理,在代码中@TransationManager显式调用开启事务、提交事务、回滚事务的相关方法
• 声明式事务管理,底层是建立在 AOP 的基础之上。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务
Spring AOP中什么是切面,关注点,通知,切入点,连接点,目标对象,代理对象,织入
(1 ) 切面(Aspect )
切面泛指交叉业务逻辑。上例中的事务处理、日志处理就可以理解为切面。常用的切面
是通知(Advice)。实际就是对主业务逻辑的一种增强。
(2 ) 连接点(JoinPoint )
连接点指可以被切面织入的具体方法。通常业务接口中的方法均为连接点。
(3 ) 切入点(Pointcut )
切入点指声明的一个或多个连接点的集合。通过切入点指定一组方法。
被标记为 final 的方法是不能作为连接点与切入点的。因为最终的是不能被修改的,不
能被增强的。
切入点表达式:
execution ( [modifiers-pattern] 访问权限类型
ret-type-pattern 返回值类型
[declaring-type-pattern] 全限定性类名
name-pattern(param-pattern)方法名(参数类型和参数个数)
[throws-pattern] 抛出异常类型
)
例如:execution(* com.xyz.service..*.*(..))
指定切入点为:定义在 service 包或者子包里的任意类的任意方法。“…”出现在类名中时,后
面必须跟“*”,表示包、子包下的所有类。
(4 ) 目标对象(Target )
目标对象指将要被增强的对象。即包含主业务逻辑的类的对象。上例中的
StudentServiceImpl 的对象若被增强,则该类称为目标类,该类对象称为目标对象。当然,
不被增强,也就无所谓目标不目标了。
(5 ) 通知(Advice )
通知是切面的一种实现,可以完成简单织入功能(织入功能就是在这里完成的)。Advice
也叫增强。上例中的 MyInvocationHandler 就可以理解为是一种通知。换个角度来说,通知
定义了增强代码切入到目标代码的时间点,是目标方法执行之前执行,还是之后执行等。通
知类型不同,切入时间不同。切入点定义切入的位置,通知定义切入的时间。
(1)前置通知@Before 前置通知- 方法有 JoinPoint 参数不光前置通知的方法,可以包含一个 JoinPoint 类型参数,所有的通知方法均可包含该
参数。
(2)后置通知@AfterReturning 后置通知- 注解有 returning 属性该变
量最好为 Object 类型,因为目标方法的返回值可能是任何类型。不能更改程序的返回值
(3)环绕通知 @Around 环绕通知- 增强方法有 ProceedingJoinPoint 参数则该方法的返回值就是目标方法的返回值。最后,环绕增强方法将其返回值返回。该增强方法实际是拦截了目标方法的执行。可以更改程序的返回值
(4)异常通知@AfterThrowing 异常通知- 注解中有 throwing 属性包含一个参数 Throwable,参数名称为 throwing 指定的名称,表示发生的异常对象。
(5)最终通知@After 最终通知,无论目标方法是否抛出异常,该增强均会被执行
Spring框架中的单例bean是否是线程安全
因为是单例,某种一样上来说是安全的,但是当你多线程访问单例对象是可能就会涉及到线程安全的问题,即对象共享的问题,可以用prototype变成多例不会出现资源共享的问题。