一. AOP与@AspectJ

AOP 是 Aspect Oriented Programming 的缩写,意思是面向方面的编程。我们在系统开发中可以提取出很多共性的东西作为一个 Aspect,可以理解为在系统中,我们需要很多次重复实现的功能。比如计算某个方法运行了多少毫秒,判断用户是不是具有访问权限,用户是否已登录,数据的事务处理,日志记录等等。

AOP的术语

  • 连接点(Joinpoint)

程序执行的某个特殊位置:比如类开始初始化前,类初始化后,某个方法调用前,调用后等。 连接点 可 以 理解为AOP向目标类织入代码的地方。

  • 切点(Pointcut)

每一个类都有许多的连接点,所以AOP通过切点来定位特定的连接点。可以通过数据库查询的概念来理解切点和连接点的关系:连接点相当于数据库中的记录,而切点就是查询条件。切点和连接点不是一对一的关系,一个切点可以匹配多个连接点。

  • 增强(Advice)

增强就是织入到目标类连接点上的一段代码。它既包含了添加到目标连接点上的一段执行逻辑,也包含了用于定位连接点的方位信息。

AspectJ是语言级的AOP实现,它扩展了AOP的语法,能够在编辑提供横切代码的织入。@AspectJ是AspecJ1.5新增的功能,它通过JDK5.0的注解技术,允许开发者在POJO中定义切面。

二. 自定义注解

因为@AspectJ是基于JDK5.0的注解技术实现,所以我们有必要了解一下注解相关的知识,并学习如何自定义一个注解。

注解(Annotation)是代码的附属信息,它可以用来修饰类,属性,方法,同时它遵循一个基本原则,注解不能直接干扰程序代码的运行,无论是增加或者删除注解,代码都能正常运行。

(1)一个简单的注解类

Java规定使用@interface修饰定义的注解类。一个注解类可以拥有多个成员,成员声明和接口方法声明类似。

   1: package com.wbl.aop;

   2:  

   3: import java.lang.annotation.ElementType;

   4: import java.lang.annotation.Retention;

   5: import java.lang.annotation.RetentionPolicy;

   6: import java.lang.annotation.Target;

   7:  

   8: /**

   9:  * Created by Lulala on 2015/7/15.

  10:  */

  11: @Retention(RetentionPolicy.RUNTIME)         //声明注解的保留期限

  12: @Target(ElementType.METHOD)                 //声明可以使用该注解的目标类型

  13: public @interface UserAccessAnnotation {    //定义注解

  14:     ACCESS value() default ACCESS.LOOK;     //声明注解成员

  15: }

三. @AspectJ的使用

Spring采用AspectJ提供的@AspectJ注解类库及相应的解析库,所以需要在项目中导入aspectjweaver.jar类包。

(1)定义一个切面

   1: import org.aspectj.lang.annotation.Aspect;

   2: import org.aspectj.lang.annotation.Before;

   3: @Aspect         //通过注解将AspectTest标识为一个切面                    

   4: public class AspectTest{

   5:     @Before("execution(* set(..))")                //定义切点和增强类型

   6:     public void before(){                        //增强的横切逻辑

   7:         System.out.println("Aspect before");

   8:     }

   9: }

首先,在AspectTest类的定义处,标注了一个@Aspect的注解,表示这个类是一个切面,其次在before方法定义处,标注了@Before注解,并为该注解提供了成员值"execution(* set(..))"。@Before注解表示该增强是前置增强,成员值是一个切点表达式,表示在目标类的set方法上织入增强。

(2)通过配置使用@AspectJ切面

   1: <beans xmlns="http://www.springframework.org/schema/beans"

   2:        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

   3:        xmlns:p="http://www.springframework.org/schema/p"

   4:        xmlns:context="http://www.springframework.org/schema/context"

   5:        xmlns:aop="http://www.springframework.org/schema/aop"

   6:        xsi:schemaLocation="http://www.springframework.org/schema/beans

   7:                 http://www.springframework.org/schema/beans/spring-beans.xsd

   8:                 http://www.springframework.org/schema/context

   9:                 http://www.springframework.org/schema/context/spring-context-3.0.xsd

  10:                 http://www.springframework.org/schema/aop

  11:                 http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

  12:  

  13:         <aop:aspectj-autoproxy/>

  14:         <bean class="com.wbl.AspectTest"/>

