基于spring注解切面的简单实现

首先定义一个注解:

package com.niu.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by niuyadong on 2018/5/10.
 */
@Target({ElementType.TYPE, ElementType.METHOD})//注解类型,级别
@Retention(RetentionPolicy.RUNTIME)//运行时注解
public @interface PermissionCheck {
    String value() default "";
}

根据这个注解编写一个注解切面:

package com.niu.aspect;

import com.niu.annotation.PermissionCheck;
import com.niu.exception.PermissionCheckException;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * Created by niuyadong on 2018/5/10.
 */
@Aspect //切面标识
@Component //交给spring管理
public class PermissionAspect {

    /**
     * 定义一个切入点方法,会拦截含有此注解的方法
     */
    @Pointcut("@annotation(com.niu.annotation.PermissionCheck)") //切入点表达式
    private void permissionCheck(){} //切入点签名

    /**
     *在被拦截的方法之前会执行的操作
     */
    @Before("permissionCheck();") //相当于  @Before("@annotation(com.niu.annotation.PermissionCheck)")
    public void before(JoinPoint joinPoint) throws NoSuchMethodException {
        Signature signature = joinPoint.getSignature(); //获取切入点方法签名对象,(在此处应该获取到被拦截的方法)
        if(!(signature instanceof MethodSignature)){
            throw new PermissionCheckException("签名方法获取异常,终端连接");
        }
        MethodSignature methodSignature = (MethodSignature) signature; //将签名对象强制转换成方法签名对象
        System.out.println(methodSignature.getName());
        System.out.println("被代理的对象:" + joinPoint.getTarget()); //getTarget() 获取被代理对象
        System.out.println("代理对象自己:" + joinPoint.getThis()); //getThis() 获取代理对象本身
        Object target = joinPoint.getTarget();//获取被代理的对象
        System.out.println("被代理的类对象:"+target.getClass());
        Method method = target.getClass().getMethod(methodSignature.getName(),
                methodSignature.getParameterTypes());//根据被代理的类对象获取要执行的方法
        PermissionCheck permissionCheck = method.getAnnotation(PermissionCheck.class);//获取该方法的指定注解
        System.out.println(permissionCheck.value()); //获取注解的值,然后根据传入的值,执行自己的业务逻辑
    }

    /**
     * 在被拦截的方法之后会执行的操作
     */
    @After("permissionCheck();") //相当于  @After("@annotation(com.niu.annotation.PermissionCheck)")
    public void after(){
        System.out.println("在切入点方法执行之后");
    }
}

在切面程序执行过程中会有一些自定义的异常抛出,所以需要设置一个自定义异常(其余可以根据自己需要设置自己的异常):

package com.niu.exception;

/**
 * Created by niuyadong on 2018/5/10.
 * 自定义签名异常
 */
public class PermissionCheckException extends RuntimeException{
    public PermissionCheckException(String exception){
        super(exception);
    }
}

最后在controller中引用这个注解,就会将自己想要的功能块交给切面处理,代码如下:

package com.niu.controller;

import com.niu.annotation.PermissionCheck;
import com.niu.domain.Girl;
import com.niu.repository.GirlRepository;
import com.niu.service.GirlService;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;

/**
 * Created by niuyadong on 2018/5/9.
 */
@RestController
public class GirlController {

    @Resource
    private GirlRepository girlRepository;

    /**
     * 添加一个女生
     * @param girl
     * @return
     */
    @PostMapping(value="/girls")
    @PermissionCheck("create:niu")
    public Girl createGirl(@Valid Girl girl, BindingResult bindingResult){
        if(bindingResult.hasErrors()){
            System.out.println(bindingResult.getFieldError().getDefaultMessage());
            return null;
        }
        return girlRepository.save(girl);
    }
}

这样就实现了一个基于注解的切面编程,可以用于自定义的事务管理,权限校验等场景。

基于注解的切面实现原理:
注解不会主动执行,只能通过method对象获取注解,然后根据注解做不同的操作。因为切入点在注解上,所以只需要增加一个注解就能够将该功能添加到自己的业务逻辑上。

测试输出结果:

被代理的对象:com.niu.controller.GirlController@294c44b7
代理对象自己:com.niu.controller.GirlController@294c44b7
被代理的类对象:class com.niu.controller.GirlController
create:niu(注解传入的值)
未成年人禁止入内!
在切入点方法执行之后

JoinPoint对象中的getThis()方法和getTarget()方法有什么区别,为什么输出结果一样?
大概理解:百度搜索给出的答案,有其他答案的请在评论中给出,谢谢。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值