1.应用的场景
- 对部分函数的调用进行日志记录,用于观察特定问题在运行过程中的函数调用情况
- 监控部分重要函数,若抛出指定的异常,需要以短信或邮件方式通知相关人员
- 监控部分重要函数的执行时间,更灵活植入和取消
- 接口报文的参数验证
基本的Demo代码
切面类
package com.wei.controller.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;
/**
* 切面
*
*/
@Component
public class AspectShow {
public void doAfter(JoinPoint jp) {
System.out.println("======>>>>>>Ending method:<<<<<<<====== "
+ jp.getTarget().getClass().getName() + "."
+ jp.getSignature().getName());
}
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
long time = System.currentTimeMillis();
Object retVal = pjp.proceed();
time = System.currentTimeMillis() - time;
System.out.println("--------->>process time: " + time + " ms");
return retVal;
}
public void doBefore(JoinPoint jp) {
System.out.println("======>>>>>>Begin method:<<<<<<<====== "
+ jp.getTarget().getClass().getName() + "."
+ jp.getSignature().getName());
}
public void doThrowing(JoinPoint jp, Throwable ex) {
System.out.println("======>>>>>>method Throwable<<<<<<<======" + jp.getTarget().getClass().getName()
+ "." + jp.getSignature().getName() + " throw exception");
System.out.println("======>>>>>>"+ex.getMessage()+"<<<<<<<======");
}
}
package com.wei.controller.aop;
/**
* AopServiceShow
*/
public interface AopServiceShow {
public void dance(String _msg);
public void singe();
}
package com.wei.controller.aop;
import org.springframework.stereotype.Component;
/**
*AopServiceShowImpl
*/
@Component
public class AopServiceShowImpl implements AopServiceShow {
public void singe() {
System.out.println("======>>>>>>AopServiceShowImpl.singe()");
}
public void dance(String _msg) {
System.out.println("======>>>>>>AopServiceShowImpl.dance()-->"+_msg);
}
}
异常service
package com.wei.controller.aop;
import org.springframework.stereotype.Service;
/**
* BServiceImpl
*/
@Service
public class AopServiceImpl {
public void run(String _msg, int _type) {
System.out.println("======>>>>>>AopServiceImpl.run()");
System.out.println("======>>>>>>AopServiceImpl.run()-->(msg:"+_msg+" type:"+_type+")");
if(_type == 1)
throw new IllegalArgumentException("======>>>>>>测试异常");
}
public void walk() {
System.out.println("======>>>>>>AopServiceImpl.walk()");
}
}
junit测试类
package com.wei.dao;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.wei.controller.aop.AopServiceImpl;
import com.wei.controller.aop.AopServiceShow;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/spring-context.xml")
public class AopServiceTestCase {
private Logger logger=LoggerFactory.getLogger(this.getClass());
@Autowired
private AopServiceShow aopServiceShowImpl;
@Autowired
private AopServiceImpl aopServiceImpl;
/**
* 测试正常调用
*/
@Test
public void testCall() {
System.out.println("------->start-------");
aopServiceShowImpl.dance("JUnit Dance");
aopServiceShowImpl.singe();
aopServiceImpl.walk();
aopServiceImpl.run("JUnit Run", 0);
System.out.println("------->end-------");
}
/**
* 测试After-Throwing
*/
@Test
public void testThrow() {
System.out.println("------->start-------");
try {
aopServiceImpl.run("JUnit Run", 10001);
} catch (IllegalArgumentException e) {
}
System.out.println("------->end-------");
}
}
AOP配置
<aop:config proxy-target-class="true">
<aop:aspect ref="aspectShow">
<aop:pointcut id="aopService" expression="execution(* com.wei.controller..*(..))"/>
<aop:before pointcut-ref="aopService" method="doBefore"/>
<aop:after pointcut-ref="aopService" method="doAfter"/>
<aop:around pointcut-ref="aopService" method="doAround"/>
<aop:after-throwing pointcut-ref="aopService" method="doThrowing" throwing="ex"/>
</aop:aspect>
</aop:config>
2.报文验证
2.1声明一个注解,在需要验证呢过报文的地方加上注解
package com.wei.service.validate;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessRequired {
}
在实现的方法上加注解,例如:
@Override
@AccessRequired
public CommonResonse<User> select(UserVo userVo) {}
切面bean如下实现MethodInterceptor接口,大家可以看下这个接口的实现其实就是通知
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import com.pingan.toa.asset.common.enums.MessageEnums;
import com.pingan.toa.asset.common.enums.ResponseTypeEnums;
import com.pingan.toa.asset.model.response.CommonResponse;
@Component
public class ValidateParamMethedIntercepter implements MethodInterceptor {
private static final Validator validator;
static {
ValidatorFactory vf = Validation.buildDefaultValidatorFactory();
validator = vf.getValidator();
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Object[] args = invocation.getArguments();
if (args != null && args.length > 0) {
List<string> errors = violation(args[0]);
if (errors.size() > 0) {
CommonResponse<object> commonResonse = new CommonResponse</object><object>();
commonResonse.setErrorMsg(StringUtils.join(errors, ", "));
commonResonse.setErrorCode(MessageEnums.ERROR00.getCode());
commonResonse.setStatus(ResponseTypeEnums.FAILED);
return commonResonse;
}
}
return invocation.proceed();
}
public static List<string> violation(Object object) {
List<string> msgs = new ArrayList<string>();
Set<ConstraintViolation<object>> set = validator.validate(object);
if (set != null && !set.isEmpty()) {
for (ConstraintViolation</object><object> cvo : set) {
msgs.add(cvo.getMessage());
}
}
return msgs;
}
}
2.2 这个类里面又返回的Object,就是返回前端的对象,代码里是我自己用的大家可以换掉
表达式加上注解,只匹配加上注解的,可以看出其实这个注解只是一个标识的作用
<aop:pointcut id="aopService"
expression="execution(@com.wei.service.validate.AccessRequired* com.wei.controller..*(..))" />