大数据WEB阶段Spring框架 AOP面向切面编程(二)

来源:互联网 发布:python基本数据类型 编辑:程序博客网 时间:2024/06/05 06:00

Spring AOP面向切面编程(二)

一、切入点的execution表达式

  1. execution的表达形式: execution(修饰符? 返回值类型 所在包类? 方法名(参数列表) 异常?)

    1. ?表示可有可无
       execution(public * *(..))
      工程中所有的public方法
      execution(* set*(..))
      工程中所有方法名以set开头的方法
      execution(* com.xyz.service.AccountService.*(..))
      com.xyz.service.AccountService类下面的所有方法

    execution(* com.xyz.service..(..))

    com.xyz.service包下所有类的所有方法

    execution(* com.xyz.service...(..))
    com.xyz.service包下及其子包下所有类的所有方法
    execution(* com.xyz..service..(..))
    报名以com.xyz开头的所有子包一直子到service下的所有类的所有方法
    举例:com.xyz.a.b.service com.xyz.a.service com.xyz.a.b.c.service 会满足上面的条件

二、五大通知的具体实现

  1. 环绕通知 around
    1. 5个中最强大的通知,唯一一个能在通知中控制目标方法是否执行的通知
  2. 前置通知
    1. 配置文件配置
  3. 后置通知
    1. 配置文件配置
  4. 异常通知
    1. 异常通知可以控制出现异常后事务回滚 , 和记录日志
    2. 配置文件配置
    3. 注意: JoinPoint参数必须放在第一位
  5. 最终通知
    1. 不管是么情况都会执行

三、AOP注解

  1. 在配置文件中把aop注解开关打开
  2. 通过注解配置切面类
  3. 通过注解配置通知方法
    1. 前置通知
    2. 后置通知
    3. 环绕通知
    4. 异常通知
    5. 最终通知

四、通过注解生成切入点表达式的引用

  1. 创建一个空方法
    1. 使用@Pointcut注解生成一个切入点的引用
    2. 使用

五、环绕嵌套问题

六、自定义注解

  1. 声明一个注解
  2. 使用
  3. 判断是否有注解

