aop管理日志事务(springboot aop日志管理)

语宇社区 情感日志 74 0

Spring AOP-事务管理

1、@Transactional使用位置

Ⅰ 写在接口类上,该接口的所有实现类的所有方法都会有事务;

Ⅱ 写在接口方法上,该接口的所有实现类的该方法都会有事务;

Ⅰ 写在实现类上,该类中的所有方法都会有事务;

Ⅱ 写在实现类方法上,该方法上有事务。

建议:写在实现类或实现类的方法上。

2、PlatformTransactionManager

PlatformTransactionManager是哗耐敏Spring中的事务管理接口,具体如下:

3、DataSourceTransactionManager

Spring中JDBC事务管理实现类是DataSourceTransactionManager,所以我们使用MyBatis时,如果需要进行事务管理则配置该事务管理即可。

1、基础准备

jdbc.properties如下:

JdbcConfig如下:

2、测试

1、相关注解

配置类注解,定义在配置类上。

设置当前Spring环境中开启注解式事务支持。

接口、类、方法注解,定义在接口、类、方法上。

为当前业务层方法添加事务(如果设置在类或接口上方则类或接口中所有方法均添加事务)。

2、事务角色

发起事务方,在Spring中通常指代业务层开启事务的方法。

加入事务方,在亩败Spring中通乱枝常指代数据层方法,也可以是业务层方法。

3、@Transactional常用属性

true只读事务,false读写事务,增删改要设为false,查询设为true。

设置超时时间单位秒,在多长时间之内事务没有提交成功就自动回滚,-1表示不设置超时时间。

当出现指定异常进行事务回滚。

4、事务传播行为

比如上述测试案例中,我们给log方法上的@Transactional设置了传播属性为REQUIRES_NEW,表示当前事务协调员会自己开启一个事务。并不会因为transfer发生回滚而回滚。

Ⅰ REQUIRED(默认);

Ⅱ SUPPORTS;

Ⅲ MANDATORY;

Ⅳ REQUIRES_NEW;

Ⅴ NOT_SUPPORTED;

Ⅵ NEVER;

Ⅶ NESTED。

以上即为Spring AOP-事务管理的全部内容,感谢阅读。

SpringMvc + AOP Aspect 日志管理AOP执行两次,如何只让AOP执行一次

您好,这样的:这个还真没有 好像 , 你自己写一个吧! 就不判断methodName直接判断Method 这个对象。

切面的优先级

为项目增加一个新的切面类,负责验证功能,则需要指定切面执行的顺序。即切面的优先级。具体方法是给切面类增加@Order注解,并指定具体的数字,值越小优先级越高

1 package com.yl.spring.aop;

2

3 import java.util.Arrays;

4

5 import org.aspectj.lang.JoinPoint;

6 import org.aspectj.lang.annotation.Aspect;

7 import org.aspectj.lang.annotation.Before;

8 import org.springframework.core.annotation.Order;

9 import org.springframework.stereotype.Component;

10

11 /**

12 * 可以使用@Order注解指定切面的优先级,蔽雹值岩改越小优先级越高

13 * @author yul

14 *

15 */

16 @Order(2)

17 @Component

18 @Aspect

19 public class ValidationAspect {

20

21 @Before("execution(public int com.yl.spring.aop.ArithmeticCalculator.*(..))")

22 public void vlidateArgs(JoinPoint joinPoint) {

23 System.out.println("validate: " + Arrays.asList(joinPoint.getArgs()));

24 }

25 }

切点表达式的重用:

在LoggingAspect类中,切点的表达式可以先定义,在使用。

1 package com.yl.spring.aop;

2

3 import java.util.Arrays;

4

5 import org.aspectj.lang.JoinPoint;

6 import org.aspectj.lang.ProceedingJoinPoint;

7 import org.aspectj.lang.annotation.After;

8 import org.aspectj.lang.annotation.AfterReturning;

9 import org.aspectj.lang.annotation.AfterThrowing;

10 import org.aspectj.lang.annotation.Around;

11 import org.aspectj.lang.annotation.Aspect;

12 import org.aspectj.lang.annotation.Before;

