• AspectJ对AOP的实现


    一:你应该明白的知识

    1.对于AOP这种编程思想,很多框架都进行了实现。Spring就是其中之一,可以完成面向切面编程。然而,AspectJ也实现了AOP的功能,且实现方式更为简捷,使用更加方便,而且还支持注解式开发。所以,Spring又将AspectJ对于AOP的实现也引入到了自己的框架中。在Spring中使用AOP开发时,一般使用AspectJ的实现方式。

    2.Spring的经典AOP配置方案
      01.使用的是Aspectj第三方框架,实现了AOP思想
      02.注解配置的AOP
      03.纯POJO <aop:config>

    3..切入点表达式
    execution(【modifiers-pattern?】 访问修饰符
    ret-type-pattern 返回值类型
    【declaring-type-pattern?】 全限定性类名
    name-pattern(param-pattern) 方法名(参数名)
    【throws-pattern?】) 抛出异常类型

    切入点表达式要匹配的对象就是目标方法的方法名。所以,execution表达式中明显就是方法的签名。注意:表达式中加[]的部分表示可省略部分,各部分间用空格分开。在其中可以使用以下符号:
    符号       意义
    *      0至多个任意字符
    ..     用在方法参数中,表示任意多个参数
       

           用在包名后,表示当前包及其子包路径
    +    用在类名后,表示当前类及其子类
           用在接口后,表示当前接口及其实现类
    案例:
    execution(public * *(..)) 指定切入点为:任意公共方法
    execution(* set*(..)) 指定切入点为:任何一个以"set"开始的方法

    二.使用的是Aspectj第三方框架注解配置的AOP增强

    源码介绍:

    1.ISomeService.java

    package entity;
    //业务接口
    public interface ISomeService {
        //1.1  执行事务
       public void doTransaction();
        //1.2 书写日志
       public String doLog();
    }
    View Code

    2.SomeServiceImpl.java

    package entity;
    //接口的实现类
    public class SomeServiceImpl implements ISomeService {
        //实现接口中的方法
        @Override
        public void doTransaction() {
            System.out.println("----开启事务----");
        }
    
        @Override
        public String doLog() {
            //int i=5/0;//制造一个错误,用于测试异常增强
            System.out.println("---书写日志-----");
            return "abc";
        }
    
    }
    View Code

    3.MyAspect.java(使用的是Aspectj第三方框架注解配置的AOP增强)

    package aop;
    //aspectj注解实现aop增强
    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;
    
    //该类为切面
    @Aspect
    public class MyAspect {
    
        // 前置通知
        @Before(value = "execution(public * *..ISomeService.doLog(..))")
        public void myBefore() {
            System.out.println("这是前置增强");
        }
    
        // 后置通知
        @AfterReturning(value = "execution(public * *..ISomeService.doLog(..))")
        public void myAfterReturning() {
            System.out.println("这是后置增强");
        }
    
        // 环绕增强
        @Around(value = "execution(public * *..ISomeService.doLog(..))")
        public void myAround(ProceedingJoinPoint pjp) throws Throwable {
            System.out.println("这是环绕前置增强");
    
            pjp.proceed();
    
            System.out.println("这是环绕后置增强");
        }
    
        // 异常增强
        @AfterThrowing(value = "execution(public * *..ISomeService.doLog(..))")
        public void myAfterThrowing() {
            System.out.println("这是异常增强");
        }
    
        // 最终增强
        @After(value = "execution(public * *..ISomeService.doLog(..))")
        public void myAfter() {
            System.out.println("这是最终增强");
        }
    }
    View Code

    4.applicationContext.xml(Spring的配置文件)

    <?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:context="http://www.springframework.org/schema/context"
        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/context http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
       
       <!-- 目标对象 -->
       <bean id="someService" class="entity.SomeServiceImpl"></bean>
    
       <!-- 切面: -->
       <bean id="myAspect" class="aop.MyAspect"></bean>
       
       <!-- 自动代理 -->
      <aop:aspectj-autoproxy/>
    </beans>
    View Code

    5.MyTest.java

    package test;
    //测试类
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import entity.ISomeService;
    
    public class MyTest {
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            ISomeService biz=(ISomeService)ctx.getBean("someService");
            biz.doLog();
            biz.doTransaction();
            System.out.println("success!");
        }
    
    }
    View Code

    6.log4j.properties(日志配置文件)

    ### direct log messages to stdout ###
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.Target=System.out
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
    
    ### direct messages to file mylog.log ###
    log4j.appender.file=org.apache.log4j.FileAppender
    log4j.appender.file.File=c:mylog.log
    log4j.appender.file.layout=org.apache.log4j.PatternLayout
    log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
    
    ### set log levels - for more verbose logging change 'info' to 'debug' ###
    
    log4j.rootLogger=info, stdout
    View Code

    7.当然,同志们别忘了引入jar包啊!

    8.其测试结果展示:

     

    三:使用的是Aspectj第三方框架 纯POJO 基于Schema配置 (<aop:config>)

    源码介绍:

    1.MyAspect.java

    package aop;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    
    public class MyAspect {
        // 前置通知
        public void myBefore() {
            System.out.println("这是前置增强");
        }
    
        public void before(JoinPoint jp) {
            System.out.println("前置通知方法before() jp = " + jp);
        }
    
        // 后置通知
        public void myAfterReturning() {
            System.out.println("这是后置增强");
        }
    
        // 带参数
        public void afterReturing(String result) {
            System.out.println("后置通知方法 result = " + result);
        }
    
        // 环绕通知
        public Object around(ProceedingJoinPoint pjp) throws Throwable {
            System.out.println("环绕通知方法,目标方法执行之前");
            // 执行目标方法
            Object result = pjp.proceed();
            System.out.println("环绕通知方法,目标方法执行之后");
            return ((String) result).toUpperCase();
        }
    
        // 异常通知
        public void afterThrowing() {
            System.out.println("异常通知方法");
        }
    
        public void afterThrowing(Exception ex) {
            System.out.println("异常通知方法 ex = " + ex.getMessage());
        }
    
        // 最终通知
        public void after() {
            System.out.println("最终通知方法");
        }
    }
    View Code

    2.applicationContext.xml(Spring的配置文件)

    <?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:context="http://www.springframework.org/schema/context"
        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/context http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
        <!-- 目标对象 -->
        <bean id="someService" class="entity.SomeServiceImpl"></bean>
    
        <!-- 切面: -->
        <bean id="myAspect" class="aop.MyAspect"></bean>
    
        <aop:config>
            <!--expression:切入点表达式 -->
            <aop:pointcut expression="execution(public * *..ISomeService.doLog(..))"
                id="beforePointcut" />
            <aop:aspect ref="myAspect"><!-- ref:指定切面 -->
                <!-- method:指定切面类中的方法; pointcut-ref:指定定义的切点 -->
                <!-- 前置增强 -->
                <aop:before method="myBefore" pointcut-ref="beforePointcut" />
                <!-- 前置增强 带参 -->
                <aop:before method="before(org.aspectj.lang.JoinPoint)"
                    pointcut-ref="beforePointcut" />
                <!-- 后置增强 -->
                <aop:after-returning method="myAfterReturning"
                    pointcut-ref="beforePointcut" />
                <!-- 后置增强 带参 -->
                <aop:after-returning method="afterReturing(java.lang.String)"
                    pointcut-ref="beforePointcut" returning="result" />
                <!-- 环绕增强 -->
                <aop:around method="around" pointcut-ref="beforePointcut" />
                <!-- 异常增强 -->
                <aop:after-throwing method="afterThrowing"
                    pointcut-ref="beforePointcut" />
                <!-- 异常增强 带参 -->
                <aop:after-throwing method="afterThrowing(java.lang.Exception)"
                    pointcut-ref="beforePointcut" throwing="ex" />
                <!-- 最终增强 -->
                <aop:after method="after" pointcut-ref="beforePointcut" />
            </aop:aspect>
        </aop:config>
    </beans>
    View Code

    其中,其他的类和文件和上面的例子中完全相同。这里则不做介绍。

    3.其测试结果展示:

  • 相关阅读:
    FZU 2113 BCD Code 数位dp
    Gym 100917L Liesbeth and the String 规律&&胡搞
    Gym 100917C Constant Ratio 数论+暴力
    CF149D Coloring Brackets
    P4342 [IOI1998]Polygon
    P4316 绿豆蛙的归宿
    P1439 【模板】最长公共子序列
    Noip 2013 真题练习
    洛谷比赛 「EZEC」 Round 4
    P5024 保卫王国
  • 原文地址:https://www.cnblogs.com/zhangzongle/p/5950197.html
Copyright © 2020-2023  润新知