七、各种示例

  1. 异常

    代码结构如图所示        PersonServlet            PersonService                PersonDao用异常通知捕获servlet的所有的方法抛出的异常:目标对象所在的类            cn.tedu.big1601.servlet.PersonServlet抛出异常所在的方法           save()抛出异常的名称              XxxException异常信息                    message意义:异常处理类和业务逻辑类完全松耦合。时刻捕获生产生产环境中所有的错误,实时监控该系统,异常收集。@Component@Aspectpublic class ExceptionAspect {    @AfterThrowing(value = "execution(* com.tj..*(..))" ,throwing = "throwable" )    public void after(JoinPoint  jp , Throwable throwable){        System.out.println("异常发生在:"+jp.getTarget().getClass());        System.out.println(jp.getSignature().getName()+"()发生了异常!");        System.out.println("发生异常类型:"+throwable.getClass());        System.out.println("异常信息:"+throwable.getMessage());    }}
  2. 统计方法执行时间

    计算servlet的各个类的各个方法的执行时间1.类的名称2.方法的名称           3.执行的时间控制台输出意义:用来监控程序的性能问题      @Component@Aspectpublic class RuntimeAspect {    @Around("execution(* com.tj..*(..))")    public Object around(ProceedingJoinPoint pjp) throws Throwable{        Long begin = System.currentTimeMillis();        Object result = pjp.proceed();        Long end = System.currentTimeMillis();        System.out.println(pjp.getTarget().getClass()+"类"+pjp.getSignature().getName()+"方法执行了"+ (end - begin)+"毫秒!");        return result;    }}
  3. 事务控制

    当方法上有事务的注解,该方法就有事务。                写一个切面来完成事务控制类       public class TxManage {    /**     * 开启事务     * */    public static void stattx(){        System.out.println("开启了事务");    }    /**     * 提交事务     * */    public  static void commitTx(){        System.out.println("提交事务");    }    /**     * 回滚事务     * */    public static void rollback(){        System.out.println("事务回滚");    }}自定义事务注解@Target(value = { ElementType.METHOD })@Retention(value = RetentionPolicy.RUNTIME)public @interface TxAnnotation {    String value() default "";}给需要事务控制的地方添加注解@Componentpublic class PersonServiceImpl implements PersonService{    @Autowired    private PersonDao dao;    @TxAnnotation    @Cacheable("add")    @Override    public void savePerson(Person person) {        dao.savePerson(person);    }    @TxAnnotation    @Cacheable("get")    @Override    public Person getPerson(int id) {        Person person = dao.getPerson(id);        return person;    }    @TxAnnotation    @Cacheable("del")    @Override    public void delPerson(int id) {        dao.delPerson(id);    }}事务控制切面@Component@Aspectpublic class TxAspect {    @Around(value = "execution(* com.tj..*(..)) && @annotation(ann)")    public Object around(ProceedingJoinPoint pjp ,TxAnnotation ann  ) throws Throwable{        Object result = null;        try{            TxManage.stattx();            result = pjp.proceed();            TxManage.commitTx();        }catch(Exception e){            TxManage.rollback();        }        return result;     }}
  4. 权限控制

    说明:每个方法上添加能够执行该方法的注解@PrivilegeInfo  并且要指明PrivilegeInfo(name=”add”)   那么将来这个方法只能执行还有add权限的方法自定义权限控制注解@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface PrivilegeInfo {    String value() ;}给需要控制权限的地方添加权限控制注解@Componentpublic class PersonServlet {    @Autowired    private PersonService ps;    /**     * 保存用户信息     * */    @PrivilegeInfo("add")    public void  savePerson(Person person){//      int  i  = 1/0;        ps.savePerson(person);    }    /**     * 获取用户信息     * */    @PrivilegeInfo("get")    public Person getPerson(int id){        Person person = ps.getPerson(id);        return person ;     }    /**     * 删除用户信息     * */    @PrivilegeInfo("del")    public void delPerson(int id  ){        ps.delPerson(id);    }}权限控制切面类@Component@Aspectpublic class PrivilegInfoAspect {    //当前用户的权限    List<String> list =Arrays.asList("add" , "get");    @Around("execution(* com.tj..*(..)) && @annotation(ann)")    public Object around(ProceedingJoinPoint pjp , PrivilegeInfo ann) throws Throwable{        String value = ann.value();        Object result = null;        if(list.contains(value)){            System.out.println("尊敬的飞秋会员你好!");            result = pjp.proceed();        }else{            System.out.println("你没有这个权限 ,滚");        }        return result;    }}
  5. 数据缓存

    缓存需求:1.savePerson的时候需要往数据库里保存一份然后再往内存(Map)中保存一份 2.getPerson的时候先从Map中获取 如果有则返回则不用执行目标方法,如果内存中没有则执行目标方法从数据库取3.如果第一次调用getPerson内存中没有的话 执行目标方法从数据库取 取出来后同时把获取到的Person对象保存到内存中,以便后续获取时直接从内存中取自定义 缓存控制注解@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface Cacheable {    String value();}给需要缓存的地方添加注解@Componentpublic class PersonServiceImpl implements PersonService{    @Autowired    private PersonDao dao;    @TxAnnotation    @Cacheable("add")    @Override    public void savePerson(Person person) {        dao.savePerson(person);    }    @TxAnnotation    @Cacheable("get")    @Override    public Person getPerson(int id) {        Person person = dao.getPerson(id);        return person;    }    @TxAnnotation    @Cacheable("del")    @Override    public void delPerson(int id) {        dao.delPerson(id);    }}缓存控制切面类@Component@Aspectpublic class CacheableAspect {    //缓存    Map<Integer , Person> map =  new HashMap<Integer,Person>();    @Around("execution(* com.tj..*(..))&& @annotation(ann)")    public Object befer(ProceedingJoinPoint jp  , Cacheable ann) throws Throwable{        Object result = null;        String v = ann.value();        if(v.equals("add")){            Person  person = (Person) jp.getArgs()[0];            int id = person.getId();            if(map.containsKey(id)){                System.out.println("该用户已存在");            }else{                System.out.println("存入 缓存");                map.put(id, person);                result = jp.proceed();            }        }else if(v.equals("get")){            int id = (Integer) jp.getArgs()[0];            if(map.containsKey(id)){                System.out.println("从缓存中获取");                result  = map.get(id);            }else{                result = jp.proceed();                Person person =  (Person) result;                map.put(person.getId(), person);            }        }        return result;    } }
原创粉丝点击