Java轻量级业务层框架Spring两大核心IOC和AOP原理

时间:2023-12-31 18:05:32

IoC(Inversion of Control):

  IOC的基本概念是:不创建对象,但是描述创建它们的方式。在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。容器负责将这些联系在一起。   

其原理是基于OO设计原则的The Hollywood Principle:Don't call us, we'll call you(别找我,我会来找你的)。也就是说,所有的组件都是被动的(Passive),所有的组件初始化和调用都由容器负责。组件处在一个容器当中,由容 器负责管理。   

简单的来讲,就是由容器控制程序之间的关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。

(1)IoC(Inversion of Control)是指容器控制程序对象之间的关系,而不是传统实现中,由程序代码直接操控。控制权由应用代码中转到了外部容器,控制权的转移是所谓反转。对于Spring而言,就是由Spring来控制对象的生命周期和对象之间的关系;IoC还有另外一个名字——“依赖注入(Dependency Injection)”。从名字上理解,所谓依赖注入,即组件之间的依赖关系由容器在运行期决定,即由容器动态地将某种依赖关系注入到组件之中。

(2)在Spring的工作方式中,所有的类都会在spring容器中登记,告诉spring这是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。

(3)在系统运行中,动态的向某个对象提供它所需要的其他对象。

(4)依赖注入的思想是通过反射机制实现的,在实例化一个类时,它通过反射调用类中set方法将事先保存在HashMap中的类属性注入到类中。

总而言之,在传统的对象创建方式中,通常由调用者来创建被调用者的实例,而在Spring中创建被调用者的工作由Spring来完成,然后注入调用者,即所谓的依赖注入or控制反转。

注入方式有两种:依赖注入和设置注入;

IoC的优点:降低了组件之间的耦合,降低了业务对象之间替换的复杂性,使之能够灵活的管理对象。

AOP(Aspect Oriented Programming):

  AOP即Aspect-Oriented Programming的缩写,中文意思是面向切面编程,也有译作面向方面编程的,因为Aspect有“方面、见地”的意思。AOP实际上是一种编程思 想,由Gregor Kiczales在Palo Alto研究中心领导的一个研究小组于1997年提出[1]。在传统的面向对象(Object-Oriented Progr amming,OOP)编程中,对垂直切面关注度很高,横切面关注却很少,也很难关注。也就是说,我们利用OOP思想可以很好的处理业务流程,却不能把系 统中的某些特定的重复性行为封装在某个模块中。比如在很多的业务中都需要记录操作日志,结果我们不得不在业务流程种嵌入大量的日志记录代码。无论是对业务 代码还是对日志记录代码来说,今后的维护都是非常复杂的。由于系统种嵌入了这种大量的与业务无关的其它重复性代码,系统的复杂性、代码的重复性增加了,从 而使bug的发生率也大大的增加。

在OOP面向对象编程中,我们总是按照某种特定的执行顺序来实现业务流程,各个执行步骤之间是相互衔接、相互耦合的。比如某个对象抛出了异常,我们就必须 对异常进行处理后才能进行下一步的操作;又比如我们要把一个学生记录插入到教务管理系统的学生表中去,那么我们就必须按照注册驱动程序、连接数据库、创建 一个statement、生成并执行SQL语句、处理结果、关闭JDBC对象等步骤按部就班的编写我们的代码。可以看到上面的步骤种除了执行SQL和处理 结果是我们业务流程所必须的外,其它的都是重复的准备和殿后工作,与业务流程毫无关系,另外我们还得要考虑程序执行过程中的异常。天!我们只是需要向一张 表中插入数据而已,可是却不得不和这些大量的重复代码纠缠在一起,我们不得不把大量的精力用在这些代码上而无法专心的设计业务流程。

那么什么可以解决这个问题呢?这时候,我们需要AOP,关注系统的“截面”,在适当的时候“拦截”程序的执行流程,把程序的预处理和后处理交给某个拦截器 来完成。比如在操作数据库时要记录日志,如果使用AOP的编程思想,那么我们在处理业务流程时不必再考虑日志记录,而是把它交给一个特定的日志记录模块去 完成。这样,业务流程就完全的从其它无关的代码中解放出来,各模块之间的分工更加明确,程序维护也变得容易多了。