首先,在配置文件中引入aop的命名空间,然后通过aop命名空间的<aop:aspectj-autoproxy/>自动为Spring容器中那些匹配@AspectJ切面的Bean创建代理,完成自动代理的创建工作。

    <aop:aspectj-autoproxy/>有一个proxy-target-class属性,默认为false,表示使用JDK的动态代理织入增强,当配置为<aop:aspectj-autoproxy proxy-target-class=”true”/>时,表示使用CGLib的动态代理织入增强。
四. 利用基于@AspectJ的AOP实现权限控制
(1) 定义一个枚举类
   1: public enum ACCESS {

   2:     LOOK,EXIT,DOWNLOAD,ADMIN

   3: }

该枚举表示用户拥有的权限,权限由低到高。

(2)定义一个注解

   1: @Retention(RetentionPolicy.RUNTIME)         //声明注解的保留期限

   2: @Target(ElementType.METHOD)                 //声明可以使用该注解的目标类型

   3: public @interface UserAccessAnnotation {    //定义注解

   4:     ACCESS value() default ACCESS.LOOK;     //声明注解成员

   5: }

定义好这个注解之后,可以把注解放在需要进行权限控制的方法前

   1: public class DataOperate extends ActioinSupport{

   2:  

   3:     @UserAccessAnnotation(ACCESS.ADMIN)

   4:     public String updateData(String data){

   5:         System.out.println("Updata Data");

   6:     }

   7: }

在这里我们使用 UserAccessAnnotation 来表示需要在updateData 方法执行之前判断用户的权限是否为管理员权限。

(3) 定义切点Pointcut

   1: public class SystemArchitecture {

   2:     /**

   3:      * A Join Point is defined in the action layer where the method needs

   4:      * a permission check.

   5:      */

   6:     @Pointcut("@annotation(com.wbl.aop.UserAccessAnnotation)")

   7:     public void userAccess(){}

   8: }

PointCut 即切入点,就是定义方法执行的点,before表示在方法执行前、after 表示方法执行后或者 around表示方法执行前后。 一般情况下,我们把 PointCut 全部集中定义在 SystemArchitecture 类中,以方便修改和管理。

(4) 定义一个切面

   1: @Aspect

   2: public class PermissionAspect {

   3:     @Before(value = "com.wbl.aop.SystemArchitecture.userAccess()&&" + 

   4:     "@annotation(userAccessAnnotation)",argNames="userAccessAnnotation")

   5:  

   6:     public void checkPermission(UserAccessAnnotation userAccessAnnotation) throws Exception{

   7:         User user = (User)ActionContext.getContext().getSession().get("user");

   8:         if(user != null){

   9:             if(user.getBehaviorLevel() < userAccessAnnotation.value().ordinal() + 1){

  10:                 throw new NoPermissionException("NO_ACCESS");

  11:             }

  12:         }

  13:     }

  14: }

argNames="userAccessAnnotation" 的意思是把 Annotation 当做参数传递进来,并判断用户的权限是否足够。如果用户的权限不足以访问该方法,就要抛出 NoPermissionException,通知系统该用户没有权限。其中NoPermissionException是自定义的异常。

   1: public class NoPermissionException extends Exception {

   2:     public NoPermissionException(String msg){

   3:         super(msg);

   4:     }

   5: }

(5) 在applicationContext.xml中配置切面

   1: <aop:aspectj-autoproxy/>

   2: <bean class="com.wbl.aop.PermissionAspect"/>

(6) 在Struts中配置全局异常

   1: <global-results> 

   2:  <result name="error">/WEB-INF/jsp/error.jsp</result> 

   3:  </global-results> 

   4:  <global-exception-mappings> 

   5:  <exception-mapping exception="com.wbl.exceptions.NoPermissionException" 

   6:  result="loginerror"/> 

   7:  </global-exception-mappings>

