zoukankan      html  css  js  c++  java
  • AspectJ

     spectJ是Java的一个AOP框架,可以单独使用,也可以整合到其它框架中。

    单独使用AspectJ时需要使用专门的编译器ajc。

    java的编译器是javac,AspectJ的编译器是ajc,aj是首字母缩写,c即compiler。

    此处介绍如何单独使用AspectJ。


      

    下载AspectJ所需的jar包

    https://www.eclipse.org/aspectj/downloads.php

    下载得到的是一个jar包,不能直接使用,解压,得到3个jar包:

    单独使用AspectJ时,只需添加aspectjrt.jar。


    IDEA环境配置

    1、安装插件

    2、使用专门的编译器


    Demo

    (1)新建Java项目,添加aspectjrt.jar。只添加这一个jar包就ok。

    (2)新建包com.chy.dao,包下新建接口UserDao、实现类UserDaoImpl:

    public interface UserDao {
        public void addUser(int i,String str);
        public void deleteUser();
    }
    public class UserDaoImpl implements UserDao {
        @Override
        public void addUser(int i,String str) {
            System.out.println("正在添加用户...");
        }
    
        @Override
        public void deleteUser() {
            System.out.println("正在删除用户...");
        }
    }

    (3)新建包com.chy.aspect,包下新建类UserDaoAspect:

    //需要用@Aspect标注
    @org.aspectj.lang.annotation.Aspect
    public class UserDaoAspect {
        /*
        配置全局切入点
        返回值类型  类|接口名.方法名(参数表)
        参数表可使用具体类型,比如(int,String),也可用(..)表示任意类型、个数的参数
         */
        @Pointcut("execution(* com.chy.dao.UserDao.*(..))")
        private void pointCut(){}
    
        /*
        前置通知
        可以引用全局切入点,也可以现配:
        @Before("execution(void com.chy.dao.UserDao.*(..))")
         */
        @Before("pointCut()")
        public void before(){
            System.out.println("正在执行前置通知...");
        }
    
        //后置通知
        @After("pointCut()")
        public void after(){
            System.out.println("正在执行后置通知...");
        }
    
        //返回通知
        @AfterReturning("pointCut()")
        public void afterReturning(){
            System.out.println("正在执行返回通知...");
        }
    
        //异常通知
        @AfterThrowing("pointCut()")
        public void  afterThrowing(JoinPoint point){
            System.out.println("正在执行异常通知...");
    
            //获取目标对象,返回值是Object类型
            Object target = point.getTarget();
    
            //目标方法名,String
            System.out.println("目标方法:"+point.getSignature());
    
            //需要转换一下才能得到具体的实参
            List<Object> args = Arrays.asList(point.getArgs());
            System.out.println("实参表:"+args);
        }
    
    }

    方法名任意,因为要用注解标注此方法是用来实现哪种通知的。

    可传入一个JointPoint类型的参数,表示连接点。

    环绕通知:

        /*
        环绕通知
        需要传入一个ProceedingJoinPoint类型的参数,用于调用目标方法。
        如果要代理多个方法,返回值最好声明为Object,因为多个方法的返回值类型可能不相同
        */
        @Around("pointCut()")
        public Object around(ProceedingJoinPoint point) throws Throwable {
            //前增强
            System.out.println("正在执行前增强...");
            //调用目标方法
            Object obj = point.proceed();
            //后增强
            System.out.println("正在执行后增强...");
            //返回目标方法的返回值
            return obj;
        }

    环绕通知与其它通知有重叠,不能一起使用。

    (4)使用

    UserDao user=new UserDaoImpl();
    user.addUser();

    AspectJ增强的是方法,调用方法时,会自动调用对应的通知来增强。


    切面的另一种写法(了解)

    包下新建Aspect:

    //注意是aspect,不是class
    public aspect UserDaoAspect {
        //配置全局切入点
        @Pointcut("execution(* com.chy.dao.UserDao.*(..))")
        private void pointCut(){}
    
        /*
        前置通知
        可以使用引用切入点,也可以现配:
        before():execution(void com.chy.dao.UserDao.*(..)){     }
         */
        before():pointCut(){
            System.out.println("正在执行前置通知...");
        }
    
        //后置通知
        after():pointCut(){
            System.out.println("正在执行后置通知...");
        }
    }

    方法名是固定的:before、after,都是关键字,before表示前置通知,after表示后置通知。

    此种方式很不好用,不推荐。

  • 相关阅读:
    HHHOJ #153. 「NOI模拟 #2」Kotomi
    HHHOJ #151. 「NOI模拟 #2」Nagisa
    Luogu P5298 [PKUWC2018]Minimax
    Luogu P5368 [PKUSC2018]真实排名
    Luogu P5408 【模板】第一类斯特林数·行
    Codechef December Challenge 2019 Division 1
    AtCoder Grand Contest 040
    CSP2019游记(翻车记)
    Codeforces Round #594 (Div. 1)
    AtCoder Grand Contest 039
  • 原文地址:https://www.cnblogs.com/chy18883701161/p/11144207.html
Copyright © 2011-2022 走看看