正如上所说,AOP不是一种技术,而是编程思想。凡是符合AOP思想的技术,都可以看成是AOP的实现。目前的AOP实现有AspectJ、 JBoss4.0、nanning、spring等项目。其中Spring对AOP进行了很好的实现,同时Spring AOP也是Spring的两大核心之一。

下面介绍一些关于AOP的一些概念,如果觉得有些晦涩,也可以先不必仔细关注。

连接点(join point):它是指应用中执行的某个点,即程序执行流程中的某个点。如执行某个语句或者语句块、执行某个方法、装载某个类、抛出某个异常……,如下:

  1. public   static   void  main(String[] args)  throws  Exception {
  2. int  i =  0 ;
  3. i++;
  4. CallMyMethod();
  5. throw   new  Exception( "哈哈,一个异常!" );
  6. }

注意:这里每一个语句都可以被称作一个连接点。
      连接点是有“强弱”的,这种强弱可以用“粒度”来表示,Spring AOP支持到方法级的连接点粒度。

切入点(pointcut): 切入点是连接点的集合,它通常和装备联系在一起,是切面和程序流程的交叉点。比如说,定义了一个pointcut,它将抛出异常ClassNotFoundException和某个装备联系起来,那么在程序执行过程中,如果抛出了该异常,那么相应的装备就会被触发执行。

 装备(advice): 也可以叫做“通知”,指切面在程序运行到某个连接点所触发的动作。在这个动作种我们可以定义自己的处理逻辑。装备需要利用切入点和连接点联系起来才会被触 发。目前AOP定义了五种装备:前置装备(Before advice)、后置装备(After advice)、环绕装备(Around Advice)、异常装备(After throwing advice)、返回后装备(After returning advice)。这些装备以后会逐一介绍。

目标对象(target object): 被一个或者多个切面装备的对象。所以它有时候也被称为Advised Object。

引入(introduction): 声明额外的成员字段或者成员方法。它可以给一个确定的对象新增某些字段或者方法。

  织入(weaving): 将切面和目标对象联系在一起的过程。这个过程可以在编译期完成,也可以在类加载时和运行时完成。Spring AOP是在运行期完成织入的。

切面(aspect): 一个关注点的模块化。它实际上是一段将被织入到程序流程中的一段代码。

  (1)AOP面向方面编程基于IoC,是对OOP的有益补充;

(2)AOP利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,比如日志记录,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。

(3)AOP代表的是一个横向的关系,将“对象”比作一个空心的圆柱体,其中封装的是对象的属性和行为;则面向方面编程的方法,就是将这个圆柱体以切面形式剖开,选择性的提供业务逻辑。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹,但完成了效果。

(4)实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。

(5)Spring实现AOP:JDK动态代理和CGLIB代理

JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理;其核心的两个类是InvocationHandler和Proxy。

CGLIB代理:实现原理类似于JDK动态代理,只是它在运行期间生成的代理对象是针对目标类扩展的子类。CGLIB是高效的代码生成包,底层是依靠ASM(开源的java字节码编辑类库)操作字节码实现的,性能比JDK强;需要引入包asm.jar和cglib.jar。

使用AspectJ注入式切面和@AspectJ注解驱动的切面实际上底层也是通过动态代理实现的。

(6)AOP使用场景:

Authentication 权限检查

Caching 缓存

Context passing 内容传递

Error handling 错误处理

Lazy loading 延迟加载

Debugging  调试

logging, tracing, profiling and monitoring 日志记录,跟踪,优化,校准

Performance optimization 性能优化,效率检查

Persistence  持久化

Resource pooling 资源池

Synchronization 同步

Transactions 事务管理

另外Filter的实现和struts2的拦截器的实现都是AOP思想的体现。

总结:

 (1)spring有以下的优点:     

  1.降低了组件之间的耦合性 ,实现了软件各层之间的解耦

  2.可以使用容易提供的众多服务,如事务管理,消息服务等

  3.容器提供单例模式支持

  4.容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能

  5.容器提供了众多的辅助类,能加快应用的开发

  6.spring对于主流的应用框架提供了集成支持,如hibernate,JPA,Struts等

  7.spring属于低侵入式设计,代码的污染极低

  8.独立于各种应用服务器

  9.spring的DI机制降低了业务对象替换的复杂性

  10.Spring的高度开放性,并不强制应用完全依赖于Spring,开发者可以*选择spring的部分或全部

 (2)AOP可以动态的添加或者删除在切面上的逻辑而不影响原来代码的执行,体现了源代码无关性。