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 }

同样是能够正确运行的。

原文地址:https://www.cnblogs.com/dongyaotou/p/12123648.html