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
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步