zoukankan      html  css  js  c++  java
  • spring的AspectJ基于XML和注解(前置、后置、环绕、抛出异常、最终通知)

    1、概念

    (1)AspectJ是一个基于Java语言的AOP框架

    (2)Spring2.0以后新增了对AspectJ切入点表达式的支持

    (3)AspectJ是AspectJ1.5的新增功能,通过JDK5注解技术,允许在Bean类中定义切面。新版本的Spring框架建议使用AspectJ方式来开发AOP

    2、切入点表达式

    (1)execution():用语描述方法

    语法:execution(修饰符、返回值、包、类、方法(参数)、异常)

    修饰符:一般省略

    public:公共方法

    *:任意

    返回值

    void:没有返回值

    String:返回值为字符串

    *:返回值任意

    方法:不能省略

    参数

    (..)参数任意

    (2)案例:

     <aop:pointcut id="myPointCut" expression="execution(* pers.zhb.proxy.*.*(..))"></aop:pointcut>

    (3)其他表达式

    within:匹配包或者子包中的方法

    this:匹配接口中代理对象中的方法

    target:匹配实现接口的目标对象的方法

    args:匹配参数格式符合标准的方法

    bean:对指定bean所有的方法

    2、AspectJ通知类型

    (1)aop联盟定义通知类型:具有特性接口,必须实现,从而确定方法名称。
    (2)aspectj通知类型:只定义类型名称。已经方法格式。
    before:前置通知(应用:各种校验)

    在方法执行前执行,如果通知抛出异常,阻止方法运行

    afterRetuming:后置通知(应用:常规数据处理)

    方法正常返回后执行,如果方法中抛出异常,通知无法执行

    必须在方法执行后才执行,所以可以获得方法的返回值

    around:环统通知(应用:十分强大,可以做任何事情)

    方法执行前后分别执行,可以阻止方法的执行。
    必须手动执行目标方法

    afterThrowing:抛出异常通知(应用:包装异常信息)

    方法抛出异常后执行,如果方法没有抛出异常,无法执行

    after最终通知(应用:清理现场)

    方法执行完毕后执行,无论方法中是否出现异常

    3、导入jar包(四个)

    aop联盟规范

     

    spring aop实现

    aspect规范

    spring aspect实现

     

    4、源码

    (1)AspectJAfterThrowingAdvice

     (2)AspectJAfterAdvice

    5、基于XML文件的配置(前置通知)

    (1)目标类的接口和实现类:

    public interface StudentService {
         void addStudent();
         void updateStudent();
         void deleteStudent();
    }
    public class StudentServiceImpl implements StudentService {
        @Override
        public void addStudent() {
            System.out.println("addStudent");
        }
    
        @Override
        public void updateStudent() {
            System.out.println("updateStudent");
        }
    
        @Override
        public void deleteStudent() {
            System.out.println("deleteStudent");
        }
    }

    (2)切面类(含有通知):

    public class MyAspect {
        public void before(JoinPoint joinPoint){
            System.out.println("前置通知:"+ joinPoint.getSignature().getName());
        }
    }

    (3)配置文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns="http://www.springframework.org/schema/beans"
           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">
        <!--目标类-->
        <bean id="studentService" class="pers.zhb.aspectxml.StudentServiceImpl"></bean>
        <!--切面类-->
        <bean id="myAspect" class="pers.zhb.aspectxml.MyAspect"></bean>
        <!--aop编程
        将切面类声明为切面,从而获得通知(方法)
        ref:切面类引用
        -->
        <aop:config>
            <aop:aspect ref="myAspect">
                <!--引入切面类,从中获得通知(方法)
                    expression:切入点表达式
                    id:名称,用于其他通知引用
                -->
                <aop:pointcut id="myPointCut" expression="execution(* pers.zhb.aspectxml.StudentServiceImpl.*(..))"></aop:pointcut>
                <!--
                method:通知,即方法名
                pointcut:切入点表达式,此表达式只能当前通知使用
                pointcut-ref:切入点的引用,可以和其它通知共享切入点
                -->
                <aop:before method="before" pointcut-ref="myPointCut"></aop:before>
            </aop:aspect>
        </aop:config>
    </beans>

    (4)测试类:

    public class TestAspectXml {
        public static void main(String[] args) {
            ApplicationContext applicationContext=new
                    ClassPathXmlApplicationContext("applicationContext.xml");
            //获得目标类
            pers.zhb.aspectxml.StudentService studentService= (StudentService) applicationContext.getBean("studentService");
            studentService.addStudent();
            studentService.deleteStudent();
            studentService.updateStudent();
        }
    }
    前置通知:addStudent
    addStudent
    前置通知:deleteStudent
    deleteStudent
    前置通知:updateStudent
    updateStudent

    6、基于XML文件的配置(后置通知)

    (1)定义接口和接口的实现类:

    public interface StudentService {
         void addStudent();
         void updateStudent();
         String deleteStudent();
    }
    public class StudentServiceImpl implements StudentService {
        @Override
        public void addStudent() {
            System.out.println("addStudent");
        }
    
        @Override
        public void updateStudent() {
            System.out.println("updateStudent");
        }
    
        @Override
        public String deleteStudent() {
            System.out.println("deleteStudent");
            return "nihao";
        }
    }

    (2)切面类:

    public class MyAspect {
        public void before(JoinPoint joinPoint){
            System.out.println("前置通知:"+ joinPoint.getSignature().getName());
        }
    
        public void after(JoinPoint joinPoint,Object ret){//参数一:连接点描述
            //参数二:类型Object,参数名returning配置的
            System.out.println("后置通知:"+ joinPoint.getSignature().getName()+"   "+ret);
        }
    }

    (3)配置文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns="http://www.springframework.org/schema/beans"
           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">
        <!--目标类-->
        <bean id="studentService" class="pers.zhb.aspectxml.StudentServiceImpl"></bean>
        <!--切面类-->
        <bean id="myAspect" class="pers.zhb.aspectxml.MyAspect"></bean>
        <!--aop编程
        将切面类声明为切面,从而获得通知(方法)
        ref:切面类引用
        -->
        <aop:config>
            <aop:aspect ref="myAspect">
                <!--引入切面类,从中获得通知(方法)
                    expression:切入点表达式
                    id:名称,用于其他通知引用
                -->
                <aop:pointcut id="myPointCut" expression="execution(* pers.zhb.aspectxml.StudentServiceImpl.*(..))"></aop:pointcut>
                <!--
                method:通知,即方法名
                pointcut:切入点表达式,此表达式只能当前通知使用
                pointcut-ref:切入点的引用,可以和其它通知共享切入点
                returning:通知方法第二个参数的名称
                -->
                <aop:before method="before" pointcut-ref="myPointCut"></aop:before>
                <aop:after-returning method="after" pointcut-ref="myPointCut" returning="ret"></aop:after-returning>
    
            </aop:aspect>
        </aop:config>
    </beans>

    (4)测试类:

    public class TestAspectXml {
        public static void main(String[] args) {
            ApplicationContext applicationContext=new
                    ClassPathXmlApplicationContext("applicationContext.xml");
            //获得目标类
            pers.zhb.aspectxml.StudentService studentService= (StudentService) applicationContext.getBean("studentService");
            studentService.addStudent();
            studentService.deleteStudent();
            studentService.updateStudent();
        }
    }
    前置通知:addStudent
    addStudent
    后置通知:addStudent   null
    前置通知:deleteStudent
    deleteStudent
    后置通知:deleteStudent   nihao
    前置通知:updateStudent
    updateStudent
    后置通知:updateStudent   null

    7、基于XML文件的配置(环绕通知)

    (1)切面类:

    public class MyAspect {
        public void before(JoinPoint joinPoint){
            System.out.println("前置通知:"+ joinPoint.getSignature().getName());
        }
    
        public void after(JoinPoint joinPoint,Object ret){//参数一:连接点描述
            //参数二:类型Object,参数名returning配置的
            System.out.println("后置通知:"+ joinPoint.getSignature().getName()+"   "+ret);
        }
        public Object around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
            //手动执行目标方法
            System.out.println("前");
            Object object=proceedingJoinPoint.proceed();
            System.out.println("后");
            return null;
        }
    }

    (2)配置文件:

     <aop:around method="around" pointcut-ref="myPointCut"></aop:around>

    (3)测试结果:

    前置通知:addStudent
    前
    addStudent
    后
    后置通知:addStudent   null
    前置通知:deleteStudent
    前
    deleteStudent
    后
    后置通知:deleteStudent   null
    前置通知:updateStudent
    前
    updateStudent
    后
    后置通知:updateStudent   null

    8、基于XML文件的配置(抛出异常)

    (1)定义目标类的接口和接口的实现类:

    public interface StudentService {
         void addStudent();
         void updateStudent();
         String deleteStudent();
    }

    在方法中制造异常:

    public class StudentServiceImpl implements StudentService {
        @Override
        public void addStudent() {
            System.out.println("addStudent");
        }
    
        @Override
        public void updateStudent() {
            int num=9/0;
            System.out.println("updateStudent");
        }
    
        @Override
        public String deleteStudent() {
            System.out.println("deleteStudent");
            return "nihao";
        }
    }

    (2)切面类:

    public class MyAspect {
        public void before(JoinPoint joinPoint){
            System.out.println("前置通知:"+ joinPoint.getSignature().getName());
        }
    
        public void after(JoinPoint joinPoint,Object ret){//参数一:连接点描述
            //参数二:类型Object,参数名returning配置的
            System.out.println("后置通知:"+ joinPoint.getSignature().getName()+"   "+ret);
        }
        public Object around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
            //手动执行目标方法
            System.out.println("前");
            Object object=proceedingJoinPoint.proceed();
            System.out.println("后");
            return null;
        }
        public void AfterThrowing(JoinPoint joinPoint,Throwable throwable){
            System.out.println("抛出异常的通知:"+throwable.getMessage());
        }
    }

    (3)配置文件:

     <aop:after-throwing method="AfterThrowing" pointcut-ref="myPointCut" throwing="throwable"></aop:after-throwing>

    (4)测试:

    前置通知:addStudent
    前
    addStudent
    后
    后置通知:addStudent   null
    前置通知:deleteStudent
    前
    deleteStudent
    后
    后置通知:deleteStudent   null
    前置通知:updateStudent
    前
    抛出异常的通知:/ by zero
    Exception in thread "main" java.lang.ArithmeticException: / by zero

    9、基于XML文件的配置(最终通知)

    (1)目标类的接口和接口的实现类:

    public interface StudentService {
         void addStudent();
         void updateStudent();
         String deleteStudent();
    }
    public class StudentServiceImpl implements StudentService {
        @Override
        public void addStudent() {
            System.out.println("addStudent");
        }
    
        @Override
        public void updateStudent() {
            int num=9/0;
            System.out.println("updateStudent");
        }
    
        @Override
        public String deleteStudent() {
            System.out.println("deleteStudent");
            return "nihao";
        }
    }

    (2)切面类:

    public class MyAspect {
        public void before(JoinPoint joinPoint){
            System.out.println("前置通知:"+ joinPoint.getSignature().getName());
        }
    
        public void after(JoinPoint joinPoint,Object ret){//参数一:连接点描述
            //参数二:类型Object,参数名returning配置的
            System.out.println("后置通知:"+ joinPoint.getSignature().getName()+"   "+ret);
        }
        public Object around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
            //手动执行目标方法
            System.out.println("前");
            Object object=proceedingJoinPoint.proceed();
            System.out.println("后");
            return null;
        }
        public void AfterThrowing(JoinPoint joinPoint,Throwable throwable){
            System.out.println("抛出异常的通知:"+throwable.getMessage());
        }
    
        public void myafter(JoinPoint joinPoint){
            System.out.println("最终通知");
        }
    }

    (3)配置文件:

     <aop:after method="myafter" pointcut-ref="myPointCut"></aop:after>

    (4)测试结果:

    前置通知:addStudent
    前
    addStudent
    最终通知
    后

    后置通知:addStudent
    null 前置通知:deleteStudent 前 deleteStudent 最终通知 后
    后置通知:deleteStudent
    null 前置通知:updateStudent 前 最终通知 抛出异常的通知:/ by zero Exception in thread "main" java.lang.ArithmeticException: / by zero

    不管有没有异常都会执行最终通知。

    10、基于注解的配置

    (1)目标类的接口和接口的实现类:

    public interface StudentService {
         void addStudent();
         void updateStudent();
         String deleteStudent();
    }
    import org.springframework.stereotype.Service;
    @Service("studentService")
    public class StudentServiceImpl implements StudentService {
        @Override
        public void addStudent() {
            System.out.println("addStudent");
        }
    
        @Override
        public void updateStudent() {
            int num=9/0;
            System.out.println("updateStudent");
        }
    
        @Override
        public String deleteStudent() {
            System.out.println("deleteStudent");
            return "nihao";
        }
    }

    (2)配置文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <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"
           xmlns="http://www.springframework.org/schema/beans"
           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">
        <!--扫描注解-->
        <context:component-scan base-package="pers.zhb.aspectxml"></context:component-scan>
        <!--确定aop注解生效-->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    </beans>

    (3)切面:

    @Component
    @Aspect//声明切面
    public class MyAspect {
        @Before("execution(* pers.zhb.aspectxml.StudentServiceImpl.*(..))")
        public void before(JoinPoint joinPoint){
            System.out.println("前置通知:"+ joinPoint.getSignature().getName());
        }
    
        //声明公共切入点
        @Pointcut("execution(* pers.zhb.aspectxml.StudentServiceImpl.*(..))")
        private void myPointCut(){
    
        }
        @AfterReturning(value = "myPointCut()",returning = "ret")
        public void after(JoinPoint joinPoint,Object ret){//参数一:连接点描述
            //参数二:类型Object,参数名returning配置的
            System.out.println("后置通知:"+ joinPoint.getSignature().getName()+"   "+ret);
        }
    
        @Around(value = "myPointCut()")
        public Object around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
            //手动执行目标方法
            System.out.println("前");
            Object object=proceedingJoinPoint.proceed();
            System.out.println("后");
            return null;
        }
    
    @AfterThrowing(value = "execution(* pers.zhb.aspectxml.StudentServiceImpl.*(..))",throwing = "throwable")
        public void AfterThrowing(JoinPoint joinPoint,Throwable throwable){
            System.out.println("抛出异常的通知:"+throwable.getMessage());
        }
    
        @After(value = "myPointCut()")
        public void myafter(JoinPoint joinPoint){
            System.out.println("最终通知");
        }
    }

    (4)测试:

    public class TestAspectXml {
        public static void main(String[] args) {
            ApplicationContext applicationContext=new
                    ClassPathXmlApplicationContext("applicationContext.xml");
            //获得目标类
            pers.zhb.aspectxml.StudentService studentService= (StudentService) applicationContext.getBean("studentService");
            studentService.addStudent();
            studentService.deleteStudent();
            studentService.updateStudent();
        }
    }
    前
    前置通知:addStudent
    addStudent
    后
    最终通知
    后置通知:addStudent   null
    前
    前置通知:deleteStudent
    deleteStudent
    后
    最终通知
    后置通知:deleteStudent   null
    前
    前置通知:updateStudent
    最终通知
    抛出异常的通知:/ by zero
    Exception in thread "main" java.lang.ArithmeticException: / by zero
  • 相关阅读:
    【转】每天一个linux命令(28):tar命令
    【转】每天一个linux命令(27):linux chmod命令
    【转】每天一个linux命令(26):用SecureCRT来上传和下载文件
    【转】每天一个linux命令(25):linux文件属性详解
    【转】每天一个linux命令(24):Linux文件类型与扩展名
    C#常用多线程方法
    追本溯源 —— 汉语词汇含义的演化
    追本溯源 —— 汉语词汇含义的演化
    古书与二十四史
    古书与二十四史
  • 原文地址:https://www.cnblogs.com/zhai1997/p/12711155.html
Copyright © 2011-2022 走看看