13 import org.aspectj.lang.annotation.Pointcut;

14 import org.springframework.core.annotation.Order;

15 import org.springframework.stereotype.Component;

16 @Order(1)

17 @Component

18 @Aspect

19 public class LoggingAspect {

20

21 /**

22 * 定义一个方法,用于声明切入点表达式。一般的,该方法中再不宏枣帆需要添加其他的代码

23 * 使用@Pointcut 来声明切入点表达式

24 * 后面的其他通知直接使用方法名直接引用方法名即可

25 */

26 @Pointcut("execution(public int com.yl.spring.aop.ArithmeticCalculator.*(..))")

27 public void declareJoinPointExpression() {

28

29 }

30

31 /**

32 * 在com.yl.spring.aop.ArithmeticCalculator接口的每一个实现类的每一个方法开始之前执行一段代码

33 */

34 @Before("declareJoinPointExpression()")

35 public void beforeMethod(JoinPoint joinPoint) {

36 String methodName = joinPoint.getSignature().getName();

37 Object[] args = joinPoint.getArgs();

38 System.out.println("The method " + methodName + " begins with " + Arrays.asList(args));

39 }

40

41 /**

42 * 在com.yl.spring.aop.ArithmeticCalculator接口的每一个实现类的每一个方法执行之后执行一段代码

43 * 无论该方法是否出现异常

44 */

45 @After("declareJoinPointExpression()")

46 public void afterMethod(JoinPoint joinPoint) {

47 String methodName = joinPoint.getSignature().getName();

48 Object[] args = joinPoint.getArgs();

49 System.out.println("The method " + methodName + " ends with " + Arrays.asList(args));

50 }

51

52 /**

53 * 方法正常结束后执行的代码

54 * 返回通知是可以访问到方法的返回值的

55 */

56 @AfterReturning(value="declareJoinPointExpression()", returning="result")

57 public void afterReturning(JoinPoint joinPoint, Object result) {

58 String methodName = joinPoint.getSignature().getName();

59 System.out.println("The method " + methodName + " return with " + result);

60 }

61

62 /**

63 * 在方法出现异常时会执行的代码

64 * 可以访问到异常对象,可以指定在出现特定异常时在执行通知代码

65 */

66 @AfterThrowing(value="declareJoinPointExpression()", throwing="ex")

67 public void afterThrowing(JoinPoint joinPoint, Exception ex) {

68 String methodName = joinPoint.getSignature().getName();

69 System.out.println("The method " + methodName + " occurs exception: " + ex);

70 }

71

72 /**

73 * 环绕通知需要携带ProceedingJoinPoint类型的参数

74 * 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法。

75 * 而且环绕通知必须有返回值,返回值即为目标方法的返回值

76 */

77 @Around("declareJoinPointExpression()")

78 public Object aroundMethod(ProceedingJoinPoint pjd) {

79 Object result = null;

80 String methodName = pjd.getSignature().getName();

81 //执行目标方法

82 try {

83 //前置通知

84 System.out.println("The method " + methodName + " begins with " + Arrays.asList(pjd.getArgs()));

85 result = pjd.proceed();

86 //返回通知

87 System.out.println("The method " + methodName + " ends with " + Arrays.asList(pjd.getArgs()));

88 } catch (Throwable e) {

89 //异常通知

90 System.out.println("The method " + methodName + " occurs expection : " + e);

91 throw new RuntimeException(e);

92 }

93 //后置通知

94 System.out.println("The method " + methodName + " ends");

95 return result;

96 }

97

98 }

当处于不同的类,甚至不同的包时,可以使用包名.类名.方法名

具体代码如下:

1 package com.yl.spring.aop;

2

3 import java.util.Arrays;

4

5 import org.aspectj.lang.JoinPoint;

6 import org.aspectj.lang.annotation.Aspect;

7 import org.aspectj.lang.annotation.Before;

8 import org.springframework.core.annotation.Order;

9 import org.springframework.stereotype.Component;

10

11 /**

12 * 可以使用@Order注解指定切面的优先级,值越小优先级越高

13 * @author yul

14 *

15 */

