Spring AOP的实现记录操作日志
适用场景:
记录接口方法的执行情况,记录相关状态到日志中。
注解类:LogTag.java
package com.lichmama.spring.annotation; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogTag {
String value() default "";
}
@Target (使用)注解的目标类型:
CONSTRUCTOR 构造方法声明
FIELD 字段声明(包括枚举常量)
LOCAL_VARIABLE 局部变量声明
METHOD 方法声明
PACKAGE 包声明
PARAMETER 参数声明
TYPE 类、接口(包括注释类型)或枚举声明
@Retention 注解的生命周期(默认CLASS):
CLASS 编译器将把注释记录在类文件中,但在运行时VM 不需要保留注释。
RUNTIME 编译器将把注释记录在类文件中,在运行时VM 将保留注释,因此可以反射性地读取。
SOURCE 编译器要丢弃的注释。
@Documented 标记生成javadoc
切面类:ServiceAspect.java
package com.lichmama.spring.aop; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component; import com.lichmama.spring.annotation.LogTag; @Aspect
@Component
public class ServiceAspect { private Log log = LogFactory.getLog(getClass()); @Pointcut("@annotation(com.lichmama.spring.annotation.LogTag)")
private void pointcut() {
} @Before("pointcut()")
public void doBefore(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String methodName = signature.getMethod().getName();
String logTag = ((LogTag) signature.getMethod().getAnnotation(LogTag.class)).value();
log.info("before calling " + methodName + ", value: " + logTag);
}
}
@Pointcut("@annotation(com.lichmama.spring.annotation.LogTag)") 标注一个切入点,执行任意带有LogTag注解的方法触发。
业务实现:UserServiceImpl.java
package com.lichmama.spring.service.impl; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import com.lichmama.spring.annotation.LogTag;
import com.lichmama.spring.dao.IUserDAO;
import com.lichmama.spring.entity.User;
import com.lichmama.spring.service.IUserService; @Service
public class UserServiceImpl implements IUserService { @Autowired
private IUserDAO userDAO; @LogTag
@Override
public User getUserById(int id) {
return userDAO.getUserById(id);
} @LogTag
@Override
public void saveUser(User user) {
userDAO.saveUser(user);
} @LogTag
@Override
public void updateUser(User user) {
userDAO.updateUser(user);
} @LogTag("dangerous operation")
@Override
public void deleteUser(int id) {
userDAO.deleteUser(id);
}
}
spring配置文件:applicationContext.xml
<?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-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"> <context:component-scan base-package="com.lichmama.spring.aop" />
<context:component-scan base-package="com.lichmama.spring.dao" />
<context:component-scan base-package="com.lichmama.spring.service" /> <aop:aspectj-autoproxy proxy-target-class="true" />
</beans>
写个测试:
public class TestCase {
private Log log = LogFactory.getLog(getClass());
private ApplicationContext ctx;
@Before
public void initSpringContext() {
ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
}
@Test
public void testAOP() {
IUserService userService = ctx.getBean(IUserService.class);
userService.saveUser(new User(1, "lichmama"));
userService.saveUser(new User(2, "james"));
userService.saveUser(new User(3, "dwyane"));
userService.updateUser(new User(2, "bill"));
User user = userService.getUserById(2);
log.info(user.toString());
userService.deleteUser(1);
}
}
16:06:22,517 INFO ServiceAspect:29 - before calling saveUser, value:
16:06:22,549 INFO ServiceAspect:29 - before calling saveUser, value:
16:06:22,549 INFO ServiceAspect:29 - before calling saveUser, value:
16:06:22,550 INFO ServiceAspect:29 - before calling updateUser, value:
16:06:22,551 INFO ServiceAspect:29 - before calling getUserById, value:
16:06:22,551 INFO TestSpring:35 - id: 2, name: bill
16:06:22,551 INFO ServiceAspect:29 - before calling deleteUser, value: dangerous operation
Spring AOP的实现记录操作日志的更多相关文章
- 我使用Spring AOP实现了用户操作日志功能
我使用Spring AOP实现了用户操作日志功能 今天答辩完了,复盘了一下系统,发现还是有一些东西值得拿出来和大家分享一下. 需求分析 系统需要对用户的操作进行记录,方便未来溯源 首先想到的就是在每个 ...
- spring aop切面编程实现操作日志步骤
1.在spring-mvc.xml配置文件中打开切面开关: <aop:aspectj-autoproxy proxy-target-class="true"/> 注意: ...
- 使用SpringBoot AOP 记录操作日志、异常日志
平时我们在做项目时经常需要对一些重要功能操作记录日志,方便以后跟踪是谁在操作此功能:我们在操作某些功能时也有可能会发生异常,但是每次发生异常要定位原因我们都要到服务器去查询日志才能找到,而且也不能对发 ...
- 运用Spring Aop,一个注解实现日志记录
运用Spring Aop,一个注解实现日志记录 1. 介绍 我们都知道Spring框架的两大特性分别是 IOC (控制反转)和 AOP (面向切面),这个是每一个Spring学习视频里面一开始都会提到 ...
- spring AOP自定义注解方式实现日志管理
今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接开始!!! 关于配置我还是的再说一遍. 在appli ...
- Appfuse:记录操作日志
appfuse的数据维护操作都发生在***form页面,与之对应的是***FormController,在Controller中处理数据的操作是onSubmit方法,既然所有的操作都通过onSubmi ...
- MVC 记录操作日志与过滤特殊字符
最近进行的MVC系统需要用到记录操作日志和过滤特殊字符的功能,如果每个action中都调用记录日志的方法就太麻烦了,所以根据需要结合mvc的过滤机制 写了个特殊字符验证与记录操作日志的公用类: pub ...
- Tomcat会话超时时怎样记录操作日志,满足安全审计要求
众所周知.在实际的Web应用程序中,会话管理一般都採用Web容器会话管理功能. 使用Tomcat做Webserver也是如此,并且从安全的角度考虑,尽量避免去更改和干预Web容器的会话管理功能. To ...
- Spring aop 记录操作日志 Aspect
前几天做系统日志记录的功能,一个操作调一次记录方法,每次还得去收集参数等等,太尼玛烦了.在程序员的世界里,当你的一个功能重复出现多次,就应该想想肯定有更简单的实现方法.于是果断搜索各种资料,终于搞定了 ...
随机推荐
- FFmpeg参考资料合集(会一直更新)
让你的软件飞起来:RGB转为YUV 朋友曾经给我推荐了一个有关代码优化的pdf文档<让你的软件飞起来>,看完之后,感受颇深.为了推广其,同时也为了自己加深印象,故将其总结为word 文档. ...
- Postgresql 常用操作
表所有者一括变更 select 'alter table public.'|| tablename ||' owner to appuser;' from pg_tables where tableo ...
- java实现mysql数据备份
/** * @param hostIP ip地址,可以是本机也可以是远程 * @param userName 数据库的用户名 * @param password 数据库的密码 * @param sav ...
- Flask介绍及简单使用
Flask Django是一个大而全的框架,Flask是一个轻量级的框架. 区别: Django内部集成了大量的组件:请求处理是逐一封装和传递: Flask本身并没有太多的功能,但是第三方组件非常丰富 ...
- gRPC应用C++
1. gRPC简述 RPC,远程方法调用,就是像调用本地方法一样调用远程方法. gRPC是Google实现的一种RPC框架,基于HTTP/2标准设计,带来诸如双向流.流控.头部压缩.单 TCP 连接 ...
- SpringCloud2.0 Ribbon 服务发现 基础教程(四)
1.启动[服务中心]集群,即 Eureka Server 参考 SpringCloud2.0 Eureka Server 服务中心 基础教程(二) 2.启动[服务提供者]集群,即 Eureka Cli ...
- Mysql InnoDB行锁不使用索引锁表的时候会锁整张表
原文:http://www.thinkphp.cn/topic/41577.html 如果使用针对InnoDB的表使用行锁,被锁定字段不是主键,也没有针对它建立索引的话.行锁锁定的也是整张表.锁整张表 ...
- 哈希长度拓展攻击之De1CTF - SSRF Me
题目考查:python代码审计.hash长度拓展攻击 0x01 题目源码: #! /usr/bin/env python #encoding=utf-8 from flask import Flask ...
- X.509
参考:https://baike.baidu.com/item/X.509/2817050?fr=aladdin 标题:X.509 百度百科 在密码术中,X.509是定义公用密钥证书格式的标准. X ...
- metasploit 一款开源的渗透测试框架
渗透神器漏洞利用框架metasploit from: https://zhuanlan.zhihu.com/p/30743401 metasploit是一款开源的渗透测试框架软件也是一个逐步发展与成熟 ...