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

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

<!-- 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>

 

自定义注解标签:web

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

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

 

定义切面类:spring

@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("&&&&&&&&&&&&&&&&&&&&&&&&&");
	}

}

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

 

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

<aop:aspectj-autoproxy/>

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

<aop:aspectj-autoproxy/>

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

<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层的扫描:ide

<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的拦截;spa

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

<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

日志均打印代表测试成功

相关文章
相关标签/搜索