zoukankan      html  css  js  c++  java
  • Spring框架使用注解定义切面 AspectJ

    AspectJ:面向切面的框架,他扩展了java语言,定义了AOP语法,能够在编译期提供代码的织入。

    需求说明:使用注解实现日志切面。

    定义切面:UserServiceLogger.java

     1 package aop;
     2 
     3 import java.util.Arrays;
     4 
     5 import org.apache.log4j.Logger;
     6 import org.aspectj.lang.JoinPoint;
     7 import org.aspectj.lang.ProceedingJoinPoint;
     8 import org.aspectj.lang.annotation.AfterReturning;
     9 import org.aspectj.lang.annotation.Aspect;
    10 import org.aspectj.lang.annotation.Before;
    11 
    12 //日志处理类  增强处理类-日志
    13 @Aspect
    14 public class UserServiceLogger {
    15     private Logger logger = Logger.getLogger(UserServiceLogger.class);
    16 
    17     // 前置增强  表示的是service包下的UserService下面的任意方法
    18     @Before("execution(* service.UserService.*(..))")
    19     public void before(JoinPoint joinPoint) {
    20         logger.info("调用" + joinPoint.getTarget() + "的"
    21                 + joinPoint.getSignature() + "方法,方法参数是:"
    22                 + Arrays.toString(joinPoint.getArgs()));
    23     }
    24 
    25     // 后置增强pointcut表示切入点表达式   returning表示返回值
    26     @AfterReturning(pointcut="execution(* service.UserService.*(..))",returning="result")
    27     public void afterReturning(JoinPoint joinPoint,Object result) {
    28         logger.info("调用" + joinPoint.getTarget() + "的"
    29                 + joinPoint.getSignature() + "方法,方法的返回值是:"
    30                 +result);
    31     }
    32     
    33     // 异常抛出增强
    34     public void afterThrowingError(JoinPoint joinPoint,RuntimeException e) {
    35         logger.info("调用" + joinPoint.getTarget() + "的"
    36                 + joinPoint.getSignature().getName() + "方法,发生异常:"
    37                 +e);
    38     }
    39     //最终增强
    40     public void after(JoinPoint joinPoint) {
    41         logger.info("调用" + joinPoint.getTarget() + "的"
    42                 + joinPoint.getSignature().getName() + "方法,结束了"
    43                 );
    44     }
    45     
    46     //环绕增强
    47     public void aroundLogger(ProceedingJoinPoint joinPoint) {
    48         //下面是目标方法的前面执行的处理
    49         logger.info("调用" + joinPoint.getTarget() + "的"
    50                 + joinPoint.getSignature() + "方法,方法参数是:"
    51                 + Arrays.toString(joinPoint.getArgs()));
    52         Object result;//这个相当于是目标方法  
    53         try {
    54             //下面是目标方法之后进行的处理
    55                 result = joinPoint.proceed();
    56                 logger.info("调用"+joinPoint.getTarget()+"的"+joinPoint.getSignature()+"方法,方法返回值:"+result);
    57             
    58         } catch (Throwable e) {
    59             logger.error(joinPoint.getSignature().getName()+"方法发生异常"+e);
    60             e.printStackTrace();
    61         } finally{
    62             
    63         }
    64     }
    65 }
     1 package dao.impl;
     2 
     3 import org.springframework.stereotype.Repository;
     4 
     5 import dao.UserDao;
     6 import entity.User;
     7 
     8 /**
     9  * 用户DAO类,实现IDao接口,负责User类的持久化操作
    10  */
    11 @Repository("userDao")
    12 public class UserDaoImpl implements UserDao {
    13 
    14     public void save(User user) {
    15         // 这里并未实现完整的数据库操作,仅为说明问题
    16         System.out.println("保存用户信息到数据库");
    17         //throw new RuntimeException("为了测试程序异常");
    18     }
    19 }
     1     package service.impl;
     2     
     3     import javax.annotation.Resource;
     4     
     5     import org.springframework.stereotype.Service;
     6     
     7     import service.UserService;
     8     import dao.UserDao;
     9     import entity.User;
    10     
    11     /**
    12      * 用户业务类,实现对User功能的业务管理
    13      */
    14     @Service("userService")
    15     public class UserServiceImpl implements UserService {
    16     
    17         // 声明接口类型的引用,和具体实现类解耦合
    18         
    19         private UserDao dao;
    20     
    21     
    22         public UserDao getDao() {
    23             return dao;
    24         }
    25     
    26         @Resource//通过resource注解进行装配
    27         public void setUserDao(UserDao dao) {
    28             this.dao = dao;
    29         }
    30     
    31     
    32     
    33         public void addNewUser(User user) {
    34             // 调用用户DAO的方法保存用户信息
    35             dao.save(user);
    36             System.out.println("注入进去的user对象的信息是:"+user.toString());
    37         }
    38     }

    核心配置文件:applicationContext.xml

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:context="http://www.springframework.org/schema/context"
     5     xmlns:aop="http://www.springframework.org/schema/aop"
     6     xsi:schemaLocation="http://www.springframework.org/schema/beans
     7     http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
     8     http://www.springframework.org/schema/context 
     9     http://www.springframework.org/schema/context/spring-context-3.2.xsd
    10     http://www.springframework.org/schema/aop 
    11     http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
    12     <!-- 扫描包中注解标注的类 -->
    13     <context:component-scan base-package="service,dao" />
    14     <!--申明切面注解类  -->
    15     <bean class="aop.UserServiceLogger"></bean>
    16     <!--启动aspectj框架,让注解生效  -->
    17     <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    18 </beans>

    编写测试方法:

     1 package test;
     2 
     3 import org.junit.Test;
     4 import org.springframework.context.ApplicationContext;
     5 import org.springframework.context.support.ClassPathXmlApplicationContext;
     6 
     7 import service.UserService;
     8 import service.impl.UserServiceImpl;
     9 
    10 import entity.TestEntity;
    11 import entity.User;
    12 
    13 
    14 public class AopTest {
    15 
    16     @Test
    17     public void aopTest() {
    18         ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    19         UserService a = (UserService) ctx.getBean("userService");
    20         User user=new User();
    21         user.setUsername("丫丫");
    22         a.addNewUser(user);
    23     }
    24 
    25 }

    运行结果:

    12-31 11:32:53[INFO]aop.UserServiceLogger
    -调用service.impl.UserServiceImpl@1283bb96的void service.UserService.addNewUser(User)方法,方法参数是:[entity.User@2a3b5b47]
    保存用户信息到数据库
    注入进去的user对象的信息是:entity.User@2a3b5b47
    12-31 11:32:53[INFO]aop.UserServiceLogger
    -调用service.impl.UserServiceImpl@1283bb96的void service.UserService.addNewUser(User)方法,方法的返回值是:null

    有时候,一个切入点表达式会在很多的增强方法上面进行引用,一个一个的配置太麻烦了,我们可以统一定义一个切入点方法。

    修改一下UserServiceLogger.java类

     1 package aop;
     2 
     3 import java.util.Arrays;
     4 
     5 import org.apache.log4j.Logger;
     6 import org.aspectj.lang.JoinPoint;
     7 import org.aspectj.lang.ProceedingJoinPoint;
     8 import org.aspectj.lang.annotation.AfterReturning;
     9 import org.aspectj.lang.annotation.Aspect;
    10 import org.aspectj.lang.annotation.Before;
    11 import org.aspectj.lang.annotation.Pointcut;
    12 
    13 //日志处理类  增强处理类-日志
    14 @Aspect
    15 public class UserServiceLogger {
    16     private Logger logger = Logger.getLogger(UserServiceLogger.class);
    17     //统一定义切入点
    18     @Pointcut("execution(* service.UserService.*(..))")
    19     public void pointcut(){
    20         
    21     }
    22     // 前置增强  表示的是service包下的UserService下面的任意方法
    23     @Before("pointcut()")
    24     public void before(JoinPoint joinPoint) {
    25         logger.info("调用" + joinPoint.getTarget() + "的"
    26                 + joinPoint.getSignature() + "方法,方法参数是:"
    27                 + Arrays.toString(joinPoint.getArgs()));
    28     }
    29 
    30     // 后置增强pointcut表示切入点表达式   returning表示返回值
    31     @AfterReturning(pointcut="pointcut()",returning="result")
    32     public void afterReturning(JoinPoint joinPoint,Object result) {
    33         logger.info("调用" + joinPoint.getTarget() + "的"
    34                 + joinPoint.getSignature() + "方法,方法的返回值是:"
    35                 +result);
    36     }
    37     
    38     // 异常抛出增强
    39     public void afterThrowingError(JoinPoint joinPoint,RuntimeException e) {
    40         logger.info("调用" + joinPoint.getTarget() + "的"
    41                 + joinPoint.getSignature().getName() + "方法,发生异常:"
    42                 +e);
    43     }
    44     //最终增强
    45     public void after(JoinPoint joinPoint) {
    46         logger.info("调用" + joinPoint.getTarget() + "的"
    47                 + joinPoint.getSignature().getName() + "方法,结束了"
    48                 );
    49     }
    50     
    51     //环绕增强
    52     public void aroundLogger(ProceedingJoinPoint joinPoint) {
    53         //下面是目标方法的前面执行的处理
    54         logger.info("调用" + joinPoint.getTarget() + "的"
    55                 + joinPoint.getSignature() + "方法,方法参数是:"
    56                 + Arrays.toString(joinPoint.getArgs()));
    57         Object result;//这个相当于是目标方法  
    58         try {
    59             //下面是目标方法之后进行的处理
    60                 result = joinPoint.proceed();
    61                 logger.info("调用"+joinPoint.getTarget()+"的"+joinPoint.getSignature()+"方法,方法返回值:"+result);
    62             
    63         } catch (Throwable e) {
    64             logger.error(joinPoint.getSignature().getName()+"方法发生异常"+e);
    65             e.printStackTrace();
    66         } finally{
    67             
    68         }
    69     }
    70 }

    同样是能够正确运行的。

  • 相关阅读:
    java把指定文字输出为图片流,支持文字换行
    java根据图片和文字生成自定义图片
    eclipse中10个最有用的快捷键组合
    关于版本号:alpha、beta、rc、stable
    Maven内置属性及使用
    Linux终端执行shell脚本,提示权限不够的解决办法
    执行tsung时报"Maximum number of concurrent users in a single VM reached
    SSIS连接SAPBI
    SharePoint 2013连接非默认端口的SQL Server
    SQL Server数据库损坏、检测以及简单的修复办法
  • 原文地址:https://www.cnblogs.com/dongyaotou/p/12123648.html
Copyright © 2011-2022 走看看