利用基于@AspectJ的AOP实现权限控制的更多相关文章

  1. 基于Vue实现后台系统权限控制

    原文地址:http://refined-x.com/2017/08/29/基于Vue实现后台系统权限控制/,转载请注明出处. 用Vue/React这类双向绑定框架做后台系统再适合不过,后台系统相比普通 ...

  2. Spring 基于 AspectJ 的 AOP 开发

    Spring 基于 AspectJ 的 AOP 开发 在 Spring 的 aop 代理方式中, AspectJ 才是主流. 1. AspectJ 简介 AspectJ 是一个基于 java 语言的 ...

  3. [Spring框架]Spring AOP基础入门总结二:Spring基于AspectJ的AOP的开发.

    前言: 在上一篇中: [Spring框架]Spring AOP基础入门总结一. 中 我们已经知道了一个Spring AOP程序是如何开发的, 在这里呢我们将基于AspectJ来进行AOP 的总结和学习 ...

  4. 基于资源名的MVC权限控制

    在程序复杂程度不断上升的过程中,无可避免需要触碰到权限控制,而权限控制又与业务逻辑紧紧相关,市场上出现了大量的权限控制产品,而程序的开发,讲究去繁化简的抽象,在我的开发过程中,逐渐发现程序的权限控制核 ...

  5. 基于RESTful API 设计用户权限控制

    RESTful简述 本文是基于RESTful描述的,需要你对这个有初步的了解. RESTful是什么? Representational State Transfer,简称REST,是Roy Fiel ...

  6. 基于原生PHP交叉会员权限控制

    对于一个网站的后台管理系统,单一的超级管理员权限往往不能满足我们的需求,尤其是对于大型网站而言,这种单一的权限会引发许许多多的问题出现. 比如:一个网站编辑,平时他只是负责公司网站的公告更新,但如果网 ...

  7. aop (权限控制之功能权限)

    在实际web开发过程中通常会存在功能权限的控制,不如这个角色只允许拥有查询权限,这个角色拥有CRUD权限,当然按钮权限显示控制上可以用button.tld来控制,本文就不说明. 具体控制流程就是通过登 ...

  8. aop(权限控制)

    创建sysContext (管理请求) package com.tp.soft.common.util; import javax.servlet.http.HttpServletRequest; i ...

  9. Spring基于AspectJ的AOP的开发——注解

    源码:https://gitee.com/kszsa/dchart 一, AspectJ的概述: AspectJ是一个面向切面的框架,它扩展了Java语言.AspectJ定义了AOP语法所以它有一个专 ...

随机推荐

  1. project工期出现小数问题

    进入“选项”,点击“日程”,将默认“开始”.“结束”时间调整为“9点~18点.原为PREJECT 日历 (注意是日历~!!)默认的“8点~17点”,与preject系统默认时间“9点~18点”有差别~ ...

  2. iOS项目上线的流程

    基本知识 首先要了解一下Xcode打包签名机制中 Certificates & Identificates &Provisioning Profiles 三者之间的关系: Certif ...

  3. ViewerJS 一个在浏览器上查看 PDF 和电子表格的 JavaScript 库

    Viewer.js简介 http://viewerjs.org/ 下载Viewer.js压缩包,解压后将ViewerJS文件夹放在网站根目录下 在浏览器地址栏中输入网址http://172.16.8. ...

  4. 总结open与fopen的区别

    https://www.zybuluo.com/yiltoncent/note/87461 参考链接1 参考链接2 对于这两个名字很类似的函数,对于很多初学者来说,不容易搞清楚它们有什么不同,只知道按 ...

  5. Flutter实战视频-移动电商-49.详细页_Stack制作底部工具栏

    49.详细页_Stack制作底部工具栏 一直悬浮在最下面的 Stack层叠组件.里面用Row 可以横向布局 开始 stack如果想定位就要用position去定位. 修改return返回值的这个地方 ...

  6. 精通BitmapData

    一.构造方法: var bmd:BitmapData=new BitmapData(200,100,true,0xffff0000); 参数说明: 1.宽 2.高 3.是否使用32位填充位图(包括al ...

  7. Fitnesse + Xebium环境搭建

    1.在搭建Fitnesse + Xebium环境之前先将selenium基础环境搭建完成并调试成功 参照:http://www.cnblogs.com/moonpool/p/5480724.html ...

  8. 翻转链表中相邻的k个节点

    示例: 输入:1->2->3->4->5 k=2 输出:2->1->4->3->5 k=3输出:3->2->1->4->5 Py ...

  9. FileReader文件读取API

    :用来把文件读入内存,并且读取文件中的数据.FileReader接口提供了一个异步API,使用该API可以在浏览器主线程中异步访问文件系统,读取文件中的数据. 1.FileReader接口的方法 Fi ...

  10. unity sprite怎么获取切割后的图

    学习了一段时间的unity,对里面的组件有一个大致的了解,但是具体操作来说还不是很熟悉,今天看了一片关于unity sprite怎么获取切割后的图的文章,感觉还不错. 假设有一张png/tga图集,导 ...