Spring AOP

    Spring是分层的java SE/EE应用的一站式的开源框架,以控制反转(Inverse of Control,IoC)和面向切面编程(Aspect Oriented Programming,AOP)为核心,提供了表现层spring MVC,持久层spring JDBC以及业务层事务管理等众多的企业级应用技术。Spring一贯遵守“好的设计优于具体实现,代码应该易于测试”这一理念。相对于传统的“所有的企业应该采用统一的标准”,Spring采用了业务驱动的模型,通过Spring提供的IOC容器,可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的程序过度依赖,更加关注上层的业务的处理。通过Spring提供的AOP功能,用户可以方便的进行面向切面编程,许多不容易使用面向对象编程(OOP)实现的功能都可以通过AOP轻松实现。

    所谓依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中。当spring容器启动后,spring容器初始化,创建并管理bean对象,以及销毁它。所以我们只需从容器直接获取Bean对象就行,而不用编写一句代码来创建bean对象。这种现象就称作控制反转,即应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的,在Spring中有一个BeanFactory,负责对象的创建。这样控制权就由应用转移到了外部容器,控制权的转移就是所谓反转。Spring中主要有两种方式实现依赖注入:属性注入和构造器注入。

    AOP(Aspect Oriented Programming),即面向切面编程,他是软件开发思想中的一个重大变革。虽让OOP已经让我们很好的用对象描述了这个世界,但是还是有很多问题,是不能使用抽取基类(公共的方法),子类继承基类的模式来完成自身业务逻辑,比如,业务中的事务处理,事务处理的逻辑会错综复杂的和业务逻辑纠缠在一起,很难使用OOP的思想构建出一个模型来解决这个问题,AOP正式用来解决这类问题的,他是OOP的一个极大补充。

    AOP是基于IoC的,AOP将应用系统分为两部分,核心业务逻辑(Core business concerns)及横向的通用逻辑,也就是所谓的方面/切面(Aspect)。如下如所示:


          AOP只是OOP的一个有益补充,所以一般只适用于具有横切逻辑的场合,就如上图所示的,可以将之前的业务横向抽取为核心业务逻辑和横切逻辑。只要将问题模型化,就可以使用AOP了,AOP主要解决的问题就是如何将独立的横切逻辑融合到业务逻辑中,使得现在完成的任何和之前的一样。

    AOP中有很多概念,将会对理解Spring AOP有重要的意义。

    连接点(Joinpoint):程序执行的某个特定位置,如类的初始化前、后,某个方法调用的前、后,方法抛出异常后。它是一个类或程序代码中具有便捷性质的一些特定点。Spring仅支持方法的连接点,即仅能在方法调用前、后,方法抛出异常这些连接点上织入增强,连接点包含两个信息:用方法表示的程序执行点和相对点表示的方位(前、后)。Spring使用切点对执行点进行定位,而方位则在增强类型中定义。

    切点(Pointcut):指定一个增强(通知)将被引发的一系列连接点的集合。切点只是定位到某个特定的方法上。切点也称为切入点。

    增强(Advice):增强是织入连接点的一段程序代码。在Spring中,增强除了描述一段程序代码外,还拥有切入点的方位信息,也就是说结合方位信息和切点信息,就可以找到特定的特定的连接点,就可以对目标对象进行织入增强了。由于Spring的增强既包含了添加到连接点的逻辑代码,又包含了定位连接点的方位信息,所以Spring提供的增强接口都是带方位名的:BeforeAdvice(表示方法调用前的位置)、AfterReturningAdvice(表示调用返回前的位置)以及ThrowsAdvice(表示方法抛出异常的位置)等。所以只有结合切点和增强才能确定特定的连接点并实施增强逻辑。增强也成为通知。

    目标对象(Target):增强逻辑的目标织入类,也就是连接点的类。也被称作被通知或被代理对象。

引入(Introduction):添加方法或字段到被增强(通知)的类。Spring允许引入新的接口到任何被增强的对象。例如,你可以使用一个引入使任何对象实现IsModified接口,来简化缓存。

    织入(Weaving):织入是将增强添加到具体连接点上的过程。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。

    代理(Proxy):它是融合了增强逻辑和原类的代理类。代理类既可以和原类有相同的接口,也可以是原类的子类,所以可以采用调用原类一样的接口来调用代理类。

    切面(Aspect):切面由切点和增强(引入)组成,他既包含了横切逻辑的定义,也包含了连接点的定义。Spring AOP就是负责实施切面的框架,他将切面定义的横切逻辑织入切面所指定的连接点。


             如上图所示,AOP 实际上是由目标类的代理类实现的。AOP 代理其实是由 AOP 框架动态生成的一个对象,该对象可作为目标对象使用。AOP 代理包含了目标对象的全部方法,但 AOP 代理中的方法与目标对象的方法存在差异,AOP 方法在特定切入点添加了增强处理,并回调了目标对象的方法。


    下面通过一个例子来说明面向切面编程。

应用场景:一个服务生的工作有两个:欢迎顾客和为顾客服务。为了使服务生更加有礼貌,必须强制在服务之前说一些客套的礼貌用语。

    下面是服务生工作的接口和实现类:

   /**
    * Created by raiet on 2014/6/13.
    */
   
   public interface Waiter {
       void greetTo(String name);
       void serveTo(String name);
   }
   /**
    * Created by raiet on 2014/6/13.
    */
   public class MyWaiter implements Waiter {
   
       public void greetTo(String name) {
           System.out.println("greet to " + name + "......");
       }
   
       public void serveTo(String name) {
           System.out.println("serve to " + name + "......");
       }
   }

下面是对目标对象的增强逻辑:

   /**
    * Created by raiet on 2014/6/13.
    */
   public class GreetBeforeAdvice implements MethodBeforeAdvice {
       //在目标方法调用前执行
       public void before(Method method, Object[] args, Object o) throws Throwable {
           String name = (String) args[0];
           System.out.println("How are you! Mr. " + name + ".");
       }
   }

修改配置文件:通过ProxyFactoryBean配置代理

 

   <!--定义增强,Spring的增强其实就是通过拦截器实现的 -->
   <bean id = "greetAdvice" class = "hust.advice.GreetBeforeAdvice"/>
   <!--需要代理的目标类 -->
   <bean id = "target" = "hust.impl.MyWaiter"/>
   <!--通过 ProxyFactoryBean生成代理类-->
   <bean id = "waite" = class = "org.springframework.aop.framework.ProxyFactoryBean"
       <!-- 指定代理的接口-->
       p:proxyInterface="hust.Waiter"
       <!--指定使用的增强,也就是拦截器 -->
       p:interceptorNames="greetAdvice"
       <!--指定对哪个bean进行代理 -->
       p:target-ref="target"
       />

      ProxyFactoryBean负责为其他的bean创建实例,他的内部使用ProxyFactory来完成这一工作。通过生成的代理对象,代替原始类进行工作,也就实现了在业务中织入横切逻辑的功能。

    Spring中的事务管理也是基于AOP实现的,他将繁琐的事务处理的代码横向抽出为横切逻辑,将执行事务的service方法作为切入点,织入事务事务逻辑,就和上面的例子的实现逻辑一样。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值