一、 IOC
1、如果合作对象的引用或依赖关系的管理由具体对象来完成,会导致代码的高度耦合和可测试性的降低。使用ioc容器则可降低组件之间依赖,更容易维护和可测试。
2、spring ioc的两种容器:BeanFactory接口的简单容器系列,实现了最基本的功能;ApplicationContext应用上下文,作为容器的高级形态而存在。
3、spring通过定义BeanDefinition来管理基于Spring的应用中各种对象以及他们之间的互相依赖关系。
看看ioc容器接口设计:
4、Ioc容器初始化过程:BeanDefinition的Resource定位、载入和注册。
以注解注入为例,Spring根据xml配置的路径来扫描类(资源定位),如果发现类的上方有类似@Service,@Controller,此时就会定位到当前类,解析并转换为BeanDefinition的数据结构(载入),之后将BeanDefinition put进BeanDefinitionMap<String, BeanDefinition>(注册),此时也就完成了IOC的初始化工作。
5、IOC容器的依赖注入,其实是在getBean时触发,即getBean是依赖注入的起点,之后会调用createBean,Bean对象会依据BeanDefinition的要求生成。createBean不但生成了需要的Bean,还对Bean初始化进行了处理。SimpleInstantiationStrategy类是Spring用来生成Bean对象的默认类,提供了两种实例化对象的方法,一种是BeanUtils,它使用了JVM的反射功能,另一种是ReflectionUtils,它使用了CGLIB(是一个常用的字节码生成器的类库,它提供了一系列API来提供生成和转换java字节码功能)来生成。对Bean的属性进行注入时,解析过程是一个递归的过程,根据依赖关系,一层一层地完成Bean的创建和注入,直到最后完成当前Bean的创建。
6、Ioc容器中Bean的生命周期:①Bean实例的创建②为Bean实例设置属性③调用Bean的初始化方法④应用通过IOC容器使用Bean⑤当容器关闭时,调用Bean的销毁方法。
7、ApplicationContext实现的默认行为就是在启动服务器时将所有singleton bean提前进行实例化(也就是依赖注入)。提前实例化意味着作为初始化过程的一部分,applicationContext实例会创建并配置所有的singleton bean。lazy-init="false"立即加载,表示在spring启动时,立刻进行实例化。设置为true,才会在getBean时加载实例。
8、FactoryBean为应用生成所需要的对象,类似于AbstractFactory工厂,具体的FactoryBean实现,可以生成特定的bean。
二、AOP
1、AOP是Aspect-Oriented Programming的简称,即面向切面编程。Spring AOP使用纯java实现,在运行期通过代理方式向目标类织入增强代码。AspecJ是一个基于Java语言的AOP框架,Spring2.0开始,Spring AOP引入对AspectJ的支持。
2、AOP的术语
Joinpoint(连接点):指被拦截的点,spring只支持方法类型的连接点。
Pointcut(切入点):指对哪些Joinpoint进行拦截的定义,例如,定义在方法上,对该方法进行拦截,定义在类上,对该类实例所有方法进行拦截。
Advice(通知/增强):拦截到Joinpoint点后,要做的处理(通知)。可分为前置通知、后置通知、异常通知、环绕通知。
Instroduction(引介):一种特殊的通知,在不修改类代码的前提下,可以在运行期的类动态添加一些方法或属性。
Target(目标对象):要被代理的目标对象。
Weaving(织入):指把增强应用到目标对象来创建新的代理对象的过程。Spring采用动态代理织入,AspectJ采用编译期织入和类装载期织入。
Proxy(代理):一个类被AOP增强后,产生的代理类。
Aspect(切面):切入点和通知的结合。
3、简单实现
4、自定义Aop注解包装业务异常
三、事务
1、Spring的事务机制主要包括声明式事务和编程式事务。声明式事务是通过AOP功能来实现,通过AOP的拦截功能,将事务处理的功能编织出来。
如图所示,insertThenRollback在添加Transactional注解后,会被AOP拦截,增强方法功能,而invokeInsertThenRollback方法本身没有添加事务,内部方法调用,之前的事务不会生效。
通过以上三种方式,可使内部方法调用添加上事务。
2、Transactional注解:
3、七种事务传播行为:
PROPAGATION_REQUIRED:默认传播行为,如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
PROPAGATION_REQUIRES_NEW:表示当前方法必须运行在它自己的事务中。一个新的事务将启动,而且如果有一个现有的事务在运行的话,则这个方法将在运行期被挂起,直到新的事务提交或者回滚才恢复执行。
PROPAGATION_SUPPORTS:表示当前方法不必需要具有一个事务上下文,但是如果有一个事务的话,它也可以在这个事务中运行
PROPAGATION_NOT_SUPPORTED:表示该方法不应该在一个事务中运行。如果有一个事务正在运行,他将在运行期被挂起,直到这个事务提交或者回滚才恢复执行
PROPAGATION_MANDATORY:表示当前方法必须在一个事务中运行,如果没有事务,将抛出异常
PROPAGATION_NEVER:表示当前方法不应该在一个事务中运行,如果存在一个事务,则抛出异常
PROPAGATION_NESTED:表示如果当前方法正有一个事务在运行中,则该方法应该运行在一个嵌套事务中,被嵌套的事务可以独立于被封装的事务中进行提交或者回滚。如果封装事务存在,并且外层事务抛出异常回滚,那么内层事务必须回滚,反之,内层事务并不影响外层事务。如果封装事务不存在,则同PROPAGATION_REQUIRED的一样
4、五种事务隔离级别:
ISOLATION_DEFAULT:默认隔离级别,表示使用底层数据库的默认隔离级别
.ISOLATION_READ_UNCOMMITTED:无隔离级别,会出现脏读,即事务A读取了事务B执行过程中的数据,事后事务B回滚操作,事务A就形成了脏读。
ISOLATION_READ_COMMITTED:一个事务只能读取另一个事务的提交内容。会出现不可重复读,即事务A、B都获取一个数据,事务B修改了数据,事务A发现当前数据与数据库数据不一致。
ISOLATION_REPEATABLE_READ:表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回相同,做到锁行。不能防止幻读。
ISOLATION_SERIALIZABLE:锁表
6、readOnly:是否是一个只读事务,数据库可利用只读特性采取某些优化措施。同时对可能启动一个新的事务传播行为(PROPAGATION_REQUIRES_NEW、PROPAGATION_REQUIRED、 ROPAGATION_NESTED),只读才有意义。
参考:
《Spring 技术内幕》
网友评论