16 @Order(2)

17 @Component

18 @Aspect

19 public class ValidationAspect {

20

21 @Before("com.yl.spring.aop.LoggingAspect.declareJoinPointExpression()")

22 public void vlidateArgs(JoinPoint joinPoint) {

23 System.out.println("validate: " + Arrays.asList(joinPoint.getArgs()));

24 }

25 }

jfinal如何用aop来做系统日志记录

Interceptor 可以对方法进行拦截,吵链并提供机会在方法的前后添加切面代码,实现 AOP 的核心目标。Interceptor 接口仅仅定义了一个方法 public void intercept(Invocation inv)。以下是简单示例:

public class DemoInterceptor implements Interceptor {

    public void intercept(Invocation inv) {

       //文件记录或者数据库记录

       LogKit.info("系统日志记录开始");

       

       inv.invoke();

       //

       LogKit.info("系统日志记录结束");

    }

}

以上代码中的 DemoInterceptor 将拦截目标方法,并且在目标方法调用前后向控制台输出文本。inv.invoke() 这一行代码是对目标方法的调用,在这一行代码的前后插入切面代码可以很方便地实现AOP。

注意:必须调用 inv.invoke() 方法,才能将当前调用传递到后续的 Interceptor 与 Action。

网页链接

JFinal中的AOP被划分为控制层AOP以及业务层AOP,严格来说业务层AOP并非仅限于在业务层使用,因为JFinal AOP可以应用于其它任何地方。

控制层拦截器的触发,只需发起action请求即可。业务层拦截器的触发需要先使用enhance方法对目标对象进行增强,然后调用目标方法即可。以下是业务层AOP使用的例子:

// 定义需要使用AOP的业务层类

public class OrderService {

    // 配置事务拦截器

    @Before(Tx.class)

    public void payment(int orderId, int userId) {

       // service code here

    }

}

 

// 定义控制器,控制器提供了enhance系列方法可对目标进行AOP增强

public class OrderController extends Controller {

    public void payment() {

       // 使用 enhance方法对业务层进行增强,使其具有AOP能力

       OrderService service = enhance(OrderService.class);

       

       // 调用payment方法时将会触发拦截器

       service.payment(getParaToInt("orderId"), getParaToInt("userId"));

    }

}

以上代码中OrderService是业务层类,其中的payment方冲则法之上配置了Tx事务拦截器,OrderController是控制器,在其中使用了enhance方法对OrderSevice进行了增强,随后调用其payment方法便可触发Tx拦截器升判孙。简言之,业务层AOP的触发相对于控制层仅需多调用一次enhance方法即可,而Interceptor、Before、Clear的使用方法完全一样。网页链接

如何用Spring进行日志管理

可以用spring aop 进行日志管理,下面是我博客中的内容,项目中也是这么用,只是复杂度更高:

第一步:导包,可以参考:spring4 项目搭建

还需要添加AspectJ(java中最流行的aop框架):

dependency  

    groupIdorg.springframework/groupId  

    artifactIdspring-aspects/artifactId  

    version4.2.2.RELEASE/version  

/dependency

第二步:配置bean文件

配置aop可以通过注解,也可以通过配置文件,项目中建议有配置文件,这样便于修改。我先讲解注解方法

配置自动扫描和AspectJ框架

    !-- 配置自动扫描的aop包 --  

    context:component-scan base-package="com.spring.aop"/  

    !-- 配置 AspectJ --  

    aop:aspectj-autoproxy/aop:aspectj-autoproxy

如果aop显示不出来就先xml头文件中导入(我相信大家会导入的,就不多说了)

xmlns:aop=""  

 

第三步渣团:业务代码,模拟用户的操作

业务代码AopService

package com.spring.aop;  

import org.springframework.stereotype.Service;  

@Service  

public class AopService {     

    // 用户登入  

    public void login(){  

        System.out.println("登入成功");  

    }  

    // 用户退出  

    public void loginOut(){  

        System.out.println("用户退出系统");  

    }  

      

    // 用户操作  

    public void writeABlog(){  

        System.out.println("用户编写博客");  

    }  粗型

    // 用户操作  

    public void deleteABlog(){  

        System.out.println("用户删除博客");  

    }  

}

切面代码:

package com.spring.aop;  

import org.aspectj.lang.JoinPoint;  

import org.aspectj.lang.annotation.After;  

import org.aspectj.lang.annotation.Aspect;  

import org.springframework.stereotype.Component;  

@Component  

@Aspect  

public class LogAspect {  

    @After("execution(public void com.spring.aop.AopService.*(..))")  

    public void afterMethod(JoinPoint joinPoint) {  

        String opreate = joinPoint.getSignature().getName();  

        System.out.println("ITDragon opreate " + opreate);  

    } 岩梁猜 

  

}

测试类:

package com.spring.aop;  

import org.junit.Test;  

import org.springframework.context.ApplicationContext;  

import org.springframework.context.support.ClassPathXmlApplicationContext;  

public class AopTest {  

      

    private ApplicationContext ctx = null;  

      

    {  

        ctx = new ClassPathXmlApplicationContext("beans.xml");  

    }  

    @Test  

    public void aopTest(){  

        AopService aopService = (AopService) ctx.getBean("aopService");  

        aopService.login();  

        aopService.writeABlog();  

        aopService.deleteABlog();  

        aopService.loginOut();  

    }  

}

测试结果:

登入成功  

ITDragon opreate login  

用户编写博客  

ITDragon opreate writeABlog  

用户删除博客  

ITDragon opreate deleteABlog  

用户退出系统  

ITDragon opreate loginOut

@Before: 前置通知, 在方法执行之前执行

@After: 后置通知, 在方法执行之后执行 

@AfterRunning: 返回通知, 在方法返回结果之后执行,方法必须有返回值。需要添加returning = "result",其中result就是返回结构,

@AfterReturning(pointcut="execution(public void com.spring.aop.AopService.*(..))",returning="result")

@AfterThrowing: 异常通知, 在方法抛出异常之后,有异常的时候才执行

@AfterThrowing(pointcut="execution(public void com.spring.aop.AopService.*(..))",throwing="e")

@Around: 环绕通知, 围绕着方法执行

@Component:标识该类受spring管理

@Aspect: 标识该类是一个切面

execution(public void com.spring.aop.AopService.*(..)) : 切入点签名表达式,用*号表示所有,也可以指定,括号内两点表示多个变量,也可以指定,还可以用 , || , !;以每个execution为一个单位

JoinPoint:连接点,该参数可以访问到更多的数据,还有很多方法可以自己试试。

@Order(n): 切面执行的优先级,n值越小,越优先执行

还有重用切面,等知识我就不过多描述了,毕竟是入门,讲一些常用的就可以了。

使用xml配置文件

package com.spring.aop;  

import org.aspectj.lang.JoinPoint;  

public class LogAspect {   

    public String afterMethod(JoinPoint joinPoint) {  

        String opreate = joinPoint.getSignature().getName();  

        System.out.println("ITDragon opreate " + opreate);  

        return "";  

    }  

}

配置文件:

!-- 扫描切面类 --  

    bean class="com.spring.aop.LogAspect" id="logAspect"/bean  

      

    !-- aop配置 --  

    aop:config  

        !-- 切点 --  

        aop:pointcut expression="execution(public void com.spring.aop.AopService.*(..))" id="aop"/  

        !-- 切面 : ref 的值是 切面类的id--  

        aop:aspect id="aspect" ref="logAspect"  

            !-- 前置方法 : pointcut-ref 的值是 切点的id --  

            aop:before method="afterMethod" pointcut-ref="aop"/  

        /aop:aspect  

    /aop:config

还是一样的测试方法,其结果为:

ITDragon opreate login  

登入成功  

ITDragon opreate writeABlog  

用户编写博客  

ITDragon opreate deleteABlog  

用户删除博客  

ITDragon opreate loginOut  

用户退出系统

在需要打印日志的地方添加切入点即可。切入点函数名尽量见名知意。这样切面函数才能通用。

发布评论 0条评论)

  • Refresh code

还木有评论哦,快来抢沙发吧~