zoukankan      html  css  js  c++  java
  • spring学习总结二-----面向切面编程(AOP)思想

    上一篇spring博客简总结了spring控制反转和依赖注入的相关思想知识点,这篇博文对spring的面向切的编程思想进行简单的梳理和总结。

    一、面向切面的思想

      与面向对象的纵向关系概念不同,面向切面体现的是一种横向的关系:即某个代码块它需要被很多个模块调用,例如安全验证类代码和日志类代码,几乎所有业务模块都必须引用这些代码块,所以这些代码块横向地穿插在各个不同模块之间,造成了代码的重复。另外,模块之间的耦合度增加,开发不同模块的程序员不能独立进行工作,而且扩展性不好。下面这个图展现了这样一种横切关系:

    下面的代码demo展示了这样一种情况:

    class User{
        //该类有个login方法
        public void login(){
            //在传统的面向对象编程中,如果login方法前需要有一个安全验证的方法,则我们直接在这里引用相应的代码
            //这里是安全验证类的代码......
            System.out.println("我是安全验证类代码,在login正式方法前必须执行");
            //下面才是正式的登录操作代码
            System.out.println("user login method");
            //然后,执行login正式代码后,我们还有可能将用户操作记录写进日志文件
            System.out.println("日志文件操作代码");
        }
    }

    显然,登录方法前后都有与登录业务关系不大的模块代码,严重影响了代码的解耦。

    所以,我们需要某种手段将横切的模块(权限,日志,事务等模块)抽取出来,然后统一地控制,而这种抽取的手段就是通过面向切面的思想来实现的。

    二、aop的一些概念

      1、横切关注点:表明我们要横切的对象方法,从什么地方开始横切,横切之后要执行说明方法。例如,上面的登录,我们的横切关注点就是:对login方法进行横切拦截操作,在方法执行前,执行我们的安全验证代码,在方法执行后,执行我们的日志方法。

      2、连接点和切入点:就是拦截到的地方。例如上面代码,连接点就是可以看成是login这个方法,我们的横切代码就是在连接点处某个状态(包括之前,之后,抛出异常等状态)开始运行的,而切入点就是具体连接点的拦截定义。

      3、通知(advice):就是我们在拦截处需要执行的具体方法,例如上面的通知就是安全验证类代码和日志类代码。

      当然,AOP中的概念这里并没有完全列举,只是列举了部分最常用的概念,想了解更多可以百度下。

     三、spring中如何面向切面(这里只讲xml配置方式,注解方式请参考其他资料)

      在将具体aop实现原理之前,让我们先通过spring这个框架,大概感受下面向切面的含义。下面的例子展示了在spring中如何面向切面;

      接着上面User类的例子,看下面的demo,注意看注释:

      首先,上java代码:

    //在User类中横切AopTest类中的方法
    class User{
        private String userName = null;
        public void setUserName(String userName) {
            this.userName = userName;
        }
    
        public void login(){
            System.out.println("user login method");
        }
    }
    //该类中含有aop的通知
    class AopTest{
        public void loginBefore(){
            System.out.println("login before method");
        }
        public void loginAfter(){
            System.out.println("login after method");
        }
    }
    //测试方法
    public class AopBlog {
        public static void main(String[] args) {
            ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml"); 
            User test = (User)appContext.getBean("userId");
            test.login();
        }
    
    }

    下面注意看spring中如何具体适用切面:

     <bean id="aopTest" class="review.blog.springRevice.AopTest"></bean>
         <bean id="userId" class="review.blog.springRevice.User">
            <property name="userName" value="UserName1"/>
        </bean>
        
         <aop:config>
             <!-- aop:aspect标签声明了织入类的信息,ref指向对应的织入类 -->
            <aop:aspect id="myAop" ref="aopTest">
                <!-- aop:pointcut标签声明了切入点,表明织入类是为该切入点服务的 -->
                <aop:pointcut id="pointCutTarget" expression="execution(* review.blog.springRevice.User.login(..))"/>
                <!-- before和after标签声明了通知执行的顺序:在切入对应方法之前(before)之后(after),当然,也可以有其他配置:例如抛出异常等 -->
                <aop:before method="loginBefore" pointcut-ref="pointCutTarget"/>
                <aop:after method="loginAfter" pointcut-ref="pointCutTarget"/>
            </aop:aspect>
          </aop:config>

    这里顺便说明切入点的命名规则,以execution (* com.sample.service.impl..*.*(..))为例

      1、execution(): 表达式主体。

       2、第一个*号:表示返回类型,*号表示所有的类型。

       3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.sample.service.impl包、子孙包下所有类的方法,当然,也可以向上面例子一样具体到某个类的方法。

       4、第二个*号:表示类名,*号表示所有的类。

       5、*(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。

      具体更详细的表达式命名规则可以参考一下这篇博客

    另外,在配置文件头部,记得引入命名空间,具体看下面截图说明:

    <beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

    运行上面代码,你会发现如下结果:

    login before method
    user login method
    login after method

    spring中aop的总结先到这里,下一篇博客将重点讲解下AOP的实现原理。

      

      

  • 相关阅读:
    在子线程中使用Toast
    时间戳与字符串的转换
    Notification小案例
    Android文件的读写操作
    SmartImageView-网络图片查看器
    JavaScript中判断对象类型的种种方法
    nodejs npm常用命令
    web前端安全机制问题全解析
    Gulp安装及配合组件构建前端开发一体化(转)
    gulp 实现 js、css,img 合并和压缩(转)
  • 原文地址:https://www.cnblogs.com/lcplcpjava/p/spring.html
Copyright © 2011-2022 走看看