• AspectJ AOP学习基础


    一、切入点表达式

      1、execution:匹配方法的执行

        格式:execution(修饰符 返回值类型 包.类.方法(参数) throw 异常)

          1.1修饰符,表示方法的修饰符,一般省略。

          1.2返回类型 String表示返回String;void表示没有返回值;*表示返回任意类型,包括无返回值。

          1.3包

            hjp.spring.service 表示指定的包

            hjp.spring.*.service 表示spring下子模块包含service的包

            hjp.spring.service.. 表示service目录及其子目录

            综合:hjp.spring.*.service..

          1.4类 UserService表示指定的类;*Service表示以Service结尾;Test*表示以Test开头;*表示任意类名。

          1.5方法(与类相似)

            addUser表示指定方法;add*表示以add开头;*Do表示以Do结尾;*表示任意。

          1.6参数 ()表示没有参数;(int)表示一个int类型参数;(int,int)表示两个int类型参数(如果是java.lang包下的可以省略,其他类型必须写完全限定类名);(..)表示

              任意,包括无参。

          1.7throws 异常,一般省略。

      综合:execution(* hjp.spring.*.service..*.*(..))

      2、within:匹配包或子包中的方法,如:within(hjp.spring.service..*)

      3、this:匹配实现接口的代理对象中的方法,如:this(hjp.spring.dao.UserDao)

      4、target:匹配实现接口的目标对象中的方法,如:target(hjp.spring.daoImpl.UserDao)

      5、args:匹配参数格式符合标准的方法,如args(int,int)

      6、bean:匹配指定的bean,如:bean("userServiceId")

    二、AspectJ规定的通知类型

      1、before:前置通知(应用:各种校验),在方法执行前执行,如果通知抛出异常,阻止方法运行。

      2、afterReturning:后置通知(应用:常规数据处理),方法正常返回后执行,如果方法中抛出异常,通知无法执行;在方法执行后执行,所以才可以获得方法的返回值。

      3、around:环绕通知(应用:可以做任何事),方法执行前后分别执行,可以阻止方法的执行。

      4、afterThrowing:抛出异常通知(应用:包装异常信息),方法抛出异常后执行,如果方法没有抛出异常,无法执行。

      5、after:最终通知(应用:清理现场),方法执行完毕后执行,无论方法是否有异常出现。

      环绕通知类似代码块:  

    try{
    //前置通知(before)
    //手动执行目标方法
    //后置通知(after),可获得返回值
    }catch{
    //抛出异常通知(afterThrowing),可获得具体异常信息
    }finally{
    //最终(finally)
    }
    环绕通知类似代码块

     三、基于XML配置的代码示例

    1、代码结构:

    2、aspectj aop不是针对接口的,所有有没有接口不影响AOP实现,下面是UserService接口和UserServiceImpl实现类(目标类)代码

    package hjp.springAOP.springAspectJXml;
    
    public interface UserService {
        void addUser();
    
        void updateUser();
    }
    UserService
    package hjp.springAOP.springAspectJXml;
    
    public class UserServiceImpl implements UserService {
    
        @Override
        public void addUser() {
            // TODO Auto-generated method stub
            System.out.println("aspectj xml add user");
        }
    
        @Override
        public void updateUser() {
            // TODO Auto-generated method stub
            //int i=9/0;
            System.out.println("aspectj xml update user");
        }
    
    }
    UserServiceImpl

    3、切面类MyAspect代码

    package hjp.springAOP.springAspectJXml;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    
    public class MyAspect {
        public void myBefore(JoinPoint joinPoint) {
            System.out.println("前置通知:" + joinPoint.getSignature().getName());
        }
    
        public void myAfterReturning(JoinPoint joinPoint, Object ret) {
            System.out.println("后置通知:方法名," + joinPoint.getSignature().getName() + ";返回值," + ret);
        }
    
        public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
            System.out.println("环绕通知前");
            // 手动执行目标方法
            Object object = proceedingJoinPoint.proceed();
            System.out.println("环绕通知后");
            return object;
        }
    
        public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {
            System.out.println("目标类方法" + joinPoint.getSignature().getName() + "抛出异常:" + e.getMessage());
        }
    
        public void myAfter(JoinPoint joinPoint) {
            System.out.println("最终执行通知:方法:" + joinPoint.getSignature().getName());
        }
    }
    MyAspect

    4、beans.xml配置文件,记得添加aop命名空间和引用地址

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
                                  http://www.springframework.org/schema/beans/spring-beans.xsd
                                  http://www.springframework.org/schema/aop 
                                  http://www.springframework.org/schema/aop/spring-aop.xsd">
        <!-- 1、创建目标类 -->
        <bean id="userServiceId" class="hjp.springAOP.springAspectJXml.UserServiceImpl"></bean>
        <!-- 2、创建切面类 (通知) -->
        <bean id="myAspectId" class="hjp.springAOP.springAspectJXml.MyAspect"></bean>
        <!-- aop编程
             如果强制使用CGLIB,则设置aop:config 属性proxy-target-class="true"
         -->
        <aop:config>
            <!-- aspectj 编程
                 ref指向切面类 -->
            <aop:aspect ref="myAspectId">
                <!-- 声明切入点,确定目标类上哪些方法需被增强 -->
                <aop:pointcut expression="execution(* hjp.springAOP.springAspectJXml.*.*(..))" id="myPointCut" />
                <!-- 声明通知方式 -->
                <!-- 1、前置通知
                     method切面类中具体方法名
                     pointcut-ref指向切入点(使用pointcut,也可以在通知里配置自己的切入点表达式)
                <aop:before method="myBefore" pointcut-ref="myPointCut"/>
                 -->
                 <!-- 2、后置通知,可获取到返回值
                       returning用于设置通知的第二个参数名称,类型为Object(注意:此处参数名称要与切面类后置通知方法第二个参数名称一致)
                 <aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret"/>
                  -->
                  <!-- 3、环绕通知                     
                  <aop:around method="myAround" pointcut-ref="myPointCut"/>
                   -->
                   <!-- 4、抛出异常通知(测试此通知时,将目标类中updateUser方法中int i=9/0;代码注释去掉)
                           目标方法在抛出异常时执行,如果没有则不执行
                           throwing设置抛出异常通知的第二个参数,参数名称和此处设置的e一致,类型Throwable        
                    <aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/>
                    -->
                    <!-- 5、最终通知,即任何情况下都会执行 -->
                    <aop:after method="myAfter" pointcut-ref="myPointCut"/>
            </aop:aspect>
        </aop:config>
    </beans>
    beans.xml

    5、测试类

    package hjp.springAOP.springAspectJXml;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class TestApp {
        @Test
        public void demo1() {
            String xmlPath="hjp/springAOP/springAspectJXml/beans.xml";
            ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath);
            UserService userService = (UserService)applicationContext.getBean("userServiceId");
            userService.addUser();
            userService.updateUser();
        }
    }
    测试类

     四、基于注解的代码示例

    1、代码结构和上面差不多

    2、目标类的接口代码不变,目标类加注解后代码:

    package hjp.springAOP.springAspectJAnnotation;
    
    import org.springframework.stereotype.Service;
    
    @Service("userServiceId")//<bean id="userServiceId" class="hjp.springAOP.springAspectJAnnotation.UserServiceImpl"></bean>
    public class UserServiceImpl implements UserService {
    
        @Override
        public void addUser() {
            // TODO Auto-generated method stub
            System.out.println("aspectj xml add user");
        }
    
        @Override
        public void updateUser() {
            // TODO Auto-generated method stub
            //int i=9/0;
            System.out.println("aspectj xml update user");
        }
    
    }
    目标类

    3、切面类加注解后代码(注意:代码里面使用了引用公共切入点表达式的方法):

    package hjp.springAOP.springAspectJAnnotation;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
    
    @Component//<bean id="myAspectId" class="hjp.springAOP.springAspectJAnnotation.MyAspect"></bean>
    @Aspect//<aop:aspect ref="myAspectId">
    public class MyAspect {
        //@Before("execution(* hjp.springAOP.springAspectJAnnotation.*.*(..))")//<aop:before method="myBefore" pointcut="myPointCut"/>
        public void myBefore(JoinPoint joinPoint) {
            System.out.println("前置通知:" + joinPoint.getSignature().getName());
        }
        //@AfterReturning(value="execution(* hjp.springAOP.springAspectJAnnotation.*.*(..))",returning="ret")
        public void myAfterReturning(JoinPoint joinPoint, Object ret) {
            System.out.println("后置通知:方法名," + joinPoint.getSignature().getName() + ";返回值," + ret);
        }
        //编写共有的切入点表达式
        @Pointcut("execution(* hjp.springAOP.springAspectJAnnotation.*.*(..))")
        private void myPointCut(){}
        //@Around("myPointCut()")//注意加括号
        public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
            System.out.println("环绕通知前");
            // 手动执行目标方法
            Object object = proceedingJoinPoint.proceed();
            System.out.println("环绕通知后");
            return object;
        }
        //@AfterThrowing(value="myPointCut()",throwing="e")
        public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {
            System.out.println("目标类方法" + joinPoint.getSignature().getName() + "抛出异常:" + e.getMessage());
        }
        @After("myPointCut()")
        public void myAfter(JoinPoint joinPoint) {
            System.out.println("最终执行通知:方法:" + joinPoint.getSignature().getName());
        }
    }
    切面类

    4、beans.xml配置文件,注意新加context和AOP命名空间及引用地址

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
                                  http://www.springframework.org/schema/beans/spring-beans.xsd
                                  http://www.springframework.org/schema/aop 
                                  http://www.springframework.org/schema/aop/spring-aop.xsd
                                  http://www.springframework.org/schema/context 
                                  http://www.springframework.org/schema/context/spring-context.xsd">
        <!-- spring注解扫描 -->
        <context:component-scan base-package="hjp.springAOP.springAspectJAnnotation"></context:component-scan>
        <!-- 使AOP注解生效 -->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    </beans>

    5、测试类

    package hjp.springAOP.springAspectJAnnotation;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class TestApp {
        @Test
        public void demo1() {
            String xmlPath="hjp/springAOP/springAspectJAnnotation/beans.xml";
            ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath);
            UserService userService = (UserService)applicationContext.getBean("userServiceId");
            userService.addUser();
            userService.updateUser();
        }
    }
    测试类

    3、

  • 相关阅读:
    常见事务码说明
    常见表说明
    确认工序
    锐捷万兆交换机开启远程登录
    华为交换机相关命令
    ip网络
    深入css过渡transition
    KVM虚拟机两种配置的概念不同之处
    SSH连接服务器时,长时间不操作就会断开的解决方案
    HTTP状态码
  • 原文地址:https://www.cnblogs.com/hujiapeng/p/4820009.html
Copyright © 2020-2023  润新知