Bootstrap

Spring的AOP与IOC原理

一、IOC(Inversion of Control):控制反转

传统模式下使用类的方法与属性,我们需要new出这个类的对象,然后使用对象进行方法调用,这种方法耦合度极高,为了降低耦合度,Spring提供了IOC控制反转机制,Spring帮助我们来创建对象就是我们所说的bean,并且管理bean对象,当我们需要用的时候,需要Spring提供给我们创建好的bean对象。这样就从之前我们的主动创建对象变为了,由Spring来控制创建对象,来给我们使用,也就是控制反转的意思。

IOC,控制反转(Inversion of Control),亦可以称为依赖注入(Dependecy Injection)。当某个角色需要另外一个角色协助的时候,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在spring中 创建被调用者的工作不再由调用者来完成,因此称为控制反转。创建被调用者的工作由spring来完成,然后注入调用者因此也称为依赖注入。

IOC意为控制反转,究竟“什么控制被反转了?”,经过详细地分析和论证后Martin Fowler得出了答案:“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入。于是,他给“控制反转”取了一个更合适的名字叫做"依赖注入(Dependency Injection)"。与此同时,他的这个答案也给出了实现IOC的方法:注入。

所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。所以,依赖注入(DI)和控制反转(IOC)是从不同的角度的描述的同一件事情,就是指通过引入IOC容器,利用依赖关系注入的方式,实现对象之间的解耦

IOC并不是一种技术实现,而是一种设计思想。在任何一个有实际开发意义的程序项目中,我们会使用很多类来描述它们特有的功能,并且通过类与类之间的相互协作来完成特定的业务逻辑。这个时候,每个类都需要负责管理与自己有交互的类的引用和依赖,代码将会变的异常难以维护和极度的高耦合。而IOC的出现正是用来解决这个问题,我们通过IOC将这些相互依赖对象的创建、协调工作交给Spring容器去处理,每个对象只需要关注其自身的业务逻辑关系就可以了。在这样的角度上来看,获得依赖的对象的方式,进行了反转,变成了由spring容器控制对象如何获取外部资源

Spring以动态灵活的方式来管理对象 , 注入的两种方式,设置注入和构造注入。 

设置注入的优点:直观,自然

构造注入的优点:可以在构造器中决定依赖关系的顺序。 

二、Aop(Aspect-Oriented Programming):面向切面编程

文档原文:

Aspect-oriented Programming (AOP) complements Object-oriented Programming (OOP) by providing another way of thinking about program structure. The key unit of modularity in OOP is the class, whereas in AOP the unit of modularity is the aspect. Aspects enable the modularization of concerns (such as transaction management) that cut across multiple types and objects. (Such concerns are often termed “crosscutting” concerns in AOP literature.)

Aspect-Oriented Programming,面向切面编程。可以理解为OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟抓取公共行为的一个集合。OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting)AOP利用一种称为"横切"的技术,不再纵向关注对象,而是从横向视角直接剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

使用"横切"技术,AOP把软件系统分为两个部分:核心关注点横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来

AOP应用场景:

Authentication 权限              Caching        缓存              Context passing 内容传递               Error handling 错误处理

Lazy loading 懒加载          Debugging    调试               Persistence  持久化                   Resource pooling 资源池

logging,tracing, profiling and monitoring 记录跟踪 优化 校准                         Performance optimization 性能优化

Synchronization 同步         Transactions 事务

AOP Concepts:

Pointcut:切点即在哪个地方进行切入,它可以指定某一个点,也可以指定多个点。比如类A的methord函数,当然一般的AOP与语言(AOL)会采用多用方式来定义PointCut,比如说利用正则表达式,可以同时指定多个类的多个函数。

Advice:在切入点干什么,指定在PointCut地方做什么事情(增强),打日志、执行缓存、处理异常等等。一个切面在什么时候需要完成什么样的功能,很明显advice的实现不是由框架来完成,而是由用户创建好advice然后注册到框架中,让框架在适当的时候使用它。SpringAOP中有before,after,afterReturning,afterThrowing,around

Aspect:切面.PointCut + Advice 形成了切面Aspect,这个概念本身即代表切面的所有元素。但到这一地步并不是完整的,因为还不知道如何将切面植入到代码中,解决此问题的技术就是Proxy

AOP proxy:由AOP框架创建的对象,用于实现切面协定(比如advise method executions )。 在Spring Framework中,AOP代理是JDK动态代理(基于接口)或CGLIB代理(基于子类)。

Join Points:连接点表示可以被选择用来增强的位置,连接点是一组集合,在程序运行中的整个周期中都存在

Weaving: linking aspects with other application types or objects to create an advised object. This can be done at compile time (using the AspectJ compiler, for example), load time, or at runtime. Spring AOP, like other pure Java AOP frameworks, performs weaving at runtime.将切面应用到目标对象并在此过程中进行创建代理对象

Spring AOP:Spring中的AOP代理离不开Spring的IOC容器.代理的生成,管理及其依赖关系都是由IOC容器负责,Spring默认使用JDK动态代理,在需要代理类而不是代理接口的时候,Spring会自动切换为使用CGLIB代理,现在的项目都是面向接口编程,所以JDK动态代理居多。

AOP编程中开发者只需要关注实现三个部分:

  1. 定义普通业务组件
  2. 定义切入点pointcut,一个切入点可能横切多个业务组件
  3. 定义增强处理advice,增强处理就是在AOP框架为普通业务组件织入的处理动作

所以进行 AOP 编程的关键就是定义切入点和定义增强处理。一旦定义了合适的切入点和增强处理,AOP 框架将会自动生成 AOP 代理,即:代理对象的方法 = 增强处理 + 被代理对象的方法

Spring AOP includes the following types of advice:

  • Before:在目标方法被调用之前做增强处理,@Before只需要指定切入点表达式即可
  • After Returning:在目标方法正常完成后做增强,@AfterReturning除了指定切入点表达式后,还可以指定一个返回值形参名returning,代表目标方法的返回值
  • After Throwing:主要用来处理程序中未处理的异常,@AfterThrowing除了指定切入点表达式后,还可以指定一个throwing的返回值形参名,可以通过该形参名来访问目标方法中所抛出的异常对象
  • After:在目标方法完成之后做增强,无论目标方法是否成功完成。@After可以指定一个切入点表达式
  • Around:环绕通知,在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint,调用ProceedingJoinPoint的proceed()方法才会执行目标方法。

 

参考:

Spring3.0 AOP 详解

Spring-aop 全面解析(从应用到原理)

Spring-framework-Core Technologies

Spring的IOC原理

深入理解Spring的两大特征(IOC和AOP)

;