spring AOP做日志操作

AOP的基本概念
AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子。

一 AOP的基本概念

(1)Aspect(切面):通常是一个类,里面可以定义切入点和通知

(2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用

(3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around

(4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式

(5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类
JoinPoint的基本方法
AspectJ中的切入点匹配的执行点称作连接的(Join Point),在通知方法中可以声明一个JoinPoint类型的参数。通过JoinPoint可以访问连接点的细节。下面简要介绍JponPoint的方法:

1.java.lang.Object[] getArgs():获取连接点方法运行时的入参列表; 
2.Signature getSignature() :获取连接点的方法签名对象; 
3.java.lang.Object getTarget() :获取连接点所在的目标对象; 
4.java.lang.Object getThis() :获取代理对象本身; 

ProceedingJoinPoint继承JoinPoint子接口,它新增了两个用于执行连接点方法的方法: 

5.java.lang.Object proceed() throws  java.lang.Throwable:通过反射执行目标对象的连接点处的方 法; 
6.java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通过反射执行目标对象连接点处的方法,不过使用新的参数替换原来的参数。
代码
注解
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperateRecordAnnotation {

    public String description() default "";

    public String operateType() default "";
}

AOP方法
@Component
public class OperateRecordAspect {

    private Logger logger= LoggerFactory.getLogger(OperateRecordAspect.class);

    @Autowired
    private OperateRecordService operateRecordService;
    @Autowired
    private UserService userService;

    public void doAfter(JoinPoint joinpoint) {
        HttpServletRequest request =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String username=null;
        String authorization = request.getHeader("Authorization");
        OperateRecord operateRecord=new OperateRecord();
        User userInfo = userService.getUserInfo(authorization);
        if (userInfo !=null){
            username=userInfo.getUsername();
        }
        //得到的类名
        String className = joinpoint.getTarget().getClass().getName();
        //得到的方法名
        String methodName = joinpoint.getSignature().getName();
        Object[] args = joinpoint.getArgs();
        if (args.length>0){
            operateRecord.setOperParams(JSONObject.toJSONString(args));
        }
        try {
            Class targetClass=Class.forName(className);
            Method[] methods = targetClass.getMethods();
            if (methods.length ==0) {
                logger.info(className+" don't any methods");
                return;
            }
            for (int i=0; i<methods.length;i++){
                if (methods[i].getName().equals(methodName)){
                    Method method = methods[i];
                    OperateRecordAnnotation annotation = method.getAnnotation(OperateRecordAnnotation.class);
                    Parameter[] parameters = method.getParameters();
                    operateRecord.setDescription(annotation.description());
                    operateRecord.setOperType(annotation.operateType());
                    operateRecord.setOperMethod(className+"."+method.getName());
                    operateRecord.setOperator(username);
                    operateRecordService.addOperateRecord(operateRecord);
                }
            }
        } catch (ClassNotFoundException e) {
            logger.error("创建反射失败,失败原因是:"+e.getMessage());
        } catch (Exception e) {
            logger.error("添加日志失败,失败原因是:"+e.getMessage());
        }
    }

}
AOP配置信息
 <!--配置日志-->
 <!--其中的execution方法自己可以学-->
    <aop:config>
        <aop:pointcut id="operateRecord" expression="execution()"/>
        <aop:pointcut id="checkconf" expression="execution(*)"/>
        <aop:aspect ref="operateRecordAspect">
            <aop:after method="doAfter" pointcut-ref="operateRecord"/>
            <aop:after method="doAfter" pointcut-ref="checkconf"/>
        </aop:aspect>
    </aop:config>
方法
 /**
     * @param order
     * @return
     */
    @OperateRecordAnnotation(description = "异常订单通过",operateType = "2")
    @RequestMapping(value = "/unsafe/confirm",method = RequestMethod.POST)
    public String unsafeConfirm(@RequestBody Order order) {
       <!--业务-->
    }

猜你喜欢

转载自blog.csdn.net/qq_25484147/article/details/80639165