java利用AOP 实现操作日志记录(一)

让人想犯罪 __ 提交于 2019-11-27 03:41:07

 除springMvc外需要引入@Aspect注解依赖:

<!-- AOP -->
		<!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
		<dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.6.11</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.11</version>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.1_3</version>
        </dependency>

 

自定义注解标签:

@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface logAnnotation {
	/**
	 * @param 模块名字
	 */
	String modelName() default "";

	/**
	 * @param 操作类型
	 */
	String option();
}

 

定义切面类:

@Aspect
// 该注解标示该类为切面类
@Component
// 注入依赖
public class OperationLogAspect {

	// 标注该方法体为后置通知,当目标方法执行成功后执行该方法体
	@AfterReturning("within(com.ustcinfo.fccos.terminal.web..*) && @annotation(rl)")
	public void addLogSuccess(JoinPoint jp, logAnnotation rl) {
		System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&");
		Object[] parames = jp.getArgs();// 获取目标方法体参数
		String className = jp.getTarget().getClass().toString();// 获取目标类名
		className = className.substring(className.indexOf("com"));
		String signature = jp.getSignature().toString();// 获取目标方法签名
		String methodName = signature.substring(signature.lastIndexOf(".") + 1, signature.indexOf("("));
		System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&");
	}

}

切面类可根据业务要求自行添加逻辑

 

在spring的容器xml中添加配置:

<aop:aspectj-autoproxy/>

此处有个注意点:网上说利用AOP无法拦截controller层,经测试,需要在web mvc中同时添加注解

<aop:aspectj-autoproxy/>

 因为为了启用事务,在spring的容器扫描中排除了controller层:

<context:annotation-config />
	<!-- 对应的是系统级别的配置,作用范围是系统上下文 -->
	<context:component-scan base-package="com.ustcinfo.fccos.terminal.web">
		<context:exclude-filter type="annotation"
			expression="org.springframework.stereotype.Controller" />
	</context:component-scan>

 

在Mvc、中只启用了controller层的扫描:

<mvc:annotation-driven />
	<!-- 对应的是 controller 级别的配置,作用范围是控制层上下文。初始话转发内容 -->
	<context:component-scan base-package="com.ustcinfo.fccos.terminal.web.controller">
		<context:include-filter type="annotation"	expression="org.springframework.stereotype.Controller" />
	</context:component-scan>

 

因此,只需要在 spring的父容器,mvc子容器中均添加

<aop:aspectj-autoproxy/>

 即可实现controller的拦截;

网上还有另外一种说法,就是配置文件改成

<aop:aspectj-autoproxy proxy-target-class="true"/>让spring使用cglib的代理方式

但是cglib的时候需要有默认的构造方法,class不能为final的,因此在项目中引入了mybatis或者其他的无默认构造的方法时候就会报错:

java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy33

,经测试,只需要在 spring的父容器,mvc子容器中均添加

<aop:aspectj-autoproxy/>

 即可实现controller以及其他业务的切面,网上说spring会自动在JDK动态代理和CGLIB之间转换,但是没做验证

查看aop是否生效

 

切面注解controller

	@RequestMapping(value = "getInstallerInfos")
	@ResponseBody
	@logAnnotation(option = "查询装维_controller")
	public Json getInstallerInfos(String installer) {

 

	@Override
	@logAnnotation(option = "查询装维_service")
	public Json getInstallerInfos(String installer) {

切面注解service

日志均打印表明测试成功

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!