• spring aop使用


      最近做一个数据库分离的功能,其中用到了spring aop,主要思路就是在service层的方法执行前根据注解(当然也可以根据方法名称,如果方法名称写的比较统一的话)来判断具体使用哪个库。所以想着再回头来看看aop的详细用法。

      因为spring aop的话原理涉及到动态代理,了解动态代理的可以查看我的另一篇博客:java动态代理
      这里主要学习讨论spring aop的用法和注意事项。
      AOP(Aspect Oriented Programming),即面向切面编程。我们知道在学习java的时候有一个OOP(Object Oriented Programming,面向对象编程),其中还涉及到它的一些特性:封装,继承,多态。这些其实就是定义了类本身以及类和类之间的关系。这里不再赘述。那么AOP是用在什么场合呢?
      下面的例子可以大致说明面向切面编程的一个场景,代码如下:
     1 public class User {
     2     private int age;
     3     private String name;
     4     public int getAge() {
     5         return age;
     6     }
     7     public void setAge(int age) {
     8         this.age = age;
     9     }
    10     public String getName() {
    11         return name;
    12     }
    13     public void setName(String name) {
    14         this.name = name;
    15     }
    16 }
    这里User就是一个普通的pojo类,现在假设有个需求说如果user对象为空,则进行判空处理,否则还是正常处理。这个时候有两种解决思路:一种是在每个方法里面判断,代码如下:
     1 public class User {
     2     private int age;
     3     private String name;
     4     private User user;
     5     public int getAge() {
     6         if(user == null){
     7             return 0;
     8         }
     9         return age;
    10     }
    11     public void setAge(int age) {
    12         this.age = age;
    13     }
    14     public String getName() {
    15         if(user == null){
    16             return "user is null";
    17         }
    18         return name;
    19     }
    20     public void setName(String name) {
    21         this.name = name;
    22     }
    23 }
      如果方法很多个,那么就要在每个方法里面判断user是否为空,这个比较麻烦,而且容易出错。另一种方式是面向切面。就是在执行User类方法的前面先判断,这样的话判断条件就比较集中。具体怎么判断呢?先来看一下aop的具体知识点。
      AOP它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
      使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。

    AOP核心概念

    1、横切关注点

      对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点

    2、切面(aspect)

      类是对物体特征的抽象,切面就是对横切关注点的抽象,所以切面一般对应一个类

    3、连接点(joinpoint)

      被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器

    4、切入点(pointcut)

      对连接点进行拦截的定义

    5、通知(advice)

      所谓通知指的就是拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类

    6、目标对象

      代理的目标对象

    7、织入(weave)

      将切面应用到目标对象并导致代理对象创建的过程

    8、引入(introduction)

      在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段
      单纯的记忆这些概念不好记,下面会根据具体实例来一一对号。

     Spring对AOP的支持

      Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC容器负责管理。因此,AOP代理可以直接使用容器中的其它bean实例作为目标,这种关系可由IOC容器的依赖注入提供。Spring创建代理的规则为:
    1. 默认使用Java动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了
    2. 当需要代理的类不是代理接口的时候,Spring会切换为使用CGLIB代理,也可强制使用CGLIB
    AOP编程其实是很简单的事情,纵观AOP编程,程序员只需要参与三个部分:
    1. 定义普通业务组件
    2. 定义切入点,一个切入点可能横切多个业务组件
    3. 定义增强处理,增强处理就是在AOP框架为普通业务组件织入的处理动作
      所以进行AOP编程的关键就是定义切入点和定义增强处理,一旦定义了合适的切入点和增强处理,AOP框架将自动生成AOP代理,即:代理对象的方法=增强处理+被代理对象的方法。
    使用Spring AOP,要成功运行起代码,只用Spring提供给开发者的jar包是不够的,请额外上网下载两个jar包:
    1. aopalliance.jar
    2. aspectjweaver.jar
    这里举一个简单的例子,首先定义一个接口Output:
    1 public interface Output {
    2     void out();
    3 }
    定义接口的实现类Subject:
    1 public class Subject implements Output{
    2     @Override
    3     public void out(){
    4         System.out.println("被代理对象的输出");
    5     }
    6 }
    接着定义一个切面AopAspect,切面可以看做是切入点,通知等的抽象集合。
    1 public class AopAspect {
    2     public void before() {
    3         System.out.println("方法执行前");
    4     }
    5     public void after() {
    6         System.out.println("方法执行后");
    7     }
    8 }
    然后在xml中配置如下:
    1 <bean id="subject" class="aop.Subject"></bean>
    2     <bean id="aopAspect" class="aop.AopAspect"></bean>
    3     <aop:config>
    4         <aop:aspect id="aopAspect" ref="aopAspect">
    5             <aop:pointcut id="allMethod" expression="execution(* aop.Subject.*(..))"/>
    6             <aop:before method="before" pointcut-ref="allMethod"></aop:before>
    7             <aop:after method="after" pointcut-ref="allMethod"></aop:after>
    8         </aop:aspect>
    9     </aop:config>
    其实在xml中能够更清晰的对应相应的概念:
      横切关注点:这里就是对Subject类的out()方法进行拦截,在out()方法前面执行before(),之后执行after(),这些成为横切关注点
      切面(aspect):很明显,就是AopAspect
      连接点(joinpoint):被拦截到的点,这里是一个方法,也就是out()方法
      切入点(pointcut):在哪里进行拦截,这里定义的是Sub   ject类下面的所有方法。这里有一个expression表达式来描述拦截的地方:常用的就是execution,这里的表达式的含义如下:
        
      通知(advie):拦截到连接点之后要执行的代码,这里就是before()和after()了
      目标对象:就是Subject
      织入:切面应用到目标对象,就是把切面AopAspect织入到Subject中

    使用Spring AOP的其他细节

    1、如果在加入一个切面,那么这两个切面的执行顺序是怎样的?
    1. 默认以aspect的定义顺序作为织入顺序
    2. aspect里面有一个order属性,order属性的数字就是横切关注点的顺序
    2、强制使用CGLIB生成代理
      Spring使用动态代理或是CGLIB生成代理是有规则的,高版本的Spring会自动选择是使用动态代理还是CGLIB生成代理内容,当然我们也可以强制使用CGLIB生成代理,那就是<aop:config>里面有一个"proxy-target-class"属性,这个属性值如果被设置为true,那么基于类的代理将起作用,如果proxy-target-class被设置为false或者这个属性被省略,那么基于接口的代理将起作用。
     
  • 相关阅读:
    【转】Paxos算法深入分析
    GOLANG 反射法则
    谈谈Java中整数类型(short int long)的存储方式
    大型网站架构学习笔记
    Java并发编程基础
    spring 优点
    JavaScript 中,num = num || 1 这种写法有哪些优缺点?
    javascript删除字符串最后一个字符
    javascript中字符串拼接详解
    JSONObject、JSONArray
  • 原文地址:https://www.cnblogs.com/uodut/p/6753146.html
Copyright © 2020-2023  润新知