Java web项目创建笔记16 之《添加AOP支持》

一、开启spring的aop功能
开启注解切面

applicationContext.xml添加aop命名空间,并添加:

<!-- 强制CGLIB代理 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>

二、自定义注解
1、建立包com.study.base.annotation
2、新增TimeCount.java

package com.study.base.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * com.study.base.annotation 时间统计注解
 * 在需要时间统计的方法上添加该注解,并提供时间统计handler类
 * 默认时间统计handler类为DefaultTimeCountHandler
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface TimeCount {
	String value() default "com.study.base.component.DefaultTimeCountHandler";
}

三、定义注解处理类
1、建立包com.study.base.component
2、新增DefaultTimeCountHandler.java

package com.study.base.component;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component("com.study.base.component.DefaultTimeCountHandler")
public class DefaultTimeCountHandler {

	private static Logger logger = LoggerFactory.getLogger(DefaultTimeCountHandler.class);
	
	public long start() {
		logger.info("DefaultTimeCountHandler start");
		return System.currentTimeMillis();
	}
	
	public long end() {
		logger.info("DefaultTimeCountHandler end");
		return System.currentTimeMillis();
	}
	
}

四、自定义切面
1、新增CustomTimeAdvice.java

package com.study.base.component;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.study.base.annotation.TimeCount;
import com.study.base.util.ApplicationContextHolder;

/**
 * 自定义切面
 * @author User
 *
 */
@Aspect //切面声明
@Component //组件声明
@Order(1) //切面执行顺序
public class CustomTimeAdvice {

	private static Logger logger = LoggerFactory.getLogger(CustomTimeAdvice.class);
	
	/**
	 * 切入点为添加了@TimeCount注解的方法
	 */
	@Pointcut(value = "@annotation(com.study.base.annotation.TimeCount)")
	public void pointCut() {
		
	}
	
	/**
	 * @param point 被切面方法相关属性
	 * @param timeCount 注解类对象
	 */
	@Around(value = "pointCut() && @annotation(timeCount)")
	public Object timeAround(ProceedingJoinPoint point, TimeCount timeCount) {
		//获取被切面方法的方法签名
		org.aspectj.lang.Signature funSignature = point.getSignature();
		//返回值的类型
		Class returnType = ((MethodSignature) funSignature).getReturnType();
		//入参
		Object[] objects = point.getArgs();
		
		logger.info("被切面方法名: {}", funSignature.getName());
		logger.info("返回值类型: {}", returnType.getName());
		logger.info("入参: {}", objects);
		
		//业务方法返回值
		Object respBean = null;
		//签名处理类
		DefaultTimeCountHandler defaultTimeCountHandler = null;
		//开始时间
		long start = 0;
		//结束时间
		long end = 0;
		
		try {
			//从spring上下文中获取签名操作对象
			defaultTimeCountHandler = (DefaultTimeCountHandler) ApplicationContextHolder.getBean(timeCount.value());
			
			//===================================前置处理================================
			start = defaultTimeCountHandler.start();
			logger.info("方法开始时间: {}", start);
			
			//===================================原请求处理================================
			try {
				respBean = point.proceed();
			} catch (Throwable throwable) {
				logger.error(throwable.getMessage(), throwable);
			}
			
			//===================================后置处理================================
			end = defaultTimeCountHandler.end();
			logger.info("方法结束时间: {}", end);
			
		} catch (Throwable e) {
			logger.error(e.getMessage(), e);
			
		} finally {
			//===================================收尾处理================================
			logger.info("方法消耗时间: {}", end - start);
		}
		
		return respBean;
	}
}

五、添加注解并测试
注意:注解要加在public的方法上,如果原来Controller里方法是private要改成public。因为aop切不进private的方法。

@RequestMapping("hello")
@TimeCount
public String hello() {
	log.info("hello in...");
	log.info("hello out...");
	return "hello";
}

测试方法:

@Test
public void testhello() {
	testController.hello();
}

测试日志:

2019-08-17 11:01:08.170 [] [] [] [] INFO  [main] com.study.base.component.CustomTimeAdvice [49]:被切面方法名: hello
2019-08-17 11:01:08.173 [] [] [] [] INFO  [main] com.study.base.component.CustomTimeAdvice [50]:返回值类型: java.lang.String
2019-08-17 11:01:08.173 [] [] [] [] INFO  [main] com.study.base.component.CustomTimeAdvice [51]:入参: {}
2019-08-17 11:01:08.173 [] [] [] [] INFO  [main] com.study.base.component.DefaultTimeCountHandler [13]:DefaultTimeCountHandler start
2019-08-17 11:01:08.173 [] [] [] [] INFO  [main] com.study.base.component.CustomTimeAdvice [68]:方法开始时间: 1566010868173
2019-08-17 11:01:08.190 [] [] [] [] INFO  [main] com.study.base.component.DefaultTimeCountHandler [18]:DefaultTimeCountHandler end
2019-08-17 11:01:08.190 [] [] [] [] INFO  [main] com.study.base.component.CustomTimeAdvice [79]:方法结束时间: 1566010868190
2019-08-17 11:01:08.191 [] [] [] [] INFO  [main] com.study.base.component.CustomTimeAdvice [86]:方法消耗时间: 17

六、其他
注:最新代码上传至https://github.com/csj50/webapp2.git
参考资料:
https://my.oschina.net/u/3217171/blog/3066776/
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值