• 基于XML的AOP配置


    一、基于XML的AOP配置

           1.假设创建一个AccountService需要增强(执行其中每一个方法都会加一个记录日志的方法),则再创建一个日志类实现记录日志方法;

    public class AccountServiceImpl implements IAccountService {
    
        public void saveAccount() {
            System.out.println("执行了保存");
        }
    
        public void updateAccount(int i) {
            System.out.println("执行了更新"+i);
        }
    
        public int deleteAccount() {
            System.out.println("执行删除");
            return 0;
        }
    public class Logger {
        /**
         * 前置通知
         */
        public void beforePrintLog(){
            System.out.println("前置通知Logger类中的beforePrintLog方法开始记录日志。。。");
        }
    
        /**
         * 后置通知
         */
        public void afterReturningPrintLog(){
            System.out.println("后置通知Logger类中的afterReturningPrintLog方法开始记录日志。。。");
        }
    
        /**
         * 异常通知
         */
        public void afterThrowingPrintLog(){
            System.out.println("异常通知Logger类中的afterThrowingPrintLog方法开始记录日志。。。");
        }
    
        /**
         * 最终通知
         */
    
        public void afterPrintLog(){
            System.out.println("最终通知Logger类中的afterPrintLog方法开始记录日志。。。");
        }
        /**
         * 环绕通知
         *问题:
         *   当我们配置环绕通知之后,切入点方法没有执行,而是通知方法执行
         *分析:
         *    动态代理中的环绕通知 有明确的切入点方法的调用,而我们的没有
         *解决:
         *    spring提供一个接口:ProceedingJoinPoint,该接口的proceed()方法相当于明确调用切入点方法
         *    该接口可以作为环绕通知的方法参数,在程序执行时,spring框架中为我们提供接口的实现类供我们使用
         *  sprig的环绕通知
         *      可以在代码中手动控制增强方法何时执行的方式
         */
        public Object aroundPrintLog(ProceedingJoinPoint pjp){
            Object rtValue=null;
            try {
                Object[] args=pjp.getArgs();
                System.out.println("Logger类中的aroundPrintLog方法开始记录日志。。。前置");
                rtValue=pjp.proceed(args);//明确调用有业务层方法(切入点方法)
                System.out.println("Logger类中的aroundPrintLog方法开始记录日志。。。后置");
                return rtValue;
            } catch (Throwable t) {
                System.out.println("Logger类中的aroundPrintLog方法开始记录日志。。。异常");
                throw new RuntimeException(t);
            }finally {
                System.out.println("Logger类中的aroundPrintLog方法开始记录日志。。。最终");
            }
        }
    }
    
    
    
     
    
    
    
     

            第一步: 导入一依赖:              

    <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.0.2.RELEASE</version>
            </dependency>
            <!--解析切入点表达式-->
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.8.7</version>
            </dependency>
    
        </dependencies>

           第二步:配置文件

             配置spring中的IOC,引入该引入的配置对象;

                    具体配置方法:https://www.cnblogs.com/cqyp/p/12498972.html

              配置spring中基于AOP的配置:

    <!--spring中基于xml的AOP配置步骤
            1.把通知Bean交给spring管理
            2.使用aop:config标签表明开始AOP的配置
            3.使用aop:aspect标签表明配置切面
                    id:是给切面唯一标识
                    ref:指通知类bean的Id
            4.在aop:aspect标签内部使用对应标签来配置通知类型
                   我们现在的示例是让printLog方法在切入点方法执行之前执行:所以是前置通知
                   aop:before:表示配置前置通知
                        method:用于指定Logger类中哪个方法是前置通知
                        pointcut:用于指定切入点表达式,该切入点表达式的含义是对业务层的方法增强
                            切入点表达式的写法:
                                 关键字:execution(表达式)
                                 表达式:
                                      访问修饰符   返回值  包名.包名.包名...类名.方法名(参数列表)
                                 标准的表达式写法:
                                       public void com.li.service.impl.AccountServiceImpl.saveAccount()
                                 访问修饰符可以省略
                                      void com.li.service.impl.AccountServiceImpl.saveAccount()
                                  返回值可以使用通配符表示任何返回值
                                      * com.li.service.impl.AccountServiceImpl.saveAccount()
                                  包名可以使用通配符,表示任意包,有几级包,就需要写几个*,也可以用..表示当前包及其子包
                                      * *..AccountServiceImpl.saveAccount()
                                  类名和方法名都可以使用*实现通配
                                      * *..*.*()
                                   参数列表:使用通配符表示任意类型的参数,但必须有参数
                                   可以使用..表示有无参数均可
                                 全通配写法
                                 * *..*.*(..)
                          实际开发中切入点表达式的写法:
                               切到业务层实现类下的所有方法
                                   * com.li.service.impl.*.*(..)
        -->
        <!--配置Logger类-->
        <bean id="logger" class="com.li.utils.Logger"></bean>
        <!--开启AOP配置-->
        <aop:config>
    <!--配置切入点表达式,id属性用于指定表达式唯一标识,expression:表达式内容
          此标签写在aop:aspect标签内部只能当前切面使用
          他可以写在aop:aspect外面,此时就变成所有的切面通用
      -->
    <aop:pointcut id="pt1" expression="execution(* com.li.service.impl.*.*(..))"/>
    
    
            <!--配置切面-->
            <aop:aspect id="logAdvice" ref="logger">
                <!--配置通知类型,并建立通知方法和切入点方法的关联-->
    <!--前置通知,切入点方法之前执行
    
    <aop:before method="beforePrintLog" pointcut-ref="pt1"/>
    -->
    <!--后置通知
    
    <aop:after-returning method="afterReturningPrintLog" pointcut-ref="pt1"/>
    -->
    <!--异常通知
    
    <aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="pt1"/>
    -->
    <!--最终通知
    
    <aop:after method="afterPrintLog" pointcut-ref="pt1"/>
    -->
    <!--配置环绕通知-->
    <aop:around method="aroundPrintLog" pointcut-ref="pt1"></aop:around>
    </aop:aspect> </aop:config>
     

                

  • 相关阅读:
    管道
    linux基本网络配置
    201671010130 201620172 《Java程序设计》第三周学习小结
    201671010130 201620172 《Java程序设计》第二周学习小结
    201671010130 201620172 《Java程序设计》第五周学习小结
    201671010130 201620172 《Java程序设计》首次与Java打交道
    朵的面向对象程序设计课程学习进度条
    201671010130 201620172 《Java程序设计》第六七周学习小结
    201671010130 201620172 《Java程序设计》第四周学习小结
    Note of Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14
  • 原文地址:https://www.cnblogs.com/cqyp/p/12512854.html
Copyright © 2020-2023  润新知