• SpringAop(日志记录)的实现


    基于xml

    1、环境搭建,添加需要引入的依赖

    • spring-aop(spring-context, 把aop加载类),
    • spring-aspects
    <!-- 导入了context,会自动导入先关依赖,包括spring-aop -->    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.3.RELEASE</version>
    </dependency>
    <!--aop实现的框架 Aspects-->
    <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aspects</artifactId>
          <version>4.3.3.RELEASE</version>
     </dependency>

    2、创建一个通知/增强类

    //将advice包下的LogAdvice交给spring容器管理
    @Component("logAdvice") public class LogAdvice { // 使用log4j日志框架进行日志的记录 // Logger Log4j进行日志输出的的类 private Logger log = Logger.getLogger(LogAdvice.class); // 编写增强方法、前置增强 // JoinPoint 连接点对象,就是正在运行的目标方法的对象 public void beforeLog(JoinPoint joinPoint) { /* * log.debug("debug"); // 对应debug输出级别 * log.info("info"); // 对应info输出级别 * log.warn("warn"); // 对应warn输出级别 * log.error("error"); // 对应error输出级别 */ //得到目标对象 Object target = joinPoint.getTarget(); //由对象获取这个对象所在类的类名 getName() 获取的 包.类名的字符串 getSimpleName() 获取类名 String className = target.getClass().getSimpleName(); //得到正在执行的目标方法的签名(例:public int findUserById(int id)) String methodName = joinPoint.getSignature().getName(); //得到调用目标方法传递参数 Object[] args = joinPoint.getArgs(); //输出日志 log.info("开始执行:"+className+"的"+methodName+",传递的参数"+Arrays.asList(args)); //打印结果:com.zl.spring.advice.LogAdvice - 开始执行:UserServiceImpl的findUserById,传递的参数[2] } /** * 后置增强方法 * 得到目标方法的返回值 * rs: 接收目标方法的返回值 如果目标方法没有返回值, 得到null * @param joinPoint */ public void afterLog(JoinPoint joinPoint,Object rs) { Object target = joinPoint.getTarget(); String className = target.getClass().getSimpleName(); String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); log.info("后置增强开始执行:"+className+"的"+methodName+",传递的参数"+Arrays.asList(args)+"目标方法的返回值:"+rs); } //最终增强方法 public void finallyLog(JoinPoint joinPoint) { Object target = joinPoint.getTarget(); String className = target.getClass().getSimpleName(); String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); log.info("最终增强开始执行:"+className+"的"+methodName+",传递的参数"+Arrays.asList(args)); } //异常增强方法 //指定异常(exceptionSQLException public void throwLog(JoinPoint joinPoint,RuntimeException e) { Object target = joinPoint.getTarget(); String className = target.getClass().getSimpleName(); String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); log.info("异常增强开始执行:"+className+"的"+methodName+",传递的参数"+Arrays.asList(args) +"出现异常"); }

    其中环绕增强应该新建一个类,一个类可以有以上四种增强

    //环绕增强
    public
    Object aroundLogger(ProceedingJoinPoint jp) throws Throwable{ log.info(jp.getSignature().getName()+"方法开始执行"); try { //执行目标方法 Object rs = jp.proceed(); log.info(jp.getSignature().getName()+"方法正常执行完"); return rs; } catch (SQLException e) { log.error("调用"+jp.getTarget()+"的"+jp.getSignature().getName() +"方法发生异常"+e); throw e; } }

    3、 进行织入, 在spring的配置文件进行织入

      使用前缀为:aop 的标签

    ①、导入命名空间

    xmlns:aop="http://www.springframework.org/schema/aop"
    ...
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd

    配置aop

    ②、切入点的配置(将service包下的所有类,运行方法进行增强)

    <aop:config>
        <aop:pointcut expression="execution(  *  spring06.service..*.*(..) )" id="pointcut1"/>

    语法:

    <!-- 切入点
         id: 唯一标示符         expression: 切入点的表达式
    语法格式  execution([访问修饰符]  返回值类型   包名.类名.方法名(参数列表) )
    execution(public  void   spring06.service.impl.UserServiceImpl.findById(int) )  对一个方法的增强
    通配符:  * 任意,   返回值可以使用,  类名可以使用,  方法名可以使用
    在类名前加两个点: 表示这个包以及这个包所有的子包下的类参数表示任意: ..
     execution(  *    spring06.service..*.*(..) )
     -->

    ③、增强的配置

    通知类(增强的方法) ref: 对应通知类的bean的id
    <aop:aspect ref="logAdvice">

    ④、织入(满足条件进行织入)

    <!-- 增强策略 : 增强分类的调用的方法-->
    <!-- 配置一个前置增强
    method: 前置增强的方法名      pointcut-ref: 引用的切入点
    织入: 对符合切入点的方法进行前置增强, 增强的方法是logAdvice的beforeLog()的方法
     -->
    <aop:before method="beforeLog"   pointcut-ref="pointcut1"/>
    <!-- 后置增强 
    public void  afterLog(JoinPoint joinPoint, Object rs) 
    returning="参数名" 告诉spring,把目标方法的返回值赋值给这个增强方法的哪一个参数上,
        要求returning后面的参数,与方法的接收返回值的参数名一样
    -->
    <aop:after-returning method="afterLog" pointcut-ref="pointcut1" returning="rs" />
    <!-- 最终增强:  不管是否发生异常, 都会执行 -->
    <aop:after method="finallyLog" pointcut-ref="pointcut1"/>
    <!-- 配置异常增强
    throwing: 参数名, 告诉spring,把异常对象赋值给增强方法的那个异常参数上
     -->
    <aop:after-throwing method="throwLog" pointcut-ref="pointcut1"  throwing="e"/>
      </aop:aspect>
    </aop:config>

    如果在通知类中没有使用注解的形式交给spring管理可以使用默认构造方法

    <!-- 通知类交给spring管理 -->
    <bean id="logAdvice" class="spring06.advice.LogAdvice"></bean>

    4、扫描注解

    <!-- 扫描注解 base-package: 包名, 扫描这个包,以及这个包后代包下所有类上的注解 -->
    <context:component-scan base-package="spring06" />

    基于注解的方式

    通知类使用注解

      @Aspect //定义为一个通知类

    方式一:

    @Component("logAdvice2")
    @Aspect //定义为一个通知类
    public class LogAdvice2 {
        private Logger log = Logger.getLogger(LogAdvice2.class);
    //最终增强方法
        @After("execution( *  com.zl.spring.service..*.*(..) )")
        public void finallyLog(JoinPoint joinPoint) {
            Object target = joinPoint.getTarget();
            String className = target.getClass().getSimpleName();
            String methodName = joinPoint.getSignature().getName();
            
            Object[] args = joinPoint.getArgs();
            log.info("最终增强开始执行2:"+className+"的"+methodName+",传递的参数"+Arrays.asList(args));
        }
            
        //异常增强方法
        //指定异常(exceptionSQLException
        @AfterThrowing(value="execution( *  com.zl.spring.service..*.*(..) )",throwing = "e")
        public void throwLog(JoinPoint joinPoint,RuntimeException e) {
            Object target = joinPoint.getTarget();
            String className = target.getClass().getSimpleName();
            String methodName = joinPoint.getSignature().getName();
            Object[] args = joinPoint.getArgs();
            log.info("异常增强开始执行2:"+className+"的"+methodName+",传递的参数"+Arrays.asList(args) +"出现异常");
        }

    方式二:

    @Component("logAdvice2")
    @Aspect //定义为一个通知类
    public class LogAdvice2 {
        private Logger log = Logger.getLogger(LogAdvice2.class);
    
        //加在方法上
        @Pointcut("execution(  *  spring06.service..*.*(..) )" )  
        private void  pit() {}
        @Before("pit()")
        public void beforeLog(JoinPoint joinPoint) {
            Object target = joinPoint.getTarget();
            String className = target.getClass().getSimpleName();
            String methodName = joinPoint.getSignature().getName();
            Object[] args = joinPoint.getArgs();
            log.info("开始执行2:"+className+"的"+methodName+",传递的参数"+Arrays.asList(args));
        }
        //后置增强方法
        @AfterReturning(value="pit()",returning="rs")
        public void afterLog(JoinPoint joinPoint,Object rs) {
            Object target = joinPoint.getTarget();
            String className = target.getClass().getSimpleName();
            String methodName = joinPoint.getSignature().getName();
            Object[] args = joinPoint.getArgs();
            log.info("后置增强开始执行2:"+className+"的"+methodName+",传递的参数"+Arrays.asList(args)+"目标方法的返回值:"+rs);
        }

    applicationContext.xml中扫描注解:

        <!-- 扫描注解 base-package: 包名, 扫描这个包,以及这个包后代包下所有类上的注解 -->
        <context:component-scan base-package="com.zl.spring" />
        
        <!-- 扫描通知类中的注解 -->
        <aop:aspectj-autoproxy/>
  • 相关阅读:
    初创业公司怎么开拓市场?(转)
    谈谈创业初期公司拓展业务的心得(转)
    互联网产品消息推送设计策略(转)
    如何成为一名合格的CTO?(转)
    jackson JsonPropertyOrder和@JsonIgnoreProperties注解
    tomcat报java.lang.VerifyError错误
    FAQ unzip无法解压文件
    Oracle监听启动失败问题
    F5 BIG-IP负载均衡器配置实例与Web管理界面体验
    如何查询 Oracle 11g日志
  • 原文地址:https://www.cnblogs.com/64Byte/p/13114306.html
Copyright © 2020-2